mirror of
https://github.com/WerWolv/ImHex.git
synced 2026-04-02 05:27:41 -05:00
refactor: Get rid of this->m_
This commit is contained in:
@@ -113,13 +113,13 @@ namespace hex {
|
||||
float xStep = (size.x * 0.95F) / 0xFF;
|
||||
float yStep = (size.y * 0.95F) / 0xFF;
|
||||
|
||||
if (!this->m_processing)
|
||||
for (size_t i = 0; i < (this->m_buffer.empty() ? 0 : this->m_buffer.size() - 1); i++) {
|
||||
auto x = this->m_buffer[i] * xStep;
|
||||
auto y = this->m_buffer[i + 1] * yStep;
|
||||
if (!m_processing)
|
||||
for (size_t i = 0; i < (m_buffer.empty() ? 0 : m_buffer.size() - 1); i++) {
|
||||
auto x = m_buffer[i] * xStep;
|
||||
auto y = m_buffer[i + 1] * yStep;
|
||||
|
||||
auto color = ImLerp(ImColor(0xFF, 0x6D, 0x01).Value, ImColor(0x01, 0x93, 0xFF).Value, float(i) / this->m_buffer.size()) + ImVec4(this->m_glowBuffer[i], this->m_glowBuffer[i], this->m_glowBuffer[i], 0.0F);
|
||||
color.w = this->m_opacity;
|
||||
auto color = ImLerp(ImColor(0xFF, 0x6D, 0x01).Value, ImColor(0x01, 0x93, 0xFF).Value, float(i) / m_buffer.size()) + ImVec4(m_glowBuffer[i], m_glowBuffer[i], m_glowBuffer[i], 0.0F);
|
||||
color.w = m_opacity;
|
||||
|
||||
auto pos = ImGui::GetWindowPos() + ImVec2(size.x * 0.025F, size.y * 0.025F) + ImVec2(x, y);
|
||||
drawList->AddRectFilled(pos, pos + ImVec2(xStep, yStep), ImColor(color));
|
||||
@@ -130,36 +130,36 @@ namespace hex {
|
||||
}
|
||||
|
||||
void process(prv::Provider *provider, u64 address, size_t size) {
|
||||
this->m_processing = true;
|
||||
this->m_buffer = impl::getSampleSelection(provider, address, size, this->m_sampleSize);
|
||||
m_processing = true;
|
||||
m_buffer = impl::getSampleSelection(provider, address, size, m_sampleSize);
|
||||
processImpl();
|
||||
this->m_processing = false;
|
||||
m_processing = false;
|
||||
}
|
||||
|
||||
void process(const std::vector<u8> &buffer) {
|
||||
this->m_processing = true;
|
||||
this->m_buffer = impl::getSampleSelection(buffer, this->m_sampleSize);
|
||||
m_processing = true;
|
||||
m_buffer = impl::getSampleSelection(buffer, m_sampleSize);
|
||||
processImpl();
|
||||
this->m_processing = false;
|
||||
m_processing = false;
|
||||
}
|
||||
|
||||
void reset(u64 size) {
|
||||
this->m_processing = true;
|
||||
this->m_buffer.clear();
|
||||
this->m_buffer.reserve(this->m_sampleSize);
|
||||
this->m_byteCount = 0;
|
||||
this->m_fileSize = size;
|
||||
m_processing = true;
|
||||
m_buffer.clear();
|
||||
m_buffer.reserve(m_sampleSize);
|
||||
m_byteCount = 0;
|
||||
m_fileSize = size;
|
||||
}
|
||||
|
||||
void update(u8 byte) {
|
||||
// Check if there is some space left
|
||||
if (this->m_byteCount < this->m_fileSize) {
|
||||
if ((this->m_byteCount % u64(std::ceil(double(this->m_fileSize) / double(this->m_sampleSize)))) == 0)
|
||||
this->m_buffer.push_back(byte);
|
||||
++this->m_byteCount;
|
||||
if (this->m_byteCount == this->m_fileSize) {
|
||||
if (m_byteCount < m_fileSize) {
|
||||
if ((m_byteCount % u64(std::ceil(double(m_fileSize) / double(m_sampleSize)))) == 0)
|
||||
m_buffer.push_back(byte);
|
||||
++m_byteCount;
|
||||
if (m_byteCount == m_fileSize) {
|
||||
processImpl();
|
||||
this->m_processing = false;
|
||||
m_processing = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -167,20 +167,20 @@ namespace hex {
|
||||
|
||||
private:
|
||||
void processImpl() {
|
||||
this->m_glowBuffer.resize(this->m_buffer.size());
|
||||
m_glowBuffer.resize(m_buffer.size());
|
||||
|
||||
std::map<u64, size_t> heatMap;
|
||||
for (size_t i = 0; i < (this->m_buffer.empty() ? 0 : this->m_buffer.size() - 1); i++) {
|
||||
auto count = ++heatMap[this->m_buffer[i] << 8 | heatMap[i + 1]];
|
||||
for (size_t i = 0; i < (m_buffer.empty() ? 0 : m_buffer.size() - 1); i++) {
|
||||
auto count = ++heatMap[m_buffer[i] << 8 | heatMap[i + 1]];
|
||||
|
||||
this->m_highestCount = std::max(this->m_highestCount, count);
|
||||
m_highestCount = std::max(m_highestCount, count);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < (this->m_buffer.empty() ? 0 : this->m_buffer.size() - 1); i++) {
|
||||
this->m_glowBuffer[i] = std::min<float>(0.2F + (float(heatMap[this->m_buffer[i] << 8 | this->m_buffer[i + 1]]) / float(this->m_highestCount / 1000)), 1.0F);
|
||||
for (size_t i = 0; i < (m_buffer.empty() ? 0 : m_buffer.size() - 1); i++) {
|
||||
m_glowBuffer[i] = std::min<float>(0.2F + (float(heatMap[m_buffer[i] << 8 | m_buffer[i + 1]]) / float(m_highestCount / 1000)), 1.0F);
|
||||
}
|
||||
|
||||
this->m_opacity = (log10(float(this->m_sampleSize)) / log10(float(m_highestCount))) / 10.0F;
|
||||
m_opacity = (log10(float(m_sampleSize)) / log10(float(m_highestCount))) / 10.0F;
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -209,13 +209,13 @@ namespace hex {
|
||||
float xStep = (size.x * 0.95F) / 0xFF;
|
||||
float yStep = (size.y * 0.95F) / 0xFF;
|
||||
|
||||
if (!this->m_processing)
|
||||
for (size_t i = 0; i < (this->m_buffer.empty() ? 0 : this->m_buffer.size()); i++) {
|
||||
auto x = this->m_buffer[i] * xStep;
|
||||
auto y = yStep * ((float(i) / this->m_buffer.size()) * 0xFF);
|
||||
if (!m_processing)
|
||||
for (size_t i = 0; i < (m_buffer.empty() ? 0 : m_buffer.size()); i++) {
|
||||
auto x = m_buffer[i] * xStep;
|
||||
auto y = yStep * ((float(i) / m_buffer.size()) * 0xFF);
|
||||
|
||||
auto color = ImLerp(ImColor(0xFF, 0x6D, 0x01).Value, ImColor(0x01, 0x93, 0xFF).Value, float(i) / this->m_buffer.size()) + ImVec4(this->m_glowBuffer[i], this->m_glowBuffer[i], this->m_glowBuffer[i], 0.0F);
|
||||
color.w = this->m_opacity;
|
||||
auto color = ImLerp(ImColor(0xFF, 0x6D, 0x01).Value, ImColor(0x01, 0x93, 0xFF).Value, float(i) / m_buffer.size()) + ImVec4(m_glowBuffer[i], m_glowBuffer[i], m_glowBuffer[i], 0.0F);
|
||||
color.w = m_opacity;
|
||||
|
||||
auto pos = ImGui::GetWindowPos() + ImVec2(size.x * 0.025F, size.y * 0.025F) + ImVec2(x, y);
|
||||
drawList->AddRectFilled(pos, pos + ImVec2(xStep, yStep), ImColor(color));
|
||||
@@ -226,56 +226,56 @@ namespace hex {
|
||||
}
|
||||
|
||||
void process(prv::Provider *provider, u64 address, size_t size) {
|
||||
this->m_processing = true;
|
||||
this->m_buffer = impl::getSampleSelection(provider, address, size, this->m_sampleSize);
|
||||
m_processing = true;
|
||||
m_buffer = impl::getSampleSelection(provider, address, size, m_sampleSize);
|
||||
processImpl();
|
||||
this->m_processing = false;
|
||||
m_processing = false;
|
||||
}
|
||||
|
||||
void process(const std::vector<u8> &buffer) {
|
||||
this->m_processing = true;
|
||||
this->m_buffer = impl::getSampleSelection(buffer, this->m_sampleSize);
|
||||
m_processing = true;
|
||||
m_buffer = impl::getSampleSelection(buffer, m_sampleSize);
|
||||
processImpl();
|
||||
this->m_processing = false;
|
||||
m_processing = false;
|
||||
}
|
||||
|
||||
void reset(u64 size) {
|
||||
this->m_processing = true;
|
||||
this->m_buffer.clear();
|
||||
this->m_buffer.reserve(this->m_sampleSize);
|
||||
this->m_byteCount = 0;
|
||||
this->m_fileSize = size;
|
||||
m_processing = true;
|
||||
m_buffer.clear();
|
||||
m_buffer.reserve(m_sampleSize);
|
||||
m_byteCount = 0;
|
||||
m_fileSize = size;
|
||||
}
|
||||
|
||||
void update(u8 byte) {
|
||||
// Check if there is some space left
|
||||
if (this->m_byteCount < this->m_fileSize) {
|
||||
if ((this->m_byteCount % u64(std::ceil(double(this->m_fileSize) / double(this->m_sampleSize)))) == 0)
|
||||
this->m_buffer.push_back(byte);
|
||||
++this->m_byteCount;
|
||||
if (this->m_byteCount == this->m_fileSize) {
|
||||
if (m_byteCount < m_fileSize) {
|
||||
if ((m_byteCount % u64(std::ceil(double(m_fileSize) / double(m_sampleSize)))) == 0)
|
||||
m_buffer.push_back(byte);
|
||||
++m_byteCount;
|
||||
if (m_byteCount == m_fileSize) {
|
||||
processImpl();
|
||||
this->m_processing = false;
|
||||
m_processing = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void processImpl() {
|
||||
this->m_glowBuffer.resize(this->m_buffer.size());
|
||||
m_glowBuffer.resize(m_buffer.size());
|
||||
|
||||
std::map<u64, size_t> heatMap;
|
||||
for (size_t i = 0; i < (this->m_buffer.empty() ? 0 : this->m_buffer.size() - 1); i++) {
|
||||
auto count = ++heatMap[this->m_buffer[i] << 8 | heatMap[i + 1]];
|
||||
for (size_t i = 0; i < (m_buffer.empty() ? 0 : m_buffer.size() - 1); i++) {
|
||||
auto count = ++heatMap[m_buffer[i] << 8 | heatMap[i + 1]];
|
||||
|
||||
this->m_highestCount = std::max(this->m_highestCount, count);
|
||||
m_highestCount = std::max(m_highestCount, count);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < (this->m_buffer.empty() ? 0 : this->m_buffer.size() - 1); i++) {
|
||||
this->m_glowBuffer[i] = std::min<float>(0.2F + (float(heatMap[this->m_buffer[i] << 8 | this->m_buffer[i + 1]]) / float(this->m_highestCount / 1000)), 1.0F);
|
||||
for (size_t i = 0; i < (m_buffer.empty() ? 0 : m_buffer.size() - 1); i++) {
|
||||
m_glowBuffer[i] = std::min<float>(0.2F + (float(heatMap[m_buffer[i] << 8 | m_buffer[i + 1]]) / float(m_highestCount / 1000)), 1.0F);
|
||||
}
|
||||
|
||||
this->m_opacity = (log10(float(this->m_sampleSize)) / log10(float(m_highestCount))) / 10.0F;
|
||||
m_opacity = (log10(float(m_sampleSize)) / log10(float(m_highestCount))) / 10.0F;
|
||||
}
|
||||
private:
|
||||
size_t m_sampleSize = 0;
|
||||
@@ -298,7 +298,7 @@ namespace hex {
|
||||
|
||||
void draw(ImVec2 size, ImPlotFlags flags, bool updateHandle = false) {
|
||||
|
||||
if (!this->m_processing && ImPlot::BeginPlot("##ChunkBasedAnalysis", size, flags)) {
|
||||
if (!m_processing && ImPlot::BeginPlot("##ChunkBasedAnalysis", size, flags)) {
|
||||
ImPlot::SetupAxes("hex.builtin.common.address"_lang, "hex.builtin.view.information.entropy"_lang,
|
||||
ImPlotAxisFlags_Lock | ImPlotAxisFlags_NoHighlight | ImPlotAxisFlags_NoSideSwitch,
|
||||
ImPlotAxisFlags_Lock | ImPlotAxisFlags_NoHighlight | ImPlotAxisFlags_NoSideSwitch);
|
||||
@@ -307,31 +307,31 @@ namespace hex {
|
||||
|
||||
// Set the axis limit to [first block : last block]
|
||||
ImPlot::SetupAxesLimits(
|
||||
this->m_xBlockEntropy.empty() ? 0 : this->m_xBlockEntropy.front(),
|
||||
this->m_xBlockEntropy.empty() ? 0 : this->m_xBlockEntropy.back(),
|
||||
m_xBlockEntropy.empty() ? 0 : m_xBlockEntropy.front(),
|
||||
m_xBlockEntropy.empty() ? 0 : m_xBlockEntropy.back(),
|
||||
-0.1F,
|
||||
1.1F,
|
||||
ImGuiCond_Always);
|
||||
|
||||
// Draw the plot
|
||||
ImPlot::PlotLine("##ChunkBasedAnalysisLine", this->m_xBlockEntropy.data(), this->m_yBlockEntropySampled.data(), this->m_xBlockEntropy.size());
|
||||
ImPlot::PlotLine("##ChunkBasedAnalysisLine", m_xBlockEntropy.data(), m_yBlockEntropySampled.data(), m_xBlockEntropy.size());
|
||||
|
||||
// The parameter updateHandle is used when using the pattern language since we don't have a provider
|
||||
// but just a set of bytes, we won't be able to use the drag bar correctly.
|
||||
if (updateHandle) {
|
||||
// Set a draggable line on the plot
|
||||
if (ImPlot::DragLineX(1, &this->m_handlePosition, ImGui::GetStyleColorVec4(ImGuiCol_Text))) {
|
||||
if (ImPlot::DragLineX(1, &m_handlePosition, ImGui::GetStyleColorVec4(ImGuiCol_Text))) {
|
||||
// The line was dragged, update the position in the hex editor
|
||||
|
||||
// Clamp the value between the start/end of the region to analyze
|
||||
this->m_handlePosition = std::clamp<double>(
|
||||
this->m_handlePosition,
|
||||
this->m_startAddress,
|
||||
this->m_endAddress);
|
||||
m_handlePosition = std::clamp<double>(
|
||||
m_handlePosition,
|
||||
m_startAddress,
|
||||
m_endAddress);
|
||||
|
||||
// Compute the position inside hex editor
|
||||
u64 address = u64(std::max<double>(this->m_handlePosition, 0)) + this->m_baseAddress;
|
||||
address = std::min<u64>(address, this->m_baseAddress + this->m_fileSize - 1);
|
||||
u64 address = u64(std::max<double>(m_handlePosition, 0)) + m_baseAddress;
|
||||
address = std::min<u64>(address, m_baseAddress + m_fileSize - 1);
|
||||
ImHexApi::HexEditor::setSelection(address, 1);
|
||||
}
|
||||
}
|
||||
@@ -340,92 +340,92 @@ namespace hex {
|
||||
}
|
||||
|
||||
void process(prv::Provider *provider, u64 chunkSize, u64 startAddress, u64 endAddress) {
|
||||
this->m_processing = true;
|
||||
m_processing = true;
|
||||
|
||||
// Update attributes
|
||||
this->m_chunkSize = chunkSize;
|
||||
this->m_startAddress = startAddress;
|
||||
this->m_endAddress = endAddress;
|
||||
m_chunkSize = chunkSize;
|
||||
m_startAddress = startAddress;
|
||||
m_endAddress = endAddress;
|
||||
|
||||
this->m_baseAddress = provider->getBaseAddress();
|
||||
this->m_fileSize = provider->getSize();
|
||||
m_baseAddress = provider->getBaseAddress();
|
||||
m_fileSize = provider->getSize();
|
||||
|
||||
// Get a file reader
|
||||
auto reader = prv::ProviderReader(provider);
|
||||
std::vector<u8> bytes = reader.read(this->m_startAddress, this->m_endAddress - this->m_startAddress);
|
||||
std::vector<u8> bytes = reader.read(m_startAddress, m_endAddress - m_startAddress);
|
||||
|
||||
this->processImpl(bytes);
|
||||
|
||||
// Set the diagram handle position to the start of the plot
|
||||
this->m_handlePosition = this->m_startAddress;
|
||||
m_handlePosition = m_startAddress;
|
||||
|
||||
this->m_processing = false;
|
||||
m_processing = false;
|
||||
}
|
||||
|
||||
void process(const std::vector<u8> &buffer, u64 chunkSize) {
|
||||
this->m_processing = true;
|
||||
m_processing = true;
|
||||
|
||||
// Update attributes (use buffer size as end address)
|
||||
this->m_chunkSize = chunkSize;
|
||||
this->m_startAddress = 0;
|
||||
this->m_endAddress = buffer.size();
|
||||
m_chunkSize = chunkSize;
|
||||
m_startAddress = 0;
|
||||
m_endAddress = buffer.size();
|
||||
|
||||
this->m_baseAddress = 0;
|
||||
this->m_fileSize = buffer.size();
|
||||
m_baseAddress = 0;
|
||||
m_fileSize = buffer.size();
|
||||
|
||||
this->processImpl(buffer);
|
||||
|
||||
// Set the diagram handle position to the start of the plot
|
||||
this->m_handlePosition = this->m_startAddress;
|
||||
m_handlePosition = m_startAddress;
|
||||
|
||||
this->m_processing = false;
|
||||
m_processing = false;
|
||||
}
|
||||
|
||||
// Reset the entropy analysis
|
||||
void reset(u64 chunkSize, u64 startAddress, u64 endAddress, u64 baseAddress, u64 size) {
|
||||
this->m_processing = true;
|
||||
m_processing = true;
|
||||
|
||||
// Update attributes
|
||||
this->m_chunkSize = chunkSize;
|
||||
this->m_startAddress = startAddress;
|
||||
this->m_endAddress = endAddress;
|
||||
this->m_baseAddress = baseAddress;
|
||||
this->m_fileSize = size;
|
||||
m_chunkSize = chunkSize;
|
||||
m_startAddress = startAddress;
|
||||
m_endAddress = endAddress;
|
||||
m_baseAddress = baseAddress;
|
||||
m_fileSize = size;
|
||||
|
||||
this->m_blockValueCounts = { 0 };
|
||||
m_blockValueCounts = { 0 };
|
||||
|
||||
// Reset and resize the array
|
||||
this->m_yBlockEntropy.clear();
|
||||
m_yBlockEntropy.clear();
|
||||
|
||||
this->m_byteCount = 0;
|
||||
this->m_blockCount = 0;
|
||||
m_byteCount = 0;
|
||||
m_blockCount = 0;
|
||||
|
||||
// Set the diagram handle position to the start of the plot
|
||||
this->m_handlePosition = this->m_startAddress;
|
||||
m_handlePosition = m_startAddress;
|
||||
}
|
||||
|
||||
// Process one byte at the time
|
||||
void update(u8 byte) {
|
||||
u64 totalBlock = std::ceil((this->m_endAddress - this->m_startAddress) / this->m_chunkSize);
|
||||
u64 totalBlock = std::ceil((m_endAddress - m_startAddress) / m_chunkSize);
|
||||
|
||||
// Check if there is still some
|
||||
if (this->m_blockCount < totalBlock) {
|
||||
if (m_blockCount < totalBlock) {
|
||||
// Increment the occurrence of the current byte
|
||||
this->m_blockValueCounts[byte]++;
|
||||
m_blockValueCounts[byte]++;
|
||||
|
||||
this->m_byteCount++;
|
||||
m_byteCount++;
|
||||
// Check if we processed one complete chunk, if so compute the entropy and start analysing the next chunk
|
||||
if (((this->m_byteCount % this->m_chunkSize) == 0) || this->m_byteCount == (this->m_endAddress - this->m_startAddress)) [[unlikely]] {
|
||||
this->m_yBlockEntropy.push_back(calculateEntropy(this->m_blockValueCounts, this->m_chunkSize));
|
||||
if (((m_byteCount % m_chunkSize) == 0) || m_byteCount == (m_endAddress - m_startAddress)) [[unlikely]] {
|
||||
m_yBlockEntropy.push_back(calculateEntropy(m_blockValueCounts, m_chunkSize));
|
||||
|
||||
this->m_blockCount += 1;
|
||||
this->m_blockValueCounts = { 0 };
|
||||
m_blockCount += 1;
|
||||
m_blockValueCounts = { 0 };
|
||||
}
|
||||
|
||||
// Check if we processed the last block, if so setup the X axis part of the data
|
||||
if (this->m_blockCount == totalBlock) {
|
||||
if (m_blockCount == totalBlock) {
|
||||
processFinalize();
|
||||
this->m_processing = false;
|
||||
m_processing = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -456,72 +456,72 @@ namespace hex {
|
||||
// Return the highest entropy value among all of the blocks
|
||||
double getHighestEntropyBlockValue() {
|
||||
double result = 0.0f;
|
||||
if (!this->m_yBlockEntropy.empty())
|
||||
result = *std::max_element(this->m_yBlockEntropy.begin(), this->m_yBlockEntropy.end());
|
||||
if (!m_yBlockEntropy.empty())
|
||||
result = *std::max_element(m_yBlockEntropy.begin(), m_yBlockEntropy.end());
|
||||
return result;
|
||||
}
|
||||
|
||||
// Return the highest entropy value among all of the blocks
|
||||
u64 getHighestEntropyBlockAddress() {
|
||||
u64 address = 0x00;
|
||||
if (!this->m_yBlockEntropy.empty())
|
||||
address = (std::max_element(this->m_yBlockEntropy.begin(), this->m_yBlockEntropy.end()) - this->m_yBlockEntropy.begin()) * this->m_blockSize;
|
||||
return this->m_startAddress + address;
|
||||
if (!m_yBlockEntropy.empty())
|
||||
address = (std::max_element(m_yBlockEntropy.begin(), m_yBlockEntropy.end()) - m_yBlockEntropy.begin()) * m_blockSize;
|
||||
return m_startAddress + address;
|
||||
}
|
||||
|
||||
// Return the highest entropy value among all of the blocks
|
||||
double getLowestEntropyBlockValue() {
|
||||
double result = 0.0f;
|
||||
if (this->m_yBlockEntropy.size() > 1)
|
||||
result = *std::min_element(this->m_yBlockEntropy.begin(), this->m_yBlockEntropy.end() - 1);
|
||||
if (m_yBlockEntropy.size() > 1)
|
||||
result = *std::min_element(m_yBlockEntropy.begin(), m_yBlockEntropy.end() - 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Return the highest entropy value among all of the blocks
|
||||
u64 getLowestEntropyBlockAddress() {
|
||||
u64 address = 0x00;
|
||||
if (this->m_yBlockEntropy.size() > 1)
|
||||
address = (std::min_element(this->m_yBlockEntropy.begin(), this->m_yBlockEntropy.end() - 1) - this->m_yBlockEntropy.begin()) * this->m_blockSize;
|
||||
return this->m_startAddress + address;
|
||||
if (m_yBlockEntropy.size() > 1)
|
||||
address = (std::min_element(m_yBlockEntropy.begin(), m_yBlockEntropy.end() - 1) - m_yBlockEntropy.begin()) * m_blockSize;
|
||||
return m_startAddress + address;
|
||||
}
|
||||
|
||||
// Return the number of blocks that have been processed
|
||||
u64 getSize() const {
|
||||
return this->m_yBlockEntropySampled.size();
|
||||
return m_yBlockEntropySampled.size();
|
||||
}
|
||||
|
||||
// Return the size of the chunk used for this analysis
|
||||
u64 getChunkSize() const {
|
||||
return this->m_chunkSize;
|
||||
return m_chunkSize;
|
||||
}
|
||||
|
||||
void setHandlePosition(u64 filePosition) {
|
||||
this->m_handlePosition = filePosition;
|
||||
m_handlePosition = filePosition;
|
||||
}
|
||||
|
||||
private:
|
||||
// Private method used to factorize the process public method
|
||||
void processImpl(const std::vector<u8> &bytes) {
|
||||
this->m_blockValueCounts = { 0 };
|
||||
m_blockValueCounts = { 0 };
|
||||
|
||||
// Reset and resize the array
|
||||
this->m_yBlockEntropy.clear();
|
||||
m_yBlockEntropy.clear();
|
||||
|
||||
this->m_byteCount = 0;
|
||||
this->m_blockCount = 0;
|
||||
m_byteCount = 0;
|
||||
m_blockCount = 0;
|
||||
|
||||
// Loop over each byte of the file (or a part of it)
|
||||
for (u8 byte: bytes) {
|
||||
// Increment the occurrence of the current byte
|
||||
this->m_blockValueCounts[byte]++;
|
||||
m_blockValueCounts[byte]++;
|
||||
|
||||
this->m_byteCount++;
|
||||
m_byteCount++;
|
||||
// Check if we processed one complete chunk, if so compute the entropy and start analysing the next chunk
|
||||
if (((this->m_byteCount % this->m_chunkSize) == 0) || this->m_byteCount == bytes.size() * 8) [[unlikely]] {
|
||||
this->m_yBlockEntropy.push_back(calculateEntropy(this->m_blockValueCounts, this->m_chunkSize));
|
||||
if (((m_byteCount % m_chunkSize) == 0) || m_byteCount == bytes.size() * 8) [[unlikely]] {
|
||||
m_yBlockEntropy.push_back(calculateEntropy(m_blockValueCounts, m_chunkSize));
|
||||
|
||||
this->m_blockCount += 1;
|
||||
this->m_blockValueCounts = { 0 };
|
||||
m_blockCount += 1;
|
||||
m_blockValueCounts = { 0 };
|
||||
}
|
||||
}
|
||||
processFinalize();
|
||||
@@ -529,23 +529,23 @@ namespace hex {
|
||||
|
||||
void processFinalize() {
|
||||
// Only save at most m_sampleSize elements of the result
|
||||
this->m_yBlockEntropySampled = sampleData(this->m_yBlockEntropy, std::min<size_t>(this->m_blockCount + 1, this->m_sampleSize));
|
||||
m_yBlockEntropySampled = sampleData(m_yBlockEntropy, std::min<size_t>(m_blockCount + 1, m_sampleSize));
|
||||
|
||||
if (!this->m_yBlockEntropySampled.empty())
|
||||
this->m_yBlockEntropySampled.push_back(this->m_yBlockEntropySampled.back());
|
||||
if (!m_yBlockEntropySampled.empty())
|
||||
m_yBlockEntropySampled.push_back(m_yBlockEntropySampled.back());
|
||||
|
||||
double stride = std::max(1.0, double(
|
||||
double(std::ceil((this->m_endAddress - this->m_startAddress)) / this->m_blockSize) / this->m_yBlockEntropySampled.size()));
|
||||
double(std::ceil((m_endAddress - m_startAddress)) / m_blockSize) / m_yBlockEntropySampled.size()));
|
||||
|
||||
this->m_blockCount = this->m_yBlockEntropySampled.size() - 1;
|
||||
m_blockCount = m_yBlockEntropySampled.size() - 1;
|
||||
|
||||
// The m_xBlockEntropy attribute is used to specify the position of entropy values
|
||||
// in the plot when the Y axis doesn't start at 0
|
||||
this->m_xBlockEntropy.clear();
|
||||
this->m_xBlockEntropy.resize(this->m_blockCount);
|
||||
for (u64 i = 0; i < this->m_blockCount; ++i)
|
||||
this->m_xBlockEntropy[i] = ((this->m_startAddress / this->m_blockSize) + stride * i) * this->m_blockSize;
|
||||
this->m_xBlockEntropy.push_back(this->m_endAddress);
|
||||
m_xBlockEntropy.clear();
|
||||
m_xBlockEntropy.resize(m_blockCount);
|
||||
for (u64 i = 0; i < m_blockCount; ++i)
|
||||
m_xBlockEntropy[i] = ((m_startAddress / m_blockSize) + stride * i) * m_blockSize;
|
||||
m_xBlockEntropy.push_back(m_endAddress);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -594,12 +594,12 @@ namespace hex {
|
||||
|
||||
void draw(ImVec2 size, ImPlotFlags flags) {
|
||||
|
||||
if (!this->m_processing && ImPlot::BeginPlot("##distribution", size, flags)) {
|
||||
if (!m_processing && ImPlot::BeginPlot("##distribution", size, flags)) {
|
||||
ImPlot::SetupAxes("hex.builtin.common.value"_lang, "hex.builtin.common.count"_lang,
|
||||
ImPlotAxisFlags_Lock | ImPlotAxisFlags_NoHighlight | ImPlotAxisFlags_NoSideSwitch,
|
||||
ImPlotAxisFlags_Lock | ImPlotAxisFlags_NoHighlight | ImPlotAxisFlags_NoSideSwitch);
|
||||
ImPlot::SetupAxisScale(ImAxis_Y1, ImPlotScale_Log10);
|
||||
ImPlot::SetupAxesLimits(-1, 256, 1, double(*std::max_element(this->m_valueCounts.begin(), this->m_valueCounts.end())) * 1.1F, ImGuiCond_Always);
|
||||
ImPlot::SetupAxesLimits(-1, 256, 1, double(*std::max_element(m_valueCounts.begin(), m_valueCounts.end())) * 1.1F, ImGuiCond_Always);
|
||||
ImPlot::SetupAxisFormat(ImAxis_X1, impl::IntegerAxisFormatter, (void*)("0x%02llX"));
|
||||
ImPlot::SetupAxisTicks(ImAxis_X1, 0, 255, 17);
|
||||
ImPlot::SetupMouseText(ImPlotLocation_NorthEast);
|
||||
@@ -610,67 +610,67 @@ namespace hex {
|
||||
return result;
|
||||
}();
|
||||
|
||||
ImPlot::PlotBars<ImU64>("##bytes", x.data(), this->m_valueCounts.data(), x.size(), 1);
|
||||
ImPlot::PlotBars<ImU64>("##bytes", x.data(), m_valueCounts.data(), x.size(), 1);
|
||||
ImPlot::EndPlot();
|
||||
}
|
||||
}
|
||||
|
||||
void process(prv::Provider *provider, u64 startAddress, u64 endAddress) {
|
||||
this->m_processing = true;
|
||||
m_processing = true;
|
||||
|
||||
// Update attributes
|
||||
this->m_startAddress = startAddress;
|
||||
this->m_endAddress = endAddress;
|
||||
m_startAddress = startAddress;
|
||||
m_endAddress = endAddress;
|
||||
|
||||
// Get a file reader
|
||||
auto reader = prv::ProviderReader(provider);
|
||||
std::vector<u8> bytes = reader.read(this->m_startAddress, this->m_endAddress - this->m_startAddress);
|
||||
std::vector<u8> bytes = reader.read(m_startAddress, m_endAddress - m_startAddress);
|
||||
|
||||
this->processImpl(bytes);
|
||||
|
||||
this->m_processing = false;
|
||||
m_processing = false;
|
||||
}
|
||||
|
||||
void process(const std::vector<u8> &buffer) {
|
||||
this->m_processing = true;
|
||||
m_processing = true;
|
||||
|
||||
// Update attributes
|
||||
this->m_startAddress = 0;
|
||||
this->m_endAddress = buffer.size();
|
||||
m_startAddress = 0;
|
||||
m_endAddress = buffer.size();
|
||||
|
||||
this->processImpl(buffer);
|
||||
|
||||
this->m_processing = false;
|
||||
m_processing = false;
|
||||
}
|
||||
|
||||
// Reset the byte distribution array
|
||||
void reset() {
|
||||
this->m_processing = true;
|
||||
this->m_valueCounts.fill(0);
|
||||
this->m_processing = false;
|
||||
m_processing = true;
|
||||
m_valueCounts.fill(0);
|
||||
m_processing = false;
|
||||
}
|
||||
|
||||
// Process one byte at the time
|
||||
void update(u8 byte) {
|
||||
this->m_processing = true;
|
||||
this->m_valueCounts[byte]++;
|
||||
this->m_processing = false;
|
||||
m_processing = true;
|
||||
m_valueCounts[byte]++;
|
||||
m_processing = false;
|
||||
}
|
||||
|
||||
// Return byte distribution array in it's current state
|
||||
std::array<ImU64, 256> & get() {
|
||||
return this->m_valueCounts;
|
||||
return m_valueCounts;
|
||||
}
|
||||
|
||||
private:
|
||||
// Private method used to factorize the process public method
|
||||
void processImpl(const std::vector<u8> &bytes) {
|
||||
// Reset the array
|
||||
this->m_valueCounts.fill(0);
|
||||
m_valueCounts.fill(0);
|
||||
// Loop over each byte of the file (or a part of it)
|
||||
// Increment the occurrence of the current byte
|
||||
for (u8 byte : bytes)
|
||||
this->m_valueCounts[byte]++;
|
||||
m_valueCounts[byte]++;
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -689,13 +689,13 @@ namespace hex {
|
||||
|
||||
void draw(ImVec2 size, ImPlotFlags flags, bool updateHandle = false) {
|
||||
// Draw the result of the analysis
|
||||
if (!this->m_processing && ImPlot::BeginPlot("##byte_types", size, flags)) {
|
||||
if (!m_processing && ImPlot::BeginPlot("##byte_types", size, flags)) {
|
||||
ImPlot::SetupAxes("hex.builtin.common.address"_lang, "hex.builtin.common.percentage"_lang,
|
||||
ImPlotAxisFlags_Lock | ImPlotAxisFlags_NoHighlight | ImPlotAxisFlags_NoSideSwitch,
|
||||
ImPlotAxisFlags_Lock | ImPlotAxisFlags_NoHighlight | ImPlotAxisFlags_NoSideSwitch);
|
||||
ImPlot::SetupAxesLimits(
|
||||
this->m_xBlockTypeDistributions.empty() ? 0 : this->m_xBlockTypeDistributions.front(),
|
||||
this->m_xBlockTypeDistributions.empty() ? 0 : this->m_xBlockTypeDistributions.back(),
|
||||
m_xBlockTypeDistributions.empty() ? 0 : m_xBlockTypeDistributions.front(),
|
||||
m_xBlockTypeDistributions.empty() ? 0 : m_xBlockTypeDistributions.back(),
|
||||
-0.1F,
|
||||
100.1F,
|
||||
ImGuiCond_Always);
|
||||
@@ -709,25 +709,25 @@ namespace hex {
|
||||
};
|
||||
|
||||
for (u32 i = 0; i < Names.size(); i++) {
|
||||
ImPlot::PlotLine(Names[i], this->m_xBlockTypeDistributions.data(), this->m_yBlockTypeDistributionsSampled[i].data(), this->m_xBlockTypeDistributions.size());
|
||||
ImPlot::PlotLine(Names[i], m_xBlockTypeDistributions.data(), m_yBlockTypeDistributionsSampled[i].data(), m_xBlockTypeDistributions.size());
|
||||
}
|
||||
|
||||
// The parameter updateHandle is used when using the pattern language since we don't have a provider
|
||||
// but just a set of bytes, we won't be able to use the drag bar correctly.
|
||||
if (updateHandle) {
|
||||
// Set a draggable line on the plot
|
||||
if (ImPlot::DragLineX(1, &this->m_handlePosition, ImGui::GetStyleColorVec4(ImGuiCol_Text))) {
|
||||
if (ImPlot::DragLineX(1, &m_handlePosition, ImGui::GetStyleColorVec4(ImGuiCol_Text))) {
|
||||
// The line was dragged, update the position in the hex editor
|
||||
|
||||
// Clamp the value between the start/end of the region to analyze
|
||||
this->m_handlePosition = std::clamp<double>(
|
||||
this->m_handlePosition,
|
||||
this->m_startAddress,
|
||||
this->m_endAddress);
|
||||
m_handlePosition = std::clamp<double>(
|
||||
m_handlePosition,
|
||||
m_startAddress,
|
||||
m_endAddress);
|
||||
|
||||
// Compute the position inside hex editor
|
||||
u64 address = u64(std::max<double>(this->m_handlePosition, 0)) + this->m_baseAddress;
|
||||
address = std::min<u64>(address, this->m_baseAddress + this->m_fileSize - 1);
|
||||
u64 address = u64(std::max<double>(m_handlePosition, 0)) + m_baseAddress;
|
||||
address = std::min<u64>(address, m_baseAddress + m_fileSize - 1);
|
||||
ImHexApi::HexEditor::setSelection(address, 1);
|
||||
}
|
||||
}
|
||||
@@ -736,103 +736,103 @@ namespace hex {
|
||||
}
|
||||
|
||||
void process(prv::Provider *provider, u64 startAddress, u64 endAddress) {
|
||||
this->m_processing = true;
|
||||
m_processing = true;
|
||||
|
||||
// Update attributes
|
||||
this->m_startAddress = startAddress;
|
||||
this->m_endAddress = endAddress;
|
||||
this->m_baseAddress = provider->getBaseAddress();
|
||||
this->m_fileSize = provider->getSize();
|
||||
m_startAddress = startAddress;
|
||||
m_endAddress = endAddress;
|
||||
m_baseAddress = provider->getBaseAddress();
|
||||
m_fileSize = provider->getSize();
|
||||
|
||||
// Get a file reader
|
||||
auto reader = prv::ProviderReader(provider);
|
||||
std::vector<u8> bytes = reader.read(this->m_startAddress, this->m_endAddress - this->m_startAddress);
|
||||
std::vector<u8> bytes = reader.read(m_startAddress, m_endAddress - m_startAddress);
|
||||
|
||||
this->processImpl(bytes);
|
||||
|
||||
// Set the diagram handle position to the start of the plot
|
||||
this->m_handlePosition = this->m_startAddress;
|
||||
m_handlePosition = m_startAddress;
|
||||
|
||||
this->m_processing = false;
|
||||
m_processing = false;
|
||||
}
|
||||
|
||||
void process(const std::vector<u8> &buffer, u64 baseAddress, u64 fileSize) {
|
||||
this->m_processing = true;
|
||||
m_processing = true;
|
||||
|
||||
// Update attributes
|
||||
this->m_startAddress = 0;
|
||||
this->m_endAddress = buffer.size();
|
||||
this->m_baseAddress = baseAddress;
|
||||
this->m_fileSize = fileSize;
|
||||
m_startAddress = 0;
|
||||
m_endAddress = buffer.size();
|
||||
m_baseAddress = baseAddress;
|
||||
m_fileSize = fileSize;
|
||||
|
||||
this->processImpl(buffer);
|
||||
|
||||
// Set the diagram handle position to the start of the plot
|
||||
this->m_handlePosition = this->m_startAddress;
|
||||
m_handlePosition = m_startAddress;
|
||||
|
||||
this->m_processing = false;
|
||||
m_processing = false;
|
||||
}
|
||||
|
||||
// Reset the byte type distribution analysis
|
||||
void reset(u64 startAddress, u64 endAddress, u64 baseAddress, u64 size) {
|
||||
this->m_processing = true;
|
||||
m_processing = true;
|
||||
|
||||
// Update attributes
|
||||
this->m_startAddress = startAddress;
|
||||
this->m_endAddress = endAddress;
|
||||
this->m_baseAddress = baseAddress;
|
||||
this->m_fileSize = size;
|
||||
m_startAddress = startAddress;
|
||||
m_endAddress = endAddress;
|
||||
m_baseAddress = baseAddress;
|
||||
m_fileSize = size;
|
||||
|
||||
this->m_byteCount = 0;
|
||||
this->m_blockCount = 0;
|
||||
this->m_blockValueCounts = { 0 };
|
||||
m_byteCount = 0;
|
||||
m_blockCount = 0;
|
||||
m_blockValueCounts = { 0 };
|
||||
|
||||
// Reset and resize the array
|
||||
this->m_yBlockTypeDistributions.fill({});
|
||||
m_yBlockTypeDistributions.fill({});
|
||||
|
||||
// Set the diagram handle position to the start of the plot
|
||||
this->m_handlePosition = this->m_startAddress;
|
||||
m_handlePosition = m_startAddress;
|
||||
}
|
||||
|
||||
// Process one byte at the time
|
||||
void update(u8 byte) {
|
||||
u64 totalBlock = std::ceil((this->m_endAddress - this->m_startAddress) / this->m_blockSize);
|
||||
u64 totalBlock = std::ceil((m_endAddress - m_startAddress) / m_blockSize);
|
||||
// Check if there is still some block to process
|
||||
if (this->m_blockCount < totalBlock) {
|
||||
if (m_blockCount < totalBlock) {
|
||||
|
||||
this->m_blockValueCounts[byte]++;
|
||||
m_blockValueCounts[byte]++;
|
||||
|
||||
this->m_byteCount++;
|
||||
if (((this->m_byteCount % this->m_blockSize) == 0) || this->m_byteCount == (this->m_endAddress - this->m_startAddress)) [[unlikely]] {
|
||||
auto typeDist = calculateTypeDistribution(this->m_blockValueCounts, this->m_blockSize);
|
||||
m_byteCount++;
|
||||
if (((m_byteCount % m_blockSize) == 0) || m_byteCount == (m_endAddress - m_startAddress)) [[unlikely]] {
|
||||
auto typeDist = calculateTypeDistribution(m_blockValueCounts, m_blockSize);
|
||||
for (size_t i = 0; i < typeDist.size(); i++)
|
||||
this->m_yBlockTypeDistributions[i].push_back(typeDist[i] * 100);
|
||||
m_yBlockTypeDistributions[i].push_back(typeDist[i] * 100);
|
||||
|
||||
this->m_blockCount += 1;
|
||||
this->m_blockValueCounts = { 0 };
|
||||
m_blockCount += 1;
|
||||
m_blockValueCounts = { 0 };
|
||||
}
|
||||
|
||||
// Check if we processed the last block, if so setup the X axis part of the data
|
||||
if (this->m_blockCount == totalBlock) {
|
||||
if (m_blockCount == totalBlock) {
|
||||
|
||||
processFinalize();
|
||||
this->m_processing = false;
|
||||
m_processing = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Return the percentage of plain text character inside the analyzed region
|
||||
double getPlainTextCharacterPercentage() {
|
||||
if (this->m_yBlockTypeDistributions[2].empty() || this->m_yBlockTypeDistributions[4].empty())
|
||||
if (m_yBlockTypeDistributions[2].empty() || m_yBlockTypeDistributions[4].empty())
|
||||
return -1.0;
|
||||
|
||||
|
||||
double plainTextPercentage = std::reduce(this->m_yBlockTypeDistributions[2].begin(), this->m_yBlockTypeDistributions[2].end()) / this->m_yBlockTypeDistributions[2].size();
|
||||
return plainTextPercentage + std::reduce(this->m_yBlockTypeDistributions[4].begin(), this->m_yBlockTypeDistributions[4].end()) / this->m_yBlockTypeDistributions[4].size();
|
||||
double plainTextPercentage = std::reduce(m_yBlockTypeDistributions[2].begin(), m_yBlockTypeDistributions[2].end()) / m_yBlockTypeDistributions[2].size();
|
||||
return plainTextPercentage + std::reduce(m_yBlockTypeDistributions[4].begin(), m_yBlockTypeDistributions[4].end()) / m_yBlockTypeDistributions[4].size();
|
||||
}
|
||||
|
||||
void setHandlePosition(u64 filePosition) {
|
||||
this->m_handlePosition = filePosition;
|
||||
m_handlePosition = filePosition;
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -880,24 +880,24 @@ namespace hex {
|
||||
|
||||
// Private method used to factorize the process public method
|
||||
void processImpl(const std::vector<u8> &bytes) {
|
||||
this->m_blockValueCounts = { 0 };
|
||||
m_blockValueCounts = { 0 };
|
||||
|
||||
this->m_yBlockTypeDistributions.fill({});
|
||||
this->m_byteCount = 0;
|
||||
this->m_blockCount = 0;
|
||||
m_yBlockTypeDistributions.fill({});
|
||||
m_byteCount = 0;
|
||||
m_blockCount = 0;
|
||||
|
||||
// Loop over each byte of the file (or a part of it)
|
||||
for (u8 byte : bytes) {
|
||||
this->m_blockValueCounts[byte]++;
|
||||
m_blockValueCounts[byte]++;
|
||||
|
||||
this->m_byteCount++;
|
||||
if (((this->m_byteCount % this->m_blockSize) == 0) || this->m_byteCount == (this->m_endAddress - this->m_startAddress)) [[unlikely]] {
|
||||
auto typeDist = calculateTypeDistribution(this->m_blockValueCounts, this->m_blockSize);
|
||||
m_byteCount++;
|
||||
if (((m_byteCount % m_blockSize) == 0) || m_byteCount == (m_endAddress - m_startAddress)) [[unlikely]] {
|
||||
auto typeDist = calculateTypeDistribution(m_blockValueCounts, m_blockSize);
|
||||
for (size_t i = 0; i < typeDist.size(); i++)
|
||||
this->m_yBlockTypeDistributions[i].push_back(typeDist[i] * 100);
|
||||
m_yBlockTypeDistributions[i].push_back(typeDist[i] * 100);
|
||||
|
||||
this->m_blockCount += 1;
|
||||
this->m_blockValueCounts = { 0 };
|
||||
m_blockCount += 1;
|
||||
m_blockValueCounts = { 0 };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -906,23 +906,23 @@ namespace hex {
|
||||
|
||||
void processFinalize() {
|
||||
// Only save at most m_sampleSize elements of the result
|
||||
for (size_t i = 0; i < this->m_yBlockTypeDistributions.size(); ++i) {
|
||||
this->m_yBlockTypeDistributionsSampled[i] = sampleData(this->m_yBlockTypeDistributions[i], std::min<size_t>(this->m_blockCount + 1, this->m_sampleSize));
|
||||
for (size_t i = 0; i < m_yBlockTypeDistributions.size(); ++i) {
|
||||
m_yBlockTypeDistributionsSampled[i] = sampleData(m_yBlockTypeDistributions[i], std::min<size_t>(m_blockCount + 1, m_sampleSize));
|
||||
|
||||
if (!this->m_yBlockTypeDistributionsSampled[i].empty())
|
||||
this->m_yBlockTypeDistributionsSampled[i].push_back(this->m_yBlockTypeDistributionsSampled[i].back());
|
||||
if (!m_yBlockTypeDistributionsSampled[i].empty())
|
||||
m_yBlockTypeDistributionsSampled[i].push_back(m_yBlockTypeDistributionsSampled[i].back());
|
||||
}
|
||||
|
||||
double stride = std::max(1.0, double(this->m_blockCount) / this->m_yBlockTypeDistributionsSampled[0].size());
|
||||
this->m_blockCount = this->m_yBlockTypeDistributionsSampled[0].size() - 1;
|
||||
double stride = std::max(1.0, double(m_blockCount) / m_yBlockTypeDistributionsSampled[0].size());
|
||||
m_blockCount = m_yBlockTypeDistributionsSampled[0].size() - 1;
|
||||
|
||||
// The m_xBlockTypeDistributions attribute is used to specify the position of entropy
|
||||
// values in the plot when the Y axis doesn't start at 0
|
||||
this->m_xBlockTypeDistributions.clear();
|
||||
this->m_xBlockTypeDistributions.resize(this->m_blockCount);
|
||||
for (u64 i = 0; i < this->m_blockCount; ++i)
|
||||
this->m_xBlockTypeDistributions[i] = this->m_startAddress + (stride * i * this->m_blockSize);
|
||||
this->m_xBlockTypeDistributions.push_back(this->m_endAddress);
|
||||
m_xBlockTypeDistributions.clear();
|
||||
m_xBlockTypeDistributions.resize(m_blockCount);
|
||||
for (u64 i = 0; i < m_blockCount; ++i)
|
||||
m_xBlockTypeDistributions[i] = m_startAddress + (stride * i * m_blockSize);
|
||||
m_xBlockTypeDistributions.push_back(m_endAddress);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -16,16 +16,16 @@ namespace hex::plugin::builtin {
|
||||
ImGui::TextUnformatted("hex.builtin.popup.blocking_task.desc"_lang);
|
||||
ImGui::Separator();
|
||||
|
||||
if (this->m_task.getProgress() == 0)
|
||||
if (m_task.getProgress() == 0)
|
||||
ImGuiExt::TextSpinner("");
|
||||
else
|
||||
ImGui::ProgressBar(this->m_task.getProgress() / 100.0F);
|
||||
ImGui::ProgressBar(m_task.getProgress() / 100.0F);
|
||||
|
||||
ImGui::NewLine();
|
||||
if (ImGui::ButtonEx("hex.builtin.common.cancel"_lang, ImVec2(ImGui::GetContentRegionAvail().x, 0)) || ImGui::IsKeyDown(ImGuiKey_Escape))
|
||||
this->m_task.interrupt();
|
||||
m_task.interrupt();
|
||||
|
||||
if (!this->m_task.isRunning()) {
|
||||
if (!m_task.isRunning()) {
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,23 +24,23 @@ namespace hex::plugin::builtin {
|
||||
|
||||
void drawContent() override {
|
||||
ImGui::PushItemWidth(600_scaled);
|
||||
ImGui::BeginDisabled(this->m_requestTask.isRunning());
|
||||
if (ImGui::InputText("##input", this->m_inputBuffer, ImGuiInputTextFlags_EnterReturnsTrue)) {
|
||||
ImGui::BeginDisabled(m_requestTask.isRunning());
|
||||
if (ImGui::InputText("##input", m_inputBuffer, ImGuiInputTextFlags_EnterReturnsTrue)) {
|
||||
this->executeQuery();
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
ImGui::PopItemWidth();
|
||||
|
||||
if (ImGui::BeginChild("##answer", scaled(ImVec2(600, 350)), true, ImGuiWindowFlags_AlwaysVerticalScrollbar)) {
|
||||
if (!this->m_requestTask.isRunning()) {
|
||||
if (this->m_answer.empty()) {
|
||||
if (this->m_noAnswer)
|
||||
if (!m_requestTask.isRunning()) {
|
||||
if (m_answer.empty()) {
|
||||
if (m_noAnswer)
|
||||
ImGuiExt::TextFormattedCentered("{}", "hex.builtin.popup.docs_question.no_answer"_lang);
|
||||
else
|
||||
ImGuiExt::TextFormattedCentered("{}", "hex.builtin.popup.docs_question.prompt"_lang);
|
||||
} else {
|
||||
int id = 1;
|
||||
for (auto &[type, text] : this->m_answer) {
|
||||
for (auto &[type, text] : m_answer) {
|
||||
ImGui::PushID(id);
|
||||
switch (type) {
|
||||
case TextBlockType::Text:
|
||||
@@ -79,10 +79,10 @@ namespace hex::plugin::builtin {
|
||||
|
||||
private:
|
||||
void executeQuery() {
|
||||
this->m_requestTask = TaskManager::createBackgroundTask("Query Docs", [this, input = this->m_inputBuffer](Task &) {
|
||||
this->m_noAnswer = false;
|
||||
m_requestTask = TaskManager::createBackgroundTask("Query Docs", [this, input = m_inputBuffer](Task &) {
|
||||
m_noAnswer = false;
|
||||
for (auto space : { "xj7sbzGbHH260vbpZOu1", "WZzDdGjxmgMSIE3xly6o" }) {
|
||||
this->m_answer.clear();
|
||||
m_answer.clear();
|
||||
|
||||
auto request = HttpRequest("POST", hex::format("https://api.gitbook.com/v1/spaces/{}/search/ask", space));
|
||||
|
||||
@@ -115,19 +115,19 @@ namespace hex::plugin::builtin {
|
||||
|
||||
if (block.starts_with("rust\n")) {
|
||||
block = block.substr(5);
|
||||
this->m_answer.emplace_back(TextBlockType::Code, block);
|
||||
m_answer.emplace_back(TextBlockType::Code, block);
|
||||
} else if (block.starts_with("cpp\n")) {
|
||||
block = block.substr(4);
|
||||
this->m_answer.emplace_back(TextBlockType::Code, block);
|
||||
m_answer.emplace_back(TextBlockType::Code, block);
|
||||
} else {
|
||||
this->m_answer.emplace_back(TextBlockType::Text, block);
|
||||
m_answer.emplace_back(TextBlockType::Text, block);
|
||||
}
|
||||
}
|
||||
} catch(...) {
|
||||
continue;
|
||||
}
|
||||
|
||||
this->m_noAnswer = this->m_answer.empty();
|
||||
m_noAnswer = m_answer.empty();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -31,10 +31,10 @@ namespace hex::plugin::builtin {
|
||||
if (adjustedPath.empty())
|
||||
adjustedPath = path.filename();
|
||||
|
||||
this->m_files.push_back({ path, adjustedPath });
|
||||
m_files.push_back({ path, adjustedPath });
|
||||
}
|
||||
|
||||
std::sort(this->m_files.begin(), this->m_files.end(), [](const auto &a, const auto &b) {
|
||||
std::sort(m_files.begin(), m_files.end(), [](const auto &a, const auto &b) {
|
||||
return a.first < b.first;
|
||||
});
|
||||
}
|
||||
@@ -44,19 +44,19 @@ namespace hex::plugin::builtin {
|
||||
|
||||
if (ImGui::BeginListBox("##files", scaled(ImVec2(500, 400)))) {
|
||||
u32 index = 0;
|
||||
for (auto &[path, pathName] : this->m_files) {
|
||||
for (auto &[path, pathName] : m_files) {
|
||||
ImGui::PushID(index);
|
||||
|
||||
bool selected = this->m_indices.contains(index);
|
||||
bool selected = m_indices.contains(index);
|
||||
if (ImGui::Selectable(wolv::util::toUTF8String(pathName).c_str(), selected, ImGuiSelectableFlags_DontClosePopups)) {
|
||||
if (!this->m_multiple) {
|
||||
this->m_indices.clear();
|
||||
this->m_indices.insert(index);
|
||||
if (!m_multiple) {
|
||||
m_indices.clear();
|
||||
m_indices.insert(index);
|
||||
} else {
|
||||
if (selected) {
|
||||
this->m_indices.erase(index);
|
||||
m_indices.erase(index);
|
||||
} else {
|
||||
this->m_indices.insert(index);
|
||||
m_indices.insert(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -74,18 +74,18 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
if (ImGui::Button("hex.builtin.common.open"_lang) || doubleClicked) {
|
||||
for (const auto &index : this->m_indices)
|
||||
this->m_openCallback(this->m_files[index].first);
|
||||
for (const auto &index : m_indices)
|
||||
m_openCallback(m_files[index].first);
|
||||
Popup::close();
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
if (ImGui::Button("hex.builtin.common.browse"_lang)) {
|
||||
fs::openFileBrowser(fs::DialogMode::Open, this->m_validExtensions, [this](const auto &path) {
|
||||
this->m_openCallback(path);
|
||||
fs::openFileBrowser(fs::DialogMode::Open, m_validExtensions, [this](const auto &path) {
|
||||
m_openCallback(path);
|
||||
Popup::close();
|
||||
}, {}, this->m_multiple);
|
||||
}, {}, m_multiple);
|
||||
}
|
||||
|
||||
if (ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Escape)))
|
||||
|
||||
@@ -20,11 +20,11 @@ namespace hex::plugin::builtin {
|
||||
m_message(std::move(message)), m_function(std::move(function)) { }
|
||||
|
||||
void drawContent() override {
|
||||
ImGuiExt::TextFormattedWrapped("{}", this->m_message.c_str());
|
||||
ImGuiExt::TextFormattedWrapped("{}", m_message.c_str());
|
||||
ImGui::NewLine();
|
||||
ImGui::Separator();
|
||||
if (ImGui::Button("hex.builtin.common.okay"_lang) || ImGui::IsKeyDown(ImGuiKey_Escape))
|
||||
this->m_function();
|
||||
m_function();
|
||||
|
||||
ImGui::SetWindowPos((ImHexApi::System::getMainWindowSize() - ImGui::GetWindowSize()) / 2, ImGuiCond_Appearing);
|
||||
|
||||
|
||||
@@ -17,20 +17,20 @@ namespace hex::plugin::builtin {
|
||||
m_yesFunction(std::move(yesFunction)), m_noFunction(std::move(noFunction)) { }
|
||||
|
||||
void drawContent() override {
|
||||
ImGuiExt::TextFormattedWrapped("{}", this->m_message.c_str());
|
||||
ImGuiExt::TextFormattedWrapped("{}", m_message.c_str());
|
||||
ImGui::NewLine();
|
||||
ImGui::Separator();
|
||||
|
||||
auto width = ImGui::GetWindowWidth();
|
||||
ImGui::SetCursorPosX(width / 9);
|
||||
if (ImGui::Button("hex.builtin.common.yes"_lang, ImVec2(width / 3, 0))) {
|
||||
this->m_yesFunction();
|
||||
m_yesFunction();
|
||||
this->close();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ImGui::SetCursorPosX(width / 9 * 5);
|
||||
if (ImGui::Button("hex.builtin.common.no"_lang, ImVec2(width / 3, 0))) {
|
||||
this->m_noFunction();
|
||||
m_noFunction();
|
||||
this->close();
|
||||
}
|
||||
|
||||
|
||||
@@ -15,12 +15,12 @@ namespace hex::plugin::builtin {
|
||||
PopupTelemetryRequest()
|
||||
: hex::Popup<PopupTelemetryRequest>("hex.builtin.common.question", false) {
|
||||
// Check if there is a telemetry uuid
|
||||
this->m_uuid = ContentRegistry::Settings::read("hex.builtin.setting.general", "hex.builtin.setting.general.uuid", "").get<std::string>();
|
||||
if(this->m_uuid.empty()) {
|
||||
m_uuid = ContentRegistry::Settings::read("hex.builtin.setting.general", "hex.builtin.setting.general.uuid", "").get<std::string>();
|
||||
if(m_uuid.empty()) {
|
||||
// Generate a new uuid
|
||||
this->m_uuid = wolv::hash::generateUUID();
|
||||
m_uuid = wolv::hash::generateUUID();
|
||||
// Save
|
||||
ContentRegistry::Settings::write("hex.builtin.setting.general", "hex.builtin.setting.general.uuid", this->m_uuid);
|
||||
ContentRegistry::Settings::write("hex.builtin.setting.general", "hex.builtin.setting.general.uuid", m_uuid);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace hex::plugin::builtin {
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::TextUnformatted("hex.builtin.welcome.server_contact.data_collected.uuid"_lang);
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::TextWrapped("%s", this->m_uuid.c_str());
|
||||
ImGui::TextWrapped("%s", m_uuid.c_str());
|
||||
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
@@ -19,17 +19,17 @@ namespace hex::plugin::builtin {
|
||||
m_message(std::move(message)), m_function(std::move(function)) { }
|
||||
|
||||
void drawContent() override {
|
||||
ImGuiExt::TextFormattedWrapped("{}", Lang(this->m_message));
|
||||
ImGuiExt::TextFormattedWrapped("{}", Lang(m_message));
|
||||
ImGui::NewLine();
|
||||
|
||||
ImGui::PushItemWidth(-1);
|
||||
|
||||
if (this->m_justOpened) {
|
||||
if (m_justOpened) {
|
||||
ImGui::SetKeyboardFocusHere();
|
||||
this->m_justOpened = false;
|
||||
m_justOpened = false;
|
||||
}
|
||||
|
||||
ImGuiExt::InputTextIcon("##input", ICON_VS_SYMBOL_KEY, this->m_input);
|
||||
ImGuiExt::InputTextIcon("##input", ICON_VS_SYMBOL_KEY, m_input);
|
||||
ImGui::PopItemWidth();
|
||||
|
||||
ImGui::NewLine();
|
||||
@@ -38,7 +38,7 @@ namespace hex::plugin::builtin {
|
||||
auto width = ImGui::GetWindowWidth();
|
||||
ImGui::SetCursorPosX(width / 9);
|
||||
if (ImGui::Button("hex.builtin.common.okay"_lang, ImVec2(width / 3, 0)) || ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Enter))) {
|
||||
this->m_function(this->m_input);
|
||||
m_function(m_input);
|
||||
this->close();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace hex::plugin::builtin {
|
||||
m_yesFunction(std::move(yesFunction)), m_noFunction(std::move(noFunction)) { }
|
||||
|
||||
void drawContent() override {
|
||||
ImGuiExt::TextFormattedWrapped("{}", this->m_message.c_str());
|
||||
ImGuiExt::TextFormattedWrapped("{}", m_message.c_str());
|
||||
ImGui::NewLine();
|
||||
|
||||
if (ImGui::BeginTable("##unsaved_providers", 1, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg, ImVec2(0, ImGui::GetTextLineHeightWithSpacing() * 4))) {
|
||||
@@ -35,13 +35,13 @@ namespace hex::plugin::builtin {
|
||||
auto width = ImGui::GetWindowWidth();
|
||||
ImGui::SetCursorPosX(width / 9);
|
||||
if (ImGui::Button("hex.builtin.common.yes"_lang, ImVec2(width / 3, 0))) {
|
||||
this->m_yesFunction();
|
||||
m_yesFunction();
|
||||
this->close();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ImGui::SetCursorPosX(width / 9 * 5);
|
||||
if (ImGui::Button("hex.builtin.common.no"_lang, ImVec2(width / 3, 0)) || ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Escape))) {
|
||||
this->m_noFunction();
|
||||
m_noFunction();
|
||||
this->close();
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace hex::plugin::builtin {
|
||||
IntelHexProvider() = default;
|
||||
~IntelHexProvider() override = default;
|
||||
|
||||
[[nodiscard]] bool isAvailable() const override { return this->m_dataValid; }
|
||||
[[nodiscard]] bool isAvailable() const override { return m_dataValid; }
|
||||
[[nodiscard]] bool isReadable() const override { return true; }
|
||||
[[nodiscard]] bool isWritable() const override { return false; }
|
||||
[[nodiscard]] bool isResizable() const override { return false; }
|
||||
|
||||
@@ -11,9 +11,9 @@ namespace hex::plugin::builtin {
|
||||
|
||||
[[nodiscard]] bool isAvailable() const override { return true; }
|
||||
[[nodiscard]] bool isReadable() const override { return true; }
|
||||
[[nodiscard]] bool isWritable() const override { return !this->m_readOnly; }
|
||||
[[nodiscard]] bool isResizable() const override { return !this->m_readOnly; }
|
||||
[[nodiscard]] bool isSavable() const override { return this->m_name.empty(); }
|
||||
[[nodiscard]] bool isWritable() const override { return !m_readOnly; }
|
||||
[[nodiscard]] bool isResizable() const override { return !m_readOnly; }
|
||||
[[nodiscard]] bool isSavable() const override { return m_name.empty(); }
|
||||
[[nodiscard]] bool isSavableAsRecent() const override { return false; }
|
||||
|
||||
[[nodiscard]] bool open() override;
|
||||
@@ -21,7 +21,7 @@ namespace hex::plugin::builtin {
|
||||
|
||||
void readRaw(u64 offset, void *buffer, size_t size) override;
|
||||
void writeRaw(u64 offset, const void *buffer, size_t size) override;
|
||||
[[nodiscard]] u64 getActualSize() const override { return this->m_data.size(); }
|
||||
[[nodiscard]] u64 getActualSize() const override { return m_data.size(); }
|
||||
|
||||
void resizeRaw(u64 newSize) override;
|
||||
void insertRaw(u64 offset, u64 size) override;
|
||||
@@ -43,7 +43,7 @@ namespace hex::plugin::builtin {
|
||||
void loadSettings(const nlohmann::json &settings) override;
|
||||
[[nodiscard]] nlohmann::json storeSettings(nlohmann::json settings) const override;
|
||||
|
||||
void setReadOnly(bool readOnly) { this->m_readOnly = readOnly; }
|
||||
void setReadOnly(bool readOnly) { m_readOnly = readOnly; }
|
||||
|
||||
private:
|
||||
void renameFile();
|
||||
|
||||
@@ -29,9 +29,9 @@ namespace hex::plugin::builtin {
|
||||
|
||||
[[nodiscard]] bool isAvailable() const override {
|
||||
#ifdef _WIN32
|
||||
return this->m_processHandle != nullptr;
|
||||
return m_processHandle != nullptr;
|
||||
#elif __linux__
|
||||
return this->m_processId != -1;
|
||||
return m_processId != -1;
|
||||
#endif
|
||||
}
|
||||
[[nodiscard]] bool isReadable() const override { return true; }
|
||||
@@ -46,11 +46,11 @@ namespace hex::plugin::builtin {
|
||||
|
||||
void save() override {}
|
||||
|
||||
[[nodiscard]] std::string getName() const override { return hex::format("hex.builtin.provider.process_memory.name"_lang, this->m_selectedProcess != nullptr ? this->m_selectedProcess->name : ""); }
|
||||
[[nodiscard]] std::string getName() const override { return hex::format("hex.builtin.provider.process_memory.name"_lang, m_selectedProcess != nullptr ? m_selectedProcess->name : ""); }
|
||||
[[nodiscard]] std::vector<Description> getDataDescription() const override {
|
||||
return {
|
||||
{ "hex.builtin.provider.process_memory.process_name"_lang, this->m_selectedProcess->name },
|
||||
{ "hex.builtin.provider.process_memory.process_id"_lang, std::to_string(this->m_selectedProcess->id) }
|
||||
{ "hex.builtin.provider.process_memory.process_name"_lang, m_selectedProcess->name },
|
||||
{ "hex.builtin.provider.process_memory.process_id"_lang, std::to_string(m_selectedProcess->id) }
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -14,19 +14,19 @@ namespace hex::plugin::builtin::undo {
|
||||
void undo(prv::Provider *provider) override {
|
||||
hex::unused(provider);
|
||||
|
||||
ImHexApi::Bookmarks::remove(this->m_entry.id);
|
||||
ImHexApi::Bookmarks::remove(m_entry.id);
|
||||
}
|
||||
|
||||
void redo(prv::Provider *provider) override {
|
||||
hex::unused(provider);
|
||||
|
||||
auto &[region, name, comment, color, locked, id] = this->m_entry;
|
||||
auto &[region, name, comment, color, locked, id] = m_entry;
|
||||
|
||||
id = ImHexApi::Bookmarks::add(region, name, comment, color);
|
||||
}
|
||||
|
||||
[[nodiscard]] std::string format() const override {
|
||||
return hex::format("Bookmark {} created", this->m_entry.name);
|
||||
return hex::format("Bookmark {} created", m_entry.name);
|
||||
}
|
||||
|
||||
std::unique_ptr<Operation> clone() const override {
|
||||
@@ -34,7 +34,7 @@ namespace hex::plugin::builtin::undo {
|
||||
}
|
||||
|
||||
[[nodiscard]] Region getRegion() const override {
|
||||
return this->m_entry.region;
|
||||
return m_entry.region;
|
||||
}
|
||||
|
||||
bool shouldHighlight() const override { return false; }
|
||||
|
||||
@@ -13,15 +13,15 @@ namespace hex::plugin::builtin::undo {
|
||||
m_offset(offset), m_size(size) { }
|
||||
|
||||
void undo(prv::Provider *provider) override {
|
||||
provider->removeRaw(this->m_offset, this->m_size);
|
||||
provider->removeRaw(m_offset, m_size);
|
||||
}
|
||||
|
||||
void redo(prv::Provider *provider) override {
|
||||
provider->insertRaw(this->m_offset, this->m_size);
|
||||
provider->insertRaw(m_offset, m_size);
|
||||
}
|
||||
|
||||
[[nodiscard]] std::string format() const override {
|
||||
return hex::format("hex.builtin.undo_operation.insert"_lang, hex::toByteString(this->m_size), this->m_offset);
|
||||
return hex::format("hex.builtin.undo_operation.insert"_lang, hex::toByteString(m_size), m_offset);
|
||||
}
|
||||
|
||||
std::unique_ptr<Operation> clone() const override {
|
||||
@@ -29,7 +29,7 @@ namespace hex::plugin::builtin::undo {
|
||||
}
|
||||
|
||||
[[nodiscard]] Region getRegion() const override {
|
||||
return { this->m_offset, this->m_size };
|
||||
return { m_offset, m_size };
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -13,20 +13,20 @@ namespace hex::plugin::builtin::undo {
|
||||
m_offset(offset), m_size(size) { }
|
||||
|
||||
void undo(prv::Provider *provider) override {
|
||||
provider->insertRaw(this->m_offset, this->m_size);
|
||||
provider->insertRaw(m_offset, m_size);
|
||||
|
||||
provider->writeRaw(this->m_offset, this->m_removedData.data(), this->m_removedData.size());
|
||||
provider->writeRaw(m_offset, m_removedData.data(), m_removedData.size());
|
||||
}
|
||||
|
||||
void redo(prv::Provider *provider) override {
|
||||
this->m_removedData.resize(this->m_size);
|
||||
provider->readRaw(this->m_offset, this->m_removedData.data(), this->m_removedData.size());
|
||||
m_removedData.resize(m_size);
|
||||
provider->readRaw(m_offset, m_removedData.data(), m_removedData.size());
|
||||
|
||||
provider->removeRaw(this->m_offset, this->m_size);
|
||||
provider->removeRaw(m_offset, m_size);
|
||||
}
|
||||
|
||||
[[nodiscard]] std::string format() const override {
|
||||
return hex::format("hex.builtin.undo_operation.remove"_lang, hex::toByteString(this->m_size), this->m_offset);
|
||||
return hex::format("hex.builtin.undo_operation.remove"_lang, hex::toByteString(m_size), m_offset);
|
||||
}
|
||||
|
||||
std::unique_ptr<Operation> clone() const override {
|
||||
@@ -34,7 +34,7 @@ namespace hex::plugin::builtin::undo {
|
||||
}
|
||||
|
||||
[[nodiscard]] Region getRegion() const override {
|
||||
return { this->m_offset, this->m_size };
|
||||
return { m_offset, m_size };
|
||||
}
|
||||
|
||||
bool shouldHighlight() const override { return false; }
|
||||
|
||||
@@ -16,20 +16,20 @@ namespace hex::plugin::builtin::undo {
|
||||
m_newData(newData, newData + size) { }
|
||||
|
||||
void undo(prv::Provider *provider) override {
|
||||
provider->writeRaw(this->m_offset, this->m_oldData.data(), this->m_oldData.size());
|
||||
provider->writeRaw(m_offset, m_oldData.data(), m_oldData.size());
|
||||
}
|
||||
|
||||
void redo(prv::Provider *provider) override {
|
||||
provider->writeRaw(this->m_offset, this->m_newData.data(), this->m_newData.size());
|
||||
provider->writeRaw(m_offset, m_newData.data(), m_newData.size());
|
||||
}
|
||||
|
||||
[[nodiscard]] std::string format() const override {
|
||||
return hex::format("hex.builtin.undo_operation.write"_lang, hex::toByteString(this->m_newData.size()), this->m_offset);
|
||||
return hex::format("hex.builtin.undo_operation.write"_lang, hex::toByteString(m_newData.size()), m_offset);
|
||||
}
|
||||
|
||||
std::vector<std::string> formatContent() const override {
|
||||
return {
|
||||
hex::format("{} {} {}", hex::crypt::encode16(this->m_oldData), ICON_VS_ARROW_RIGHT, hex::crypt::encode16(this->m_newData)),
|
||||
hex::format("{} {} {}", hex::crypt::encode16(m_oldData), ICON_VS_ARROW_RIGHT, hex::crypt::encode16(m_newData)),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace hex::plugin::builtin::undo {
|
||||
}
|
||||
|
||||
[[nodiscard]] Region getRegion() const override {
|
||||
return { this->m_offset, this->m_oldData.size() };
|
||||
return { m_offset, m_oldData.size() };
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace hex::plugin::builtin {
|
||||
public:
|
||||
explicit ViewProvider() {
|
||||
EventProviderClosing::subscribe(this, [this](const prv::Provider *provider, bool*) {
|
||||
if (this->m_provider == provider)
|
||||
if (m_provider == provider)
|
||||
ImHexApi::Provider::remove(this, false);
|
||||
});
|
||||
}
|
||||
@@ -20,85 +20,85 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
[[nodiscard]] bool isAvailable() const override {
|
||||
if (this->m_provider == nullptr)
|
||||
if (m_provider == nullptr)
|
||||
return false;
|
||||
else
|
||||
return this->m_provider->isAvailable();
|
||||
return m_provider->isAvailable();
|
||||
}
|
||||
[[nodiscard]] bool isReadable() const override {
|
||||
if (this->m_provider == nullptr)
|
||||
if (m_provider == nullptr)
|
||||
return false;
|
||||
else
|
||||
return this->m_provider->isReadable();
|
||||
return m_provider->isReadable();
|
||||
}
|
||||
[[nodiscard]] bool isWritable() const override {
|
||||
if (this->m_provider == nullptr)
|
||||
if (m_provider == nullptr)
|
||||
return false;
|
||||
else
|
||||
return this->m_provider->isWritable();
|
||||
return m_provider->isWritable();
|
||||
}
|
||||
[[nodiscard]] bool isResizable() const override { return true; }
|
||||
|
||||
[[nodiscard]] bool isSavable() const override {
|
||||
if (this->m_provider == nullptr)
|
||||
if (m_provider == nullptr)
|
||||
return false;
|
||||
else
|
||||
return this->m_provider->isSavable();
|
||||
return m_provider->isSavable();
|
||||
}
|
||||
|
||||
void save() override {
|
||||
this->m_provider->save();
|
||||
m_provider->save();
|
||||
}
|
||||
|
||||
[[nodiscard]] bool open() override { return true; }
|
||||
void close() override { }
|
||||
|
||||
void resizeRaw(u64 newSize) override {
|
||||
this->m_size = newSize;
|
||||
m_size = newSize;
|
||||
}
|
||||
void insertRaw(u64 offset, u64 size) override {
|
||||
if (this->m_provider == nullptr)
|
||||
if (m_provider == nullptr)
|
||||
return;
|
||||
|
||||
this->m_size += size;
|
||||
this->m_provider->insert(offset + this->m_startAddress, size);
|
||||
m_size += size;
|
||||
m_provider->insert(offset + m_startAddress, size);
|
||||
}
|
||||
|
||||
void removeRaw(u64 offset, u64 size) override {
|
||||
if (this->m_provider == nullptr)
|
||||
if (m_provider == nullptr)
|
||||
return;
|
||||
|
||||
this->m_size -= size;
|
||||
this->m_provider->remove(offset + this->m_startAddress, size);
|
||||
m_size -= size;
|
||||
m_provider->remove(offset + m_startAddress, size);
|
||||
}
|
||||
|
||||
void readRaw(u64 offset, void *buffer, size_t size) override {
|
||||
if (this->m_provider == nullptr)
|
||||
if (m_provider == nullptr)
|
||||
return;
|
||||
|
||||
this->m_provider->read(offset + this->m_startAddress, buffer, size);
|
||||
m_provider->read(offset + m_startAddress, buffer, size);
|
||||
}
|
||||
|
||||
void writeRaw(u64 offset, const void *buffer, size_t size) override {
|
||||
if (this->m_provider == nullptr)
|
||||
if (m_provider == nullptr)
|
||||
return;
|
||||
|
||||
this->m_provider->write(offset + this->m_startAddress, buffer, size);
|
||||
m_provider->write(offset + m_startAddress, buffer, size);
|
||||
}
|
||||
|
||||
[[nodiscard]] u64 getActualSize() const override { return this->m_size; }
|
||||
[[nodiscard]] u64 getActualSize() const override { return m_size; }
|
||||
|
||||
[[nodiscard]] std::string getName() const override {
|
||||
if (this->m_provider == nullptr)
|
||||
if (m_provider == nullptr)
|
||||
return "View";
|
||||
else
|
||||
return hex::format("{} View", this->m_provider->getName());
|
||||
return hex::format("{} View", m_provider->getName());
|
||||
}
|
||||
[[nodiscard]] std::vector<Description> getDataDescription() const override {
|
||||
if (this->m_provider == nullptr)
|
||||
if (m_provider == nullptr)
|
||||
return { };
|
||||
|
||||
return this->m_provider->getDataDescription();
|
||||
return m_provider->getDataDescription();
|
||||
}
|
||||
|
||||
void loadSettings(const nlohmann::json &settings) override { hex::unused(settings); }
|
||||
@@ -109,9 +109,9 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
void setProvider(u64 startAddress, size_t size, hex::prv::Provider *provider) {
|
||||
this->m_startAddress = startAddress;
|
||||
this->m_size = size;
|
||||
this->m_provider = provider;
|
||||
m_startAddress = startAddress;
|
||||
m_size = size;
|
||||
m_provider = provider;
|
||||
}
|
||||
|
||||
[[nodiscard]] std::pair<Region, bool> getRegionValidity(u64 address) const override {
|
||||
|
||||
@@ -48,7 +48,7 @@ namespace hex::plugin::builtin {
|
||||
std::string m_exactResult;
|
||||
|
||||
void focusInputTextBox() {
|
||||
this->m_focusInputTextBox = true;
|
||||
m_focusInputTextBox = true;
|
||||
}
|
||||
|
||||
std::vector<CommandResult> getCommandResults(const std::string &input);
|
||||
|
||||
@@ -51,7 +51,7 @@ namespace hex::plugin::builtin {
|
||||
|
||||
void reloadCustomNodes();
|
||||
|
||||
std::vector<Workspace*> &getWorkspaceStack() { return *this->m_workspaceStack; }
|
||||
std::vector<Workspace*> &getWorkspaceStack() { return *m_workspaceStack; }
|
||||
|
||||
private:
|
||||
void drawContextMenus(ViewDataProcessor::Workspace &workspace);
|
||||
|
||||
@@ -23,42 +23,42 @@ namespace hex::plugin::builtin {
|
||||
};
|
||||
|
||||
[[nodiscard]] bool isAnyPopupOpen() const {
|
||||
return this->m_currPopup != nullptr;
|
||||
return m_currPopup != nullptr;
|
||||
}
|
||||
|
||||
template<std::derived_from<Popup> T>
|
||||
[[nodiscard]] bool isPopupOpen() const {
|
||||
return dynamic_cast<T*>(this->m_currPopup.get()) != nullptr;
|
||||
return dynamic_cast<T*>(m_currPopup.get()) != nullptr;
|
||||
}
|
||||
|
||||
template<std::derived_from<Popup> T, typename ... Args>
|
||||
void openPopup(Args && ...args) {
|
||||
this->m_currPopup = std::make_unique<T>(std::forward<Args>(args)...);
|
||||
this->m_shouldOpenPopup = true;
|
||||
m_currPopup = std::make_unique<T>(std::forward<Args>(args)...);
|
||||
m_shouldOpenPopup = true;
|
||||
}
|
||||
|
||||
void closePopup() {
|
||||
this->m_currPopup.reset();
|
||||
m_currPopup.reset();
|
||||
}
|
||||
|
||||
bool isSelectionValid() const {
|
||||
return this->m_hexEditor.isSelectionValid();
|
||||
return m_hexEditor.isSelectionValid();
|
||||
}
|
||||
|
||||
Region getSelection() const {
|
||||
return this->m_hexEditor.getSelection();
|
||||
return m_hexEditor.getSelection();
|
||||
}
|
||||
|
||||
void setSelection(const Region ®ion) {
|
||||
this->m_hexEditor.setSelection(region);
|
||||
m_hexEditor.setSelection(region);
|
||||
}
|
||||
|
||||
void setSelection(u128 start, u128 end) {
|
||||
this->m_hexEditor.setSelection(start, end);
|
||||
m_hexEditor.setSelection(start, end);
|
||||
}
|
||||
|
||||
void jumpToSelection() {
|
||||
this->m_hexEditor.jumpToSelection();
|
||||
m_hexEditor.jumpToSelection();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -52,20 +52,20 @@ namespace hex::plugin::builtin {
|
||||
ImGuiExt::TextFormattedWrapped("{}", static_cast<const char *>("hex.builtin.view.pattern_editor.accept_pattern.desc"_lang));
|
||||
|
||||
std::vector<std::string> entries;
|
||||
entries.resize(this->m_view->m_possiblePatternFiles.get(provider).size());
|
||||
entries.resize(m_view->m_possiblePatternFiles.get(provider).size());
|
||||
|
||||
for (u32 i = 0; i < entries.size(); i++) {
|
||||
entries[i] = wolv::util::toUTF8String(this->m_view->m_possiblePatternFiles.get(provider)[i].filename());
|
||||
entries[i] = wolv::util::toUTF8String(m_view->m_possiblePatternFiles.get(provider)[i].filename());
|
||||
}
|
||||
|
||||
if (ImGui::BeginListBox("##patterns_accept", ImVec2(-FLT_MIN, 0))) {
|
||||
u32 index = 0;
|
||||
for (auto &path : this->m_view->m_possiblePatternFiles.get(provider)) {
|
||||
if (ImGui::Selectable(wolv::util::toUTF8String(path.filename()).c_str(), index == this->m_selectedPatternFile, ImGuiSelectableFlags_DontClosePopups))
|
||||
this->m_selectedPatternFile = index;
|
||||
for (auto &path : m_view->m_possiblePatternFiles.get(provider)) {
|
||||
if (ImGui::Selectable(wolv::util::toUTF8String(path.filename()).c_str(), index == m_selectedPatternFile, ImGuiSelectableFlags_DontClosePopups))
|
||||
m_selectedPatternFile = index;
|
||||
|
||||
if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(0))
|
||||
this->m_view->loadPatternFile(this->m_view->m_possiblePatternFiles.get(provider)[this->m_selectedPatternFile], provider);
|
||||
m_view->loadPatternFile(m_view->m_possiblePatternFiles.get(provider)[m_selectedPatternFile], provider);
|
||||
|
||||
ImGuiExt::InfoTooltip(wolv::util::toUTF8String(path).c_str());
|
||||
|
||||
@@ -84,7 +84,7 @@ namespace hex::plugin::builtin {
|
||||
|
||||
ImGuiExt::ConfirmButtons("hex.builtin.common.yes"_lang, "hex.builtin.common.no"_lang,
|
||||
[this, provider] {
|
||||
this->m_view->loadPatternFile(this->m_view->m_possiblePatternFiles.get(provider)[this->m_selectedPatternFile], provider);
|
||||
m_view->loadPatternFile(m_view->m_possiblePatternFiles.get(provider)[m_selectedPatternFile], provider);
|
||||
this->close();
|
||||
},
|
||||
[this] {
|
||||
|
||||
@@ -18,10 +18,10 @@ namespace hex::plugin::builtin::ui {
|
||||
void draw(float height = ImGui::GetContentRegionAvail().y);
|
||||
|
||||
void setProvider(prv::Provider *provider) {
|
||||
this->m_provider = provider;
|
||||
this->m_currValidRegion = { Region::Invalid(), false };
|
||||
m_provider = provider;
|
||||
m_currValidRegion = { Region::Invalid(), false };
|
||||
}
|
||||
void setUnknownDataCharacter(char character) { this->m_unknownDataCharacter = character; }
|
||||
void setUnknownDataCharacter(char character) { m_unknownDataCharacter = character; }
|
||||
private:
|
||||
enum class CellType { None, Hex, ASCII };
|
||||
|
||||
@@ -36,36 +36,36 @@ namespace hex::plugin::builtin::ui {
|
||||
|
||||
public:
|
||||
void setSelectionUnchecked(std::optional<u64> start, std::optional<u64> end) {
|
||||
this->m_selectionStart = start;
|
||||
this->m_selectionEnd = end;
|
||||
this->m_cursorPosition = end;
|
||||
m_selectionStart = start;
|
||||
m_selectionEnd = end;
|
||||
m_cursorPosition = end;
|
||||
}
|
||||
void setSelection(const Region ®ion) { this->setSelection(region.getStartAddress(), region.getEndAddress()); }
|
||||
void setSelection(u128 start, u128 end) {
|
||||
if (!ImHexApi::Provider::isValid())
|
||||
return;
|
||||
|
||||
if (start > this->m_provider->getBaseAddress() + this->m_provider->getActualSize())
|
||||
if (start > m_provider->getBaseAddress() + m_provider->getActualSize())
|
||||
return;
|
||||
|
||||
if (start < this->m_provider->getBaseAddress())
|
||||
if (start < m_provider->getBaseAddress())
|
||||
return;
|
||||
|
||||
if (this->m_provider->getActualSize() == 0)
|
||||
if (m_provider->getActualSize() == 0)
|
||||
return;
|
||||
|
||||
const size_t maxAddress = this->m_provider->getActualSize() + this->m_provider->getBaseAddress() - 1;
|
||||
const size_t maxAddress = m_provider->getActualSize() + m_provider->getBaseAddress() - 1;
|
||||
|
||||
constexpr static auto alignDown = [](u128 value, u128 alignment) {
|
||||
return value & ~(alignment - 1);
|
||||
};
|
||||
|
||||
this->m_selectionChanged = this->m_selectionStart != start || this->m_selectionEnd != end;
|
||||
m_selectionChanged = m_selectionStart != start || m_selectionEnd != end;
|
||||
|
||||
if (!this->m_selectionStart.has_value()) this->m_selectionStart = start;
|
||||
if (!this->m_selectionEnd.has_value()) this->m_selectionEnd = end;
|
||||
if (!m_selectionStart.has_value()) m_selectionStart = start;
|
||||
if (!m_selectionEnd.has_value()) m_selectionEnd = end;
|
||||
|
||||
if (auto bytesPerCell = this->m_currDataVisualizer->getBytesPerCell(); bytesPerCell > 1) {
|
||||
if (auto bytesPerCell = m_currDataVisualizer->getBytesPerCell(); bytesPerCell > 1) {
|
||||
if (end > start) {
|
||||
start = alignDown(start, bytesPerCell);
|
||||
end = alignDown(end, bytesPerCell) + (bytesPerCell - 1);
|
||||
@@ -75,14 +75,14 @@ namespace hex::plugin::builtin::ui {
|
||||
}
|
||||
}
|
||||
|
||||
this->m_selectionStart = std::clamp<u128>(start, 0, maxAddress);
|
||||
this->m_selectionEnd = std::clamp<u128>(end, 0, maxAddress);
|
||||
this->m_cursorPosition = this->m_selectionEnd;
|
||||
m_selectionStart = std::clamp<u128>(start, 0, maxAddress);
|
||||
m_selectionEnd = std::clamp<u128>(end, 0, maxAddress);
|
||||
m_cursorPosition = m_selectionEnd;
|
||||
|
||||
if (this->m_selectionChanged) {
|
||||
if (m_selectionChanged) {
|
||||
auto selection = this->getSelection();
|
||||
EventRegionSelected::post(ImHexApi::HexEditor::ProviderRegion{ { selection.address, selection.size }, this->m_provider });
|
||||
this->m_shouldModifyValue = true;
|
||||
EventRegionSelected::post(ImHexApi::HexEditor::ProviderRegion{ { selection.address, selection.size }, m_provider });
|
||||
m_shouldModifyValue = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,138 +90,138 @@ namespace hex::plugin::builtin::ui {
|
||||
if (!isSelectionValid())
|
||||
return Region::Invalid();
|
||||
|
||||
const auto start = std::min(this->m_selectionStart.value(), this->m_selectionEnd.value());
|
||||
const auto end = std::max(this->m_selectionStart.value(), this->m_selectionEnd.value());
|
||||
const auto start = std::min(m_selectionStart.value(), m_selectionEnd.value());
|
||||
const auto end = std::max(m_selectionStart.value(), m_selectionEnd.value());
|
||||
const size_t size = end - start + 1;
|
||||
|
||||
return { start, size };
|
||||
}
|
||||
|
||||
[[nodiscard]] std::optional<u64> getCursorPosition() const {
|
||||
return this->m_cursorPosition;
|
||||
return m_cursorPosition;
|
||||
}
|
||||
|
||||
void setCursorPosition(u64 cursorPosition) {
|
||||
this->m_cursorPosition = cursorPosition;
|
||||
m_cursorPosition = cursorPosition;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool isSelectionValid() const {
|
||||
return this->m_selectionStart.has_value() && this->m_selectionEnd.has_value();
|
||||
return m_selectionStart.has_value() && m_selectionEnd.has_value();
|
||||
}
|
||||
|
||||
void jumpToSelection(bool center = true) {
|
||||
this->m_shouldJumpToSelection = true;
|
||||
m_shouldJumpToSelection = true;
|
||||
|
||||
if (center)
|
||||
this->m_centerOnJump = true;
|
||||
m_centerOnJump = true;
|
||||
}
|
||||
|
||||
void scrollToSelection() {
|
||||
this->m_shouldScrollToSelection = true;
|
||||
m_shouldScrollToSelection = true;
|
||||
}
|
||||
|
||||
void jumpIfOffScreen() {
|
||||
this->m_shouldJumpWhenOffScreen = true;
|
||||
m_shouldJumpWhenOffScreen = true;
|
||||
}
|
||||
|
||||
[[nodiscard]] u16 getBytesPerRow() const {
|
||||
return this->m_bytesPerRow;
|
||||
return m_bytesPerRow;
|
||||
}
|
||||
|
||||
[[nodiscard]] u16 getBytesPerCell() const {
|
||||
return this->m_currDataVisualizer->getBytesPerCell();
|
||||
return m_currDataVisualizer->getBytesPerCell();
|
||||
}
|
||||
|
||||
void setBytesPerRow(u16 bytesPerRow) {
|
||||
this->m_bytesPerRow = bytesPerRow;
|
||||
m_bytesPerRow = bytesPerRow;
|
||||
}
|
||||
|
||||
[[nodiscard]] u16 getVisibleRowCount() const {
|
||||
return this->m_visibleRowCount;
|
||||
return m_visibleRowCount;
|
||||
}
|
||||
|
||||
void setSelectionColor(color_t color) {
|
||||
this->m_selectionColor = color;
|
||||
m_selectionColor = color;
|
||||
}
|
||||
|
||||
void enableUpperCaseHex(bool upperCaseHex) {
|
||||
this->m_upperCaseHex = upperCaseHex;
|
||||
m_upperCaseHex = upperCaseHex;
|
||||
}
|
||||
|
||||
void enableGrayOutZeros(bool grayOutZeros) {
|
||||
this->m_grayOutZero = grayOutZeros;
|
||||
m_grayOutZero = grayOutZeros;
|
||||
}
|
||||
|
||||
void enableShowAscii(bool showAscii) {
|
||||
this->m_showAscii = showAscii;
|
||||
m_showAscii = showAscii;
|
||||
}
|
||||
|
||||
void enableShowHumanReadableUnits(bool showHumanReadableUnits) {
|
||||
this->m_showHumanReadableUnits = showHumanReadableUnits;
|
||||
m_showHumanReadableUnits = showHumanReadableUnits;
|
||||
}
|
||||
|
||||
void enableSyncScrolling(bool syncScrolling) {
|
||||
this->m_syncScrolling = syncScrolling;
|
||||
m_syncScrolling = syncScrolling;
|
||||
}
|
||||
|
||||
void setByteCellPadding(u32 byteCellPadding) {
|
||||
this->m_byteCellPadding = byteCellPadding;
|
||||
m_byteCellPadding = byteCellPadding;
|
||||
}
|
||||
|
||||
void setCharacterCellPadding(u32 characterCellPadding) {
|
||||
this->m_characterCellPadding = characterCellPadding;
|
||||
m_characterCellPadding = characterCellPadding;
|
||||
}
|
||||
|
||||
[[nodiscard]] const std::optional<EncodingFile>& getCustomEncoding() const {
|
||||
return this->m_currCustomEncoding;
|
||||
return m_currCustomEncoding;
|
||||
}
|
||||
|
||||
void setCustomEncoding(const EncodingFile &encoding) {
|
||||
this->m_currCustomEncoding = encoding;
|
||||
this->m_encodingLineStartAddresses.clear();
|
||||
m_currCustomEncoding = encoding;
|
||||
m_encodingLineStartAddresses.clear();
|
||||
}
|
||||
|
||||
void setCustomEncoding(EncodingFile &&encoding) {
|
||||
this->m_currCustomEncoding = std::move(encoding);
|
||||
this->m_encodingLineStartAddresses.clear();
|
||||
m_currCustomEncoding = std::move(encoding);
|
||||
m_encodingLineStartAddresses.clear();
|
||||
}
|
||||
|
||||
void forceUpdateScrollPosition() {
|
||||
this->m_shouldUpdateScrollPosition = true;
|
||||
m_shouldUpdateScrollPosition = true;
|
||||
}
|
||||
|
||||
void setForegroundHighlightCallback(const std::function<std::optional<color_t>(u64, const u8 *, size_t)> &callback) {
|
||||
this->m_foregroundColorCallback = callback;
|
||||
m_foregroundColorCallback = callback;
|
||||
}
|
||||
|
||||
void setBackgroundHighlightCallback(const std::function<std::optional<color_t>(u64, const u8 *, size_t)> &callback) {
|
||||
this->m_backgroundColorCallback = callback;
|
||||
m_backgroundColorCallback = callback;
|
||||
}
|
||||
|
||||
void setTooltipCallback(const std::function<void(u64, const u8 *, size_t)> &callback) {
|
||||
this->m_tooltipCallback = callback;
|
||||
m_tooltipCallback = callback;
|
||||
}
|
||||
|
||||
[[nodiscard]] float getScrollPosition() const {
|
||||
return this->m_scrollPosition;
|
||||
return m_scrollPosition;
|
||||
}
|
||||
|
||||
void setScrollPosition(float scrollPosition) {
|
||||
this->m_scrollPosition = scrollPosition;
|
||||
m_scrollPosition = scrollPosition;
|
||||
}
|
||||
|
||||
void setEditingAddress(u64 address) {
|
||||
this->m_editingAddress = address;
|
||||
this->m_shouldModifyValue = false;
|
||||
this->m_enteredEditingMode = true;
|
||||
m_editingAddress = address;
|
||||
m_shouldModifyValue = false;
|
||||
m_enteredEditingMode = true;
|
||||
|
||||
this->m_editingBytes.resize(this->m_currDataVisualizer->getBytesPerCell());
|
||||
this->m_provider->read(address + this->m_provider->getBaseAddress(), this->m_editingBytes.data(), this->m_editingBytes.size());
|
||||
this->m_editingCellType = CellType::Hex;
|
||||
m_editingBytes.resize(m_currDataVisualizer->getBytesPerCell());
|
||||
m_provider->read(address + m_provider->getBaseAddress(), m_editingBytes.data(), m_editingBytes.size());
|
||||
m_editingCellType = CellType::Hex;
|
||||
}
|
||||
|
||||
void clearEditingAddress() {
|
||||
this->m_editingAddress = std::nullopt;
|
||||
m_editingAddress = std::nullopt;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace hex::plugin::builtin::ui {
|
||||
class PatternDrawer : public pl::PatternVisitor {
|
||||
public:
|
||||
PatternDrawer() {
|
||||
this->m_formatters = pl::gen::fmt::createFormatters();
|
||||
m_formatters = pl::gen::fmt::createFormatters();
|
||||
}
|
||||
|
||||
virtual ~PatternDrawer() = default;
|
||||
@@ -30,9 +30,9 @@ namespace hex::plugin::builtin::ui {
|
||||
Flattened = 2
|
||||
};
|
||||
|
||||
void setTreeStyle(TreeStyle style) { this->m_treeStyle = style; }
|
||||
void setSelectionCallback(std::function<void(Region)> callback) { this->m_selectionCallback = std::move(callback); }
|
||||
void enableRowColoring(bool enabled) { this->m_rowColoring = enabled; }
|
||||
void setTreeStyle(TreeStyle style) { m_treeStyle = style; }
|
||||
void setSelectionCallback(std::function<void(Region)> callback) { m_selectionCallback = std::move(callback); }
|
||||
void enableRowColoring(bool enabled) { m_rowColoring = enabled; }
|
||||
void reset();
|
||||
|
||||
private:
|
||||
|
||||
@@ -180,12 +180,12 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
unitString = wolv::util::trim(unitString);
|
||||
this->m_unitString = unitString;
|
||||
m_unitString = unitString;
|
||||
if (unitString.empty()) {
|
||||
if (multiplier == 1)
|
||||
return { Unit::Unitless, 1 };
|
||||
else {
|
||||
this->m_unitString = unitStringCopy;
|
||||
m_unitString = unitStringCopy;
|
||||
return { Unit::Unitless, 1 };
|
||||
}
|
||||
|
||||
|
||||
@@ -29,27 +29,27 @@ namespace hex::plugin::builtin {
|
||||
constexpr static int StepSize = 1, FastStepSize = 10;
|
||||
|
||||
ImGui::PushItemWidth(100_scaled);
|
||||
ImGui::InputScalar("hex.builtin.nodes.constants.buffer.size"_lang, ImGuiDataType_U32, &this->m_size, &StepSize, &FastStepSize);
|
||||
ImGui::InputScalar("hex.builtin.nodes.constants.buffer.size"_lang, ImGuiDataType_U32, &m_size, &StepSize, &FastStepSize);
|
||||
ImGui::PopItemWidth();
|
||||
}
|
||||
|
||||
void process() override {
|
||||
if (this->m_buffer.size() != this->m_size)
|
||||
this->m_buffer.resize(this->m_size, 0x00);
|
||||
if (m_buffer.size() != m_size)
|
||||
m_buffer.resize(m_size, 0x00);
|
||||
|
||||
this->setBufferOnOutput(0, this->m_buffer);
|
||||
this->setBufferOnOutput(0, m_buffer);
|
||||
}
|
||||
|
||||
void store(nlohmann::json &j) const override {
|
||||
j = nlohmann::json::object();
|
||||
|
||||
j["size"] = this->m_size;
|
||||
j["data"] = this->m_buffer;
|
||||
j["size"] = m_size;
|
||||
j["data"] = m_buffer;
|
||||
}
|
||||
|
||||
void load(const nlohmann::json &j) override {
|
||||
this->m_size = j.at("size");
|
||||
this->m_buffer = j.at("data").get<std::vector<u8>>();
|
||||
m_size = j.at("size");
|
||||
m_buffer = j.at("data").get<std::vector<u8>>();
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -64,21 +64,21 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
void drawNode() override {
|
||||
ImGui::InputTextMultiline("##string", this->m_value, ImVec2(150_scaled, 0), ImGuiInputTextFlags_AllowTabInput);
|
||||
ImGui::InputTextMultiline("##string", m_value, ImVec2(150_scaled, 0), ImGuiInputTextFlags_AllowTabInput);
|
||||
}
|
||||
|
||||
void process() override {
|
||||
this->setBufferOnOutput(0, hex::decodeByteString(this->m_value));
|
||||
this->setBufferOnOutput(0, hex::decodeByteString(m_value));
|
||||
}
|
||||
|
||||
void store(nlohmann::json &j) const override {
|
||||
j = nlohmann::json::object();
|
||||
|
||||
j["data"] = this->m_value;
|
||||
j["data"] = m_value;
|
||||
}
|
||||
|
||||
void load(const nlohmann::json &j) override {
|
||||
this->m_value = j.at("data").get<std::string>();
|
||||
m_value = j.at("data").get<std::string>();
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -91,22 +91,22 @@ namespace hex::plugin::builtin {
|
||||
|
||||
void drawNode() override {
|
||||
ImGui::PushItemWidth(100_scaled);
|
||||
ImGuiExt::InputHexadecimal("##integer_value", &this->m_value);
|
||||
ImGuiExt::InputHexadecimal("##integer_value", &m_value);
|
||||
ImGui::PopItemWidth();
|
||||
}
|
||||
|
||||
void process() override {
|
||||
this->setIntegerOnOutput(0, this->m_value);
|
||||
this->setIntegerOnOutput(0, m_value);
|
||||
}
|
||||
|
||||
void store(nlohmann::json &j) const override {
|
||||
j = nlohmann::json::object();
|
||||
|
||||
j["data"] = this->m_value;
|
||||
j["data"] = m_value;
|
||||
}
|
||||
|
||||
void load(const nlohmann::json &j) override {
|
||||
this->m_value = j.at("data");
|
||||
m_value = j.at("data");
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -119,22 +119,22 @@ namespace hex::plugin::builtin {
|
||||
|
||||
void drawNode() override {
|
||||
ImGui::PushItemWidth(100_scaled);
|
||||
ImGui::InputScalar("##floatValue", ImGuiDataType_Float, &this->m_value, nullptr, nullptr, "%f", ImGuiInputTextFlags_CharsDecimal);
|
||||
ImGui::InputScalar("##floatValue", ImGuiDataType_Float, &m_value, nullptr, nullptr, "%f", ImGuiInputTextFlags_CharsDecimal);
|
||||
ImGui::PopItemWidth();
|
||||
}
|
||||
|
||||
void process() override {
|
||||
this->setFloatOnOutput(0, this->m_value);
|
||||
this->setFloatOnOutput(0, m_value);
|
||||
}
|
||||
|
||||
void store(nlohmann::json &j) const override {
|
||||
j = nlohmann::json::object();
|
||||
|
||||
j["data"] = this->m_value;
|
||||
j["data"] = m_value;
|
||||
}
|
||||
|
||||
void load(const nlohmann::json &j) override {
|
||||
this->m_value = j.at("data");
|
||||
m_value = j.at("data");
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -151,30 +151,30 @@ namespace hex::plugin::builtin {
|
||||
|
||||
void drawNode() override {
|
||||
ImGui::PushItemWidth(200_scaled);
|
||||
ImGui::ColorPicker4("##colorPicker", &this->m_color.Value.x, ImGuiColorEditFlags_AlphaBar);
|
||||
ImGui::ColorPicker4("##colorPicker", &m_color.Value.x, ImGuiColorEditFlags_AlphaBar);
|
||||
ImGui::PopItemWidth();
|
||||
}
|
||||
|
||||
void process() override {
|
||||
this->setBufferOnOutput(0, wolv::util::toBytes<u8>(u8(this->m_color.Value.x * 0xFF)));
|
||||
this->setBufferOnOutput(1, wolv::util::toBytes<u8>(u8(this->m_color.Value.y * 0xFF)));
|
||||
this->setBufferOnOutput(2, wolv::util::toBytes<u8>(u8(this->m_color.Value.z * 0xFF)));
|
||||
this->setBufferOnOutput(3, wolv::util::toBytes<u8>(u8(this->m_color.Value.w * 0xFF)));
|
||||
this->setBufferOnOutput(0, wolv::util::toBytes<u8>(u8(m_color.Value.x * 0xFF)));
|
||||
this->setBufferOnOutput(1, wolv::util::toBytes<u8>(u8(m_color.Value.y * 0xFF)));
|
||||
this->setBufferOnOutput(2, wolv::util::toBytes<u8>(u8(m_color.Value.z * 0xFF)));
|
||||
this->setBufferOnOutput(3, wolv::util::toBytes<u8>(u8(m_color.Value.w * 0xFF)));
|
||||
}
|
||||
|
||||
void store(nlohmann::json &j) const override {
|
||||
j = nlohmann::json::object();
|
||||
|
||||
j["data"] = nlohmann::json::object();
|
||||
j["data"]["r"] = this->m_color.Value.x;
|
||||
j["data"]["g"] = this->m_color.Value.y;
|
||||
j["data"]["b"] = this->m_color.Value.z;
|
||||
j["data"]["a"] = this->m_color.Value.w;
|
||||
j["data"]["r"] = m_color.Value.x;
|
||||
j["data"]["g"] = m_color.Value.y;
|
||||
j["data"]["b"] = m_color.Value.z;
|
||||
j["data"]["a"] = m_color.Value.w;
|
||||
}
|
||||
|
||||
void load(const nlohmann::json &j) override {
|
||||
const auto &color = j.at("data");
|
||||
this->m_color = ImVec4(color.at("r"), color.at("g"), color.at("b"), color.at("a"));
|
||||
m_color = ImVec4(color.at("r"), color.at("g"), color.at("b"), color.at("a"));
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -188,7 +188,7 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
void drawNode() override {
|
||||
ImGui::InputTextMultiline("##string", this->m_comment, scaled(ImVec2(150, 100)));
|
||||
ImGui::InputTextMultiline("##string", m_comment, scaled(ImVec2(150, 100)));
|
||||
}
|
||||
|
||||
void process() override {
|
||||
@@ -197,11 +197,11 @@ namespace hex::plugin::builtin {
|
||||
void store(nlohmann::json &j) const override {
|
||||
j = nlohmann::json::object();
|
||||
|
||||
j["comment"] = this->m_comment;
|
||||
j["comment"] = m_comment;
|
||||
}
|
||||
|
||||
void load(const nlohmann::json &j) override {
|
||||
this->m_comment = j["comment"].get<std::string>();
|
||||
m_comment = j["comment"].get<std::string>();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -19,8 +19,8 @@ namespace hex::plugin::builtin {
|
||||
|
||||
void drawNode() override {
|
||||
ImGui::PushItemWidth(100_scaled);
|
||||
ImGui::Combo("hex.builtin.nodes.crypto.aes.mode"_lang, &this->m_mode, "ECB\0CBC\0CFB128\0CTR\0GCM\0CCM\0OFB\0");
|
||||
ImGui::Combo("hex.builtin.nodes.crypto.aes.key_length"_lang, &this->m_keyLength, "128 Bits\000192 Bits\000256 Bits\000");
|
||||
ImGui::Combo("hex.builtin.nodes.crypto.aes.mode"_lang, &m_mode, "ECB\0CBC\0CFB128\0CTR\0GCM\0CCM\0OFB\0");
|
||||
ImGui::Combo("hex.builtin.nodes.crypto.aes.key_length"_lang, &m_keyLength, "128 Bits\000192 Bits\000256 Bits\000");
|
||||
ImGui::PopItemWidth();
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace hex::plugin::builtin {
|
||||
std::copy(iv.begin(), iv.end(), ivData.begin());
|
||||
std::copy(nonce.begin(), nonce.end(), nonceData.begin());
|
||||
|
||||
auto output = crypt::aesDecrypt(static_cast<crypt::AESMode>(this->m_mode), static_cast<crypt::KeyLength>(this->m_keyLength), key, nonceData, ivData, input);
|
||||
auto output = crypt::aesDecrypt(static_cast<crypt::AESMode>(m_mode), static_cast<crypt::KeyLength>(m_keyLength), key, nonceData, ivData, input);
|
||||
|
||||
this->setBufferOnOutput(4, output);
|
||||
}
|
||||
@@ -50,13 +50,13 @@ namespace hex::plugin::builtin {
|
||||
j = nlohmann::json::object();
|
||||
|
||||
j["data"] = nlohmann::json::object();
|
||||
j["data"]["mode"] = this->m_mode;
|
||||
j["data"]["key_length"] = this->m_keyLength;
|
||||
j["data"]["mode"] = m_mode;
|
||||
j["data"]["key_length"] = m_keyLength;
|
||||
}
|
||||
|
||||
void load(const nlohmann::json &j) override {
|
||||
this->m_mode = j["data"]["mode"];
|
||||
this->m_keyLength = j["data"]["key_length"];
|
||||
m_mode = j["data"]["mode"];
|
||||
m_keyLength = j["data"]["key_length"];
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -61,8 +61,8 @@ namespace hex::plugin::builtin {
|
||||
public:
|
||||
NodeDataSelection() : Node("hex.builtin.nodes.data_access.selection.header", { dp::Attribute(dp::Attribute::IOType::Out, dp::Attribute::Type::Integer, "hex.builtin.nodes.data_access.selection.address"), dp::Attribute(dp::Attribute::IOType::Out, dp::Attribute::Type::Integer, "hex.builtin.nodes.data_access.selection.size") }) {
|
||||
EventRegionSelected::subscribe(this, [this](const auto ®ion) {
|
||||
this->m_address = region.address;
|
||||
this->m_size = region.size;
|
||||
m_address = region.address;
|
||||
m_size = region.size;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -71,8 +71,8 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
void process() override {
|
||||
this->setIntegerOnOutput(0, this->m_address);
|
||||
this->setIntegerOnOutput(1, this->m_size);
|
||||
this->setIntegerOnOutput(0, m_address);
|
||||
this->setIntegerOnOutput(1, m_size);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -232,17 +232,17 @@ namespace hex::plugin::builtin {
|
||||
NodeVisualizerDigram() : Node("hex.builtin.nodes.visualizer.digram.header", { dp::Attribute(dp::Attribute::IOType::In, dp::Attribute::Type::Buffer, "hex.builtin.nodes.common.input") }) { }
|
||||
|
||||
void drawNode() override {
|
||||
this->m_digram.draw(scaled({ 200, 200 }));
|
||||
m_digram.draw(scaled({ 200, 200 }));
|
||||
|
||||
if (ImGui::IsItemHovered() && ImGui::IsKeyDown(ImGuiKey_LeftShift)) {
|
||||
ImGui::BeginTooltip();
|
||||
this->m_digram.draw(scaled({ 600, 600 }));
|
||||
m_digram.draw(scaled({ 600, 600 }));
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
}
|
||||
|
||||
void process() override {
|
||||
this->m_digram.process(this->getBufferOnInput(0));
|
||||
m_digram.process(this->getBufferOnInput(0));
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -254,16 +254,16 @@ namespace hex::plugin::builtin {
|
||||
NodeVisualizerLayeredDistribution() : Node("hex.builtin.nodes.visualizer.layered_dist.header", { dp::Attribute(dp::Attribute::IOType::In, dp::Attribute::Type::Buffer, "hex.builtin.nodes.common.input") }) { }
|
||||
|
||||
void drawNode() override {
|
||||
this->m_layeredDistribution.draw(scaled({ 200, 200 }));
|
||||
m_layeredDistribution.draw(scaled({ 200, 200 }));
|
||||
if (ImGui::IsItemHovered() && ImGui::IsKeyDown(ImGuiKey_LeftShift)) {
|
||||
ImGui::BeginTooltip();
|
||||
this->m_layeredDistribution.draw(scaled({ 600, 600 }));
|
||||
m_layeredDistribution.draw(scaled({ 600, 600 }));
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
}
|
||||
|
||||
void process() override {
|
||||
this->m_layeredDistribution.process(this->getBufferOnInput(0));
|
||||
m_layeredDistribution.process(this->getBufferOnInput(0));
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -275,10 +275,10 @@ namespace hex::plugin::builtin {
|
||||
NodeVisualizerImage() : Node("hex.builtin.nodes.visualizer.image.header", { dp::Attribute(dp::Attribute::IOType::In, dp::Attribute::Type::Buffer, "hex.builtin.nodes.common.input") }) { }
|
||||
|
||||
void drawNode() override {
|
||||
ImGui::Image(this->m_texture, scaled(ImVec2(this->m_texture.getAspectRatio() * 200, 200)));
|
||||
ImGui::Image(m_texture, scaled(ImVec2(m_texture.getAspectRatio() * 200, 200)));
|
||||
if (ImGui::IsItemHovered() && ImGui::IsKeyDown(ImGuiKey_LeftShift)) {
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::Image(this->m_texture, scaled(ImVec2(this->m_texture.getAspectRatio() * 600, 600)));
|
||||
ImGui::Image(m_texture, scaled(ImVec2(m_texture.getAspectRatio() * 600, 600)));
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
}
|
||||
@@ -286,7 +286,7 @@ namespace hex::plugin::builtin {
|
||||
void process() override {
|
||||
const auto &rawData = this->getBufferOnInput(0);
|
||||
|
||||
this->m_texture = ImGuiExt::Texture(rawData.data(), rawData.size(), ImGuiExt::Texture::Filter::Nearest);
|
||||
m_texture = ImGuiExt::Texture(rawData.data(), rawData.size(), ImGuiExt::Texture::Filter::Nearest);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -298,16 +298,16 @@ namespace hex::plugin::builtin {
|
||||
NodeVisualizerImageRGBA() : Node("hex.builtin.nodes.visualizer.image_rgba.header", { dp::Attribute(dp::Attribute::IOType::In, dp::Attribute::Type::Buffer, "hex.builtin.nodes.common.input"), dp::Attribute(dp::Attribute::IOType::In, dp::Attribute::Type::Integer, "hex.builtin.nodes.common.width"), dp::Attribute(dp::Attribute::IOType::In, dp::Attribute::Type::Integer, "hex.builtin.nodes.common.height") }) { }
|
||||
|
||||
void drawNode() override {
|
||||
ImGui::Image(this->m_texture, scaled(ImVec2(this->m_texture.getAspectRatio() * 200, 200)));
|
||||
ImGui::Image(m_texture, scaled(ImVec2(m_texture.getAspectRatio() * 200, 200)));
|
||||
if (ImGui::IsItemHovered() && ImGui::IsKeyDown(ImGuiKey_LeftShift)) {
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::Image(this->m_texture, scaled(ImVec2(this->m_texture.getAspectRatio() * 600, 600)));
|
||||
ImGui::Image(m_texture, scaled(ImVec2(m_texture.getAspectRatio() * 600, 600)));
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
}
|
||||
|
||||
void process() override {
|
||||
this->m_texture = { };
|
||||
m_texture = { };
|
||||
|
||||
const auto &rawData = this->getBufferOnInput(0);
|
||||
const auto &width = this->getIntegerOnInput(1);
|
||||
@@ -317,7 +317,7 @@ namespace hex::plugin::builtin {
|
||||
if (requiredBytes > rawData.size())
|
||||
throwNodeError(hex::format("Image requires at least {} bytes of data, but only {} bytes are available", requiredBytes, rawData.size()));
|
||||
|
||||
this->m_texture = ImGuiExt::Texture(rawData.data(), rawData.size(), ImGuiExt::Texture::Filter::Nearest, width, height);
|
||||
m_texture = ImGuiExt::Texture(rawData.data(), rawData.size(), ImGuiExt::Texture::Filter::Nearest, width, height);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -342,7 +342,7 @@ namespace hex::plugin::builtin {
|
||||
if (ImPlot::BeginPlot("##distribution", viewSize, ImPlotFlags_NoLegend | ImPlotFlags_NoMenus | ImPlotFlags_NoBoxSelect)) {
|
||||
ImPlot::SetupAxes("Address", "Count", ImPlotAxisFlags_Lock, ImPlotAxisFlags_Lock);
|
||||
ImPlot::SetupAxisScale(ImAxis_Y1, ImPlotScale_Log10);
|
||||
ImPlot::SetupAxesLimits(0, 256, 1, double(*std::max_element(this->m_counts.begin(), this->m_counts.end())) * 1.1F, ImGuiCond_Always);
|
||||
ImPlot::SetupAxesLimits(0, 256, 1, double(*std::max_element(m_counts.begin(), m_counts.end())) * 1.1F, ImGuiCond_Always);
|
||||
|
||||
static auto x = [] {
|
||||
std::array<ImU64, 256> result { 0 };
|
||||
@@ -351,7 +351,7 @@ namespace hex::plugin::builtin {
|
||||
}();
|
||||
|
||||
|
||||
ImPlot::PlotBars<ImU64>("##bytes", x.data(), this->m_counts.data(), x.size(), 1);
|
||||
ImPlot::PlotBars<ImU64>("##bytes", x.data(), m_counts.data(), x.size(), 1);
|
||||
|
||||
ImPlot::EndPlot();
|
||||
}
|
||||
@@ -360,9 +360,9 @@ namespace hex::plugin::builtin {
|
||||
void process() override {
|
||||
const auto &buffer = this->getBufferOnInput(0);
|
||||
|
||||
this->m_counts.fill(0x00);
|
||||
m_counts.fill(0x00);
|
||||
for (const auto &byte : buffer) {
|
||||
this->m_counts[byte]++;
|
||||
m_counts[byte]++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -377,7 +377,7 @@ namespace hex::plugin::builtin {
|
||||
|
||||
void drawNode() override {
|
||||
ImGui::PushItemWidth(100_scaled);
|
||||
ImGui::InputText("##name", this->m_name);
|
||||
ImGui::InputText("##name", m_name);
|
||||
ImGui::PopItemWidth();
|
||||
}
|
||||
|
||||
@@ -387,7 +387,7 @@ namespace hex::plugin::builtin {
|
||||
|
||||
const auto &outVars = runtime.getOutVariables();
|
||||
|
||||
if (outVars.contains(this->m_name)) {
|
||||
if (outVars.contains(m_name)) {
|
||||
std::visit(wolv::util::overloaded {
|
||||
[](const std::string &) {},
|
||||
[](pl::ptrn::Pattern *) {},
|
||||
@@ -397,20 +397,20 @@ namespace hex::plugin::builtin {
|
||||
|
||||
this->setBufferOnOutput(0, buffer);
|
||||
}
|
||||
}, outVars.at(this->m_name));
|
||||
}, outVars.at(m_name));
|
||||
} else {
|
||||
throwNodeError(hex::format("Out variable '{}' has not been defined!", this->m_name));
|
||||
throwNodeError(hex::format("Out variable '{}' has not been defined!", m_name));
|
||||
}
|
||||
}
|
||||
|
||||
void store(nlohmann::json &j) const override {
|
||||
j = nlohmann::json::object();
|
||||
|
||||
j["name"] = this->m_name;
|
||||
j["name"] = m_name;
|
||||
}
|
||||
|
||||
void load(const nlohmann::json &j) override {
|
||||
this->m_name = j["name"].get<std::string>();
|
||||
m_name = j["name"].get<std::string>();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -11,18 +11,18 @@ namespace hex::plugin::builtin {
|
||||
|
||||
void drawNode() override {
|
||||
ImGui::PushItemWidth(150_scaled);
|
||||
if (this->m_value.has_value())
|
||||
ImGuiExt::TextFormatted("0x{0:X}", this->m_value.value());
|
||||
if (m_value.has_value())
|
||||
ImGuiExt::TextFormatted("0x{0:X}", m_value.value());
|
||||
else
|
||||
ImGui::TextUnformatted("???");
|
||||
ImGui::PopItemWidth();
|
||||
}
|
||||
|
||||
void process() override {
|
||||
this->m_value.reset();
|
||||
m_value.reset();
|
||||
const auto &input = this->getIntegerOnInput(0);
|
||||
|
||||
this->m_value = input;
|
||||
m_value = input;
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -35,18 +35,18 @@ namespace hex::plugin::builtin {
|
||||
|
||||
void drawNode() override {
|
||||
ImGui::PushItemWidth(150_scaled);
|
||||
if (this->m_value.has_value())
|
||||
ImGuiExt::TextFormatted("{0}", this->m_value.value());
|
||||
if (m_value.has_value())
|
||||
ImGuiExt::TextFormatted("{0}", m_value.value());
|
||||
else
|
||||
ImGui::TextUnformatted("???");
|
||||
ImGui::PopItemWidth();
|
||||
}
|
||||
|
||||
void process() override {
|
||||
this->m_value.reset();
|
||||
m_value.reset();
|
||||
const auto &input = this->getFloatOnInput(0);
|
||||
|
||||
this->m_value = input;
|
||||
m_value = input;
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -63,7 +63,7 @@ namespace hex::plugin::builtin {
|
||||
if (ImGui::BeginChild("##hex_view", scaled(ImVec2(ImGui::CalcTextSize(Header.c_str()).x, 200)), true)) {
|
||||
ImGui::TextUnformatted(Header.c_str());
|
||||
|
||||
auto size = this->m_buffer.size();
|
||||
auto size = m_buffer.size();
|
||||
ImGuiListClipper clipper;
|
||||
|
||||
clipper.Begin((size + 0x0F) / 0x10);
|
||||
@@ -75,7 +75,7 @@ namespace hex::plugin::builtin {
|
||||
std::string line = hex::format(" {:08X}: ", y * 0x10);
|
||||
for (u32 x = 0; x < 0x10; x++) {
|
||||
if (x < lineSize)
|
||||
line += hex::format("{:02X} ", this->m_buffer[y * 0x10 + x]);
|
||||
line += hex::format("{:02X} ", m_buffer[y * 0x10 + x]);
|
||||
else
|
||||
line += " ";
|
||||
|
||||
@@ -85,7 +85,7 @@ namespace hex::plugin::builtin {
|
||||
line += " ";
|
||||
|
||||
for (u32 x = 0; x < lineSize; x++) {
|
||||
auto c = char(this->m_buffer[y * 0x10 + x]);
|
||||
auto c = char(m_buffer[y * 0x10 + x]);
|
||||
if (std::isprint(c))
|
||||
line += c;
|
||||
else
|
||||
@@ -100,7 +100,7 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
void process() override {
|
||||
this->m_buffer = this->getBufferOnInput(0);
|
||||
m_buffer = this->getBufferOnInput(0);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -114,7 +114,7 @@ namespace hex::plugin::builtin {
|
||||
void drawNode() override {
|
||||
constexpr static auto LineLength = 50;
|
||||
if (ImGui::BeginChild("##string_view", scaled(ImVec2(ImGui::CalcTextSize(" ").x * (LineLength + 4), 150)), true)) {
|
||||
std::string_view string = this->m_value;
|
||||
std::string_view string = m_value;
|
||||
|
||||
ImGuiListClipper clipper;
|
||||
clipper.Begin((string.length() + (LineLength - 1)) / LineLength);
|
||||
@@ -135,7 +135,7 @@ namespace hex::plugin::builtin {
|
||||
void process() override {
|
||||
const auto &input = this->getBufferOnInput(0);
|
||||
|
||||
this->m_value = hex::encodeByteString(input);
|
||||
m_value = hex::encodeByteString(input);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -148,7 +148,7 @@ namespace hex::plugin::builtin {
|
||||
|
||||
void drawNode() override {
|
||||
ImGui::PushItemWidth(100_scaled);
|
||||
ImGui::Text("%s", this->m_display.c_str());
|
||||
ImGui::Text("%s", m_display.c_str());
|
||||
ImGui::PopItemWidth();
|
||||
}
|
||||
|
||||
@@ -165,7 +165,7 @@ namespace hex::plugin::builtin {
|
||||
display += (byte & (1 << i)) != 0 ? '1' : '0';
|
||||
}
|
||||
}
|
||||
this->m_display = wolv::util::trim(display);
|
||||
m_display = wolv::util::trim(display);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -236,16 +236,16 @@ namespace hex::plugin::builtin {
|
||||
hex::unused(address, data, size, upperCase);
|
||||
|
||||
if (startedEditing) {
|
||||
this->m_currColor = { float(data[0]) / 0xFF, float(data[1]) / 0xFF, float(data[2]) / 0xFF, float(data[3]) / 0xFF };
|
||||
m_currColor = { float(data[0]) / 0xFF, float(data[1]) / 0xFF, float(data[2]) / 0xFF, float(data[3]) / 0xFF };
|
||||
ImGui::OpenPopup("##color_popup");
|
||||
}
|
||||
|
||||
ImGui::ColorButton("##color", ImColor(this->m_currColor[0], this->m_currColor[1], this->m_currColor[2], this->m_currColor[3]), ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_NoLabel | ImGuiColorEditFlags_NoDragDrop, ImVec2(ImGui::GetColumnWidth(), ImGui::GetTextLineHeight()));
|
||||
ImGui::ColorButton("##color", ImColor(m_currColor[0], m_currColor[1], m_currColor[2], m_currColor[3]), ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_NoLabel | ImGuiColorEditFlags_NoDragDrop, ImVec2(ImGui::GetColumnWidth(), ImGui::GetTextLineHeight()));
|
||||
|
||||
if (ImGui::BeginPopup("##color_popup")) {
|
||||
if (ImGui::ColorPicker4("##picker", this->m_currColor.data(), ImGuiColorEditFlags_AlphaBar)) {
|
||||
if (ImGui::ColorPicker4("##picker", m_currColor.data(), ImGuiColorEditFlags_AlphaBar)) {
|
||||
for (u8 i = 0; i < 4; i++)
|
||||
data[i] = this->m_currColor[i] * 0xFF;
|
||||
data[i] = m_currColor[i] * 0xFF;
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
} else {
|
||||
@@ -274,11 +274,11 @@ namespace hex::plugin::builtin {
|
||||
hex::unused(address, startedEditing);
|
||||
|
||||
if (startedEditing) {
|
||||
this->m_inputBuffer = hex::format("{:08b}", *data);
|
||||
m_inputBuffer = hex::format("{:08b}", *data);
|
||||
}
|
||||
|
||||
if (drawDefaultTextEditingTextBox(address, this->m_inputBuffer, ImGuiInputTextFlags_None)) {
|
||||
if (auto result = hex::parseBinaryString(wolv::util::trim(this->m_inputBuffer)); result.has_value()) {
|
||||
if (drawDefaultTextEditingTextBox(address, m_inputBuffer, ImGuiInputTextFlags_None)) {
|
||||
if (auto result = hex::parseBinaryString(wolv::util::trim(m_inputBuffer)); result.has_value()) {
|
||||
*data = result.value();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -112,14 +112,14 @@ namespace hex::plugin::builtin {
|
||||
: Hash(name), m_crcFunction(crcFunction), m_polynomial(polynomial), m_initialValue(initialValue), m_xorOut(xorOut), m_reflectIn(reflectIn), m_reflectOut(reflectOut) {}
|
||||
|
||||
void draw() override {
|
||||
ImGuiExt::InputHexadecimal("hex.builtin.hash.crc.poly"_lang, &this->m_polynomial);
|
||||
ImGuiExt::InputHexadecimal("hex.builtin.hash.crc.iv"_lang, &this->m_initialValue);
|
||||
ImGuiExt::InputHexadecimal("hex.builtin.hash.crc.xor_out"_lang, &this->m_xorOut);
|
||||
ImGuiExt::InputHexadecimal("hex.builtin.hash.crc.poly"_lang, &m_polynomial);
|
||||
ImGuiExt::InputHexadecimal("hex.builtin.hash.crc.iv"_lang, &m_initialValue);
|
||||
ImGuiExt::InputHexadecimal("hex.builtin.hash.crc.xor_out"_lang, &m_xorOut);
|
||||
|
||||
ImGui::NewLine();
|
||||
|
||||
ImGui::Checkbox("hex.builtin.hash.crc.refl_in"_lang, &this->m_reflectIn);
|
||||
ImGui::Checkbox("hex.builtin.hash.crc.refl_out"_lang, &this->m_reflectOut);
|
||||
ImGui::Checkbox("hex.builtin.hash.crc.refl_in"_lang, &m_reflectIn);
|
||||
ImGui::Checkbox("hex.builtin.hash.crc.refl_out"_lang, &m_reflectOut);
|
||||
}
|
||||
|
||||
Function create(std::string name) override {
|
||||
@@ -139,22 +139,22 @@ namespace hex::plugin::builtin {
|
||||
[[nodiscard]] nlohmann::json store() const override {
|
||||
nlohmann::json result;
|
||||
|
||||
result["polynomial"] = this->m_polynomial;
|
||||
result["initialValue"] = this->m_initialValue;
|
||||
result["xorOut"] = this->m_xorOut;
|
||||
result["reflectIn"] = this->m_reflectIn;
|
||||
result["reflectOut"] = this->m_reflectOut;
|
||||
result["polynomial"] = m_polynomial;
|
||||
result["initialValue"] = m_initialValue;
|
||||
result["xorOut"] = m_xorOut;
|
||||
result["reflectIn"] = m_reflectIn;
|
||||
result["reflectOut"] = m_reflectOut;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void load(const nlohmann::json &json) override {
|
||||
try {
|
||||
this->m_polynomial = json.at("polynomial");
|
||||
this->m_initialValue = json.at("initialValue");
|
||||
this->m_xorOut = json.at("xorOut");
|
||||
this->m_reflectIn = json.at("reflectIn");
|
||||
this->m_reflectOut = json.at("reflectOut");
|
||||
m_polynomial = json.at("polynomial");
|
||||
m_initialValue = json.at("initialValue");
|
||||
m_xorOut = json.at("xorOut");
|
||||
m_reflectIn = json.at("reflectIn");
|
||||
m_reflectOut = json.at("reflectOut");
|
||||
} catch (std::exception&) { }
|
||||
}
|
||||
|
||||
|
||||
@@ -50,21 +50,21 @@ namespace hex::plugin::builtin {
|
||||
bool DiskProvider::isAvailable() const {
|
||||
#if defined(OS_WINDOWS)
|
||||
|
||||
return this->m_diskHandle != INVALID_HANDLE_VALUE;
|
||||
return m_diskHandle != INVALID_HANDLE_VALUE;
|
||||
|
||||
#else
|
||||
|
||||
return this->m_diskHandle != -1;
|
||||
return m_diskHandle != -1;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
bool DiskProvider::isReadable() const {
|
||||
return this->m_readable;
|
||||
return m_readable;
|
||||
}
|
||||
|
||||
bool DiskProvider::isWritable() const {
|
||||
return this->m_writable;
|
||||
return m_writable;
|
||||
}
|
||||
|
||||
bool DiskProvider::isResizable() const {
|
||||
@@ -77,7 +77,7 @@ namespace hex::plugin::builtin {
|
||||
|
||||
|
||||
void DiskProvider::setPath(const std::fs::path &path) {
|
||||
this->m_path = path;
|
||||
m_path = path;
|
||||
}
|
||||
|
||||
#if defined (OS_LINUX)
|
||||
@@ -143,19 +143,19 @@ namespace hex::plugin::builtin {
|
||||
#endif
|
||||
|
||||
bool DiskProvider::open() {
|
||||
this->m_readable = true;
|
||||
this->m_writable = true;
|
||||
m_readable = true;
|
||||
m_writable = true;
|
||||
|
||||
#if defined(OS_WINDOWS)
|
||||
|
||||
const auto &path = this->m_path.native();
|
||||
const auto &path = m_path.native();
|
||||
|
||||
this->m_diskHandle = CreateFileW(path.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||
if (this->m_diskHandle == INVALID_HANDLE_VALUE) {
|
||||
this->m_diskHandle = CreateFileW(path.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||
this->m_writable = false;
|
||||
m_diskHandle = CreateFileW(path.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||
if (m_diskHandle == INVALID_HANDLE_VALUE) {
|
||||
m_diskHandle = CreateFileW(path.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||
m_writable = false;
|
||||
|
||||
if (this->m_diskHandle == INVALID_HANDLE_VALUE)
|
||||
if (m_diskHandle == INVALID_HANDLE_VALUE)
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -163,7 +163,7 @@ namespace hex::plugin::builtin {
|
||||
DISK_GEOMETRY_EX diskGeometry = { };
|
||||
DWORD bytesRead = 0;
|
||||
if (DeviceIoControl(
|
||||
this->m_diskHandle,
|
||||
m_diskHandle,
|
||||
IOCTL_DISK_GET_DRIVE_GEOMETRY_EX,
|
||||
nullptr,
|
||||
0,
|
||||
@@ -171,45 +171,45 @@ namespace hex::plugin::builtin {
|
||||
sizeof(DISK_GEOMETRY_EX),
|
||||
&bytesRead,
|
||||
nullptr)) {
|
||||
this->m_diskSize = diskGeometry.DiskSize.QuadPart;
|
||||
this->m_sectorSize = diskGeometry.Geometry.BytesPerSector;
|
||||
this->m_sectorBuffer.resize(this->m_sectorSize);
|
||||
m_diskSize = diskGeometry.DiskSize.QuadPart;
|
||||
m_sectorSize = diskGeometry.Geometry.BytesPerSector;
|
||||
m_sectorBuffer.resize(m_sectorSize);
|
||||
}
|
||||
}
|
||||
|
||||
if (this->m_diskHandle == nullptr || this->m_diskHandle == INVALID_HANDLE_VALUE) {
|
||||
this->m_readable = false;
|
||||
this->m_diskHandle = nullptr;
|
||||
CloseHandle(this->m_diskHandle);
|
||||
if (m_diskHandle == nullptr || m_diskHandle == INVALID_HANDLE_VALUE) {
|
||||
m_readable = false;
|
||||
m_diskHandle = nullptr;
|
||||
CloseHandle(m_diskHandle);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
const auto &path = this->m_path.native();
|
||||
const auto &path = m_path.native();
|
||||
|
||||
this->m_diskHandle = ::open(path.c_str(), O_RDWR);
|
||||
if (this->m_diskHandle == -1) {
|
||||
m_diskHandle = ::open(path.c_str(), O_RDWR);
|
||||
if (m_diskHandle == -1) {
|
||||
this->setErrorMessage(hex::format("hex.builtin.provider.disk.error.read_rw"_lang, path, ::strerror(errno)));
|
||||
log::warn(this->getErrorMessage());
|
||||
this->m_diskHandle = ::open(path.c_str(), O_RDONLY);
|
||||
this->m_writable = false;
|
||||
m_diskHandle = ::open(path.c_str(), O_RDONLY);
|
||||
m_writable = false;
|
||||
}
|
||||
|
||||
if (this->m_diskHandle == -1) {
|
||||
if (m_diskHandle == -1) {
|
||||
this->setErrorMessage(hex::format("hex.builtin.provider.disk.error.read_ro"_lang, path, ::strerror(errno)));
|
||||
log::warn(this->getErrorMessage());
|
||||
this->m_readable = false;
|
||||
m_readable = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
u64 diskSize = 0;
|
||||
blkdev_get_size(this->m_diskHandle, &diskSize);
|
||||
this->m_diskSize = diskSize;
|
||||
blkdev_get_sector_size(this->m_diskHandle, reinterpret_cast<int *>(&this->m_sectorSize));
|
||||
blkdev_get_size(m_diskHandle, &diskSize);
|
||||
m_diskSize = diskSize;
|
||||
blkdev_get_sector_size(m_diskHandle, reinterpret_cast<int *>(&m_sectorSize));
|
||||
|
||||
this->m_sectorBuffer.resize(this->m_sectorSize);
|
||||
m_sectorBuffer.resize(m_sectorSize);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -219,17 +219,17 @@ namespace hex::plugin::builtin {
|
||||
void DiskProvider::close() {
|
||||
#if defined(OS_WINDOWS)
|
||||
|
||||
if (this->m_diskHandle != INVALID_HANDLE_VALUE)
|
||||
::CloseHandle(this->m_diskHandle);
|
||||
if (m_diskHandle != INVALID_HANDLE_VALUE)
|
||||
::CloseHandle(m_diskHandle);
|
||||
|
||||
this->m_diskHandle = INVALID_HANDLE_VALUE;
|
||||
m_diskHandle = INVALID_HANDLE_VALUE;
|
||||
|
||||
#else
|
||||
|
||||
if (this->m_diskHandle != -1)
|
||||
::close(this->m_diskHandle);
|
||||
if (m_diskHandle != -1)
|
||||
::close(m_diskHandle);
|
||||
|
||||
this->m_diskHandle = -1;
|
||||
m_diskHandle = -1;
|
||||
|
||||
#endif
|
||||
}
|
||||
@@ -243,19 +243,19 @@ namespace hex::plugin::builtin {
|
||||
|
||||
while (size > 0) {
|
||||
LARGE_INTEGER seekPosition;
|
||||
seekPosition.LowPart = (offset & 0xFFFF'FFFF) - (offset % this->m_sectorSize);
|
||||
seekPosition.LowPart = (offset & 0xFFFF'FFFF) - (offset % m_sectorSize);
|
||||
seekPosition.HighPart = LONG(offset >> 32);
|
||||
|
||||
if (this->m_sectorBufferAddress != static_cast<u64>(seekPosition.QuadPart)) {
|
||||
::SetFilePointer(this->m_diskHandle, seekPosition.LowPart, &seekPosition.HighPart, FILE_BEGIN);
|
||||
::ReadFile(this->m_diskHandle, this->m_sectorBuffer.data(), this->m_sectorBuffer.size(), &bytesRead, nullptr);
|
||||
this->m_sectorBufferAddress = seekPosition.QuadPart;
|
||||
if (m_sectorBufferAddress != static_cast<u64>(seekPosition.QuadPart)) {
|
||||
::SetFilePointer(m_diskHandle, seekPosition.LowPart, &seekPosition.HighPart, FILE_BEGIN);
|
||||
::ReadFile(m_diskHandle, m_sectorBuffer.data(), m_sectorBuffer.size(), &bytesRead, nullptr);
|
||||
m_sectorBufferAddress = seekPosition.QuadPart;
|
||||
}
|
||||
|
||||
std::memcpy(static_cast<u8 *>(buffer) + (offset - startOffset), this->m_sectorBuffer.data() + (offset & (this->m_sectorSize - 1)), std::min<u64>(this->m_sectorSize, size));
|
||||
std::memcpy(static_cast<u8 *>(buffer) + (offset - startOffset), m_sectorBuffer.data() + (offset & (m_sectorSize - 1)), std::min<u64>(m_sectorSize, size));
|
||||
|
||||
size = std::max<ssize_t>(static_cast<ssize_t>(size) - this->m_sectorSize, 0);
|
||||
offset += this->m_sectorSize;
|
||||
size = std::max<ssize_t>(static_cast<ssize_t>(size) - m_sectorSize, 0);
|
||||
offset += m_sectorSize;
|
||||
}
|
||||
|
||||
#else
|
||||
@@ -263,22 +263,22 @@ namespace hex::plugin::builtin {
|
||||
u64 startOffset = offset;
|
||||
|
||||
while (size > 0) {
|
||||
u64 seekPosition = offset - (offset % this->m_sectorSize);
|
||||
u64 seekPosition = offset - (offset % m_sectorSize);
|
||||
|
||||
if (this->m_sectorBufferAddress != seekPosition || this->m_sectorBufferAddress == 0) {
|
||||
::lseek(this->m_diskHandle, seekPosition, SEEK_SET);
|
||||
if (::read(this->m_diskHandle, this->m_sectorBuffer.data(), this->m_sectorBuffer.size()) == -1)
|
||||
if (m_sectorBufferAddress != seekPosition || m_sectorBufferAddress == 0) {
|
||||
::lseek(m_diskHandle, seekPosition, SEEK_SET);
|
||||
if (::read(m_diskHandle, m_sectorBuffer.data(), m_sectorBuffer.size()) == -1)
|
||||
break;
|
||||
|
||||
this->m_sectorBufferAddress = seekPosition;
|
||||
m_sectorBufferAddress = seekPosition;
|
||||
}
|
||||
|
||||
std::memcpy(reinterpret_cast<u8 *>(buffer) + (offset - startOffset),
|
||||
this->m_sectorBuffer.data() + (offset & (this->m_sectorSize - 1)),
|
||||
std::min<u64>(this->m_sectorSize, size));
|
||||
m_sectorBuffer.data() + (offset & (m_sectorSize - 1)),
|
||||
std::min<u64>(m_sectorSize, size));
|
||||
|
||||
size = std::max<ssize_t>(static_cast<ssize_t>(size) - this->m_sectorSize, 0);
|
||||
offset += this->m_sectorSize;
|
||||
size = std::max<ssize_t>(static_cast<ssize_t>(size) - m_sectorSize, 0);
|
||||
offset += m_sectorSize;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -292,21 +292,21 @@ namespace hex::plugin::builtin {
|
||||
u64 startOffset = offset;
|
||||
|
||||
std::vector<u8> modifiedSectorBuffer;
|
||||
modifiedSectorBuffer.resize(this->m_sectorSize);
|
||||
modifiedSectorBuffer.resize(m_sectorSize);
|
||||
|
||||
while (size > 0) {
|
||||
u64 sectorBase = offset - (offset % this->m_sectorSize);
|
||||
size_t currSize = std::min<u64>(size, this->m_sectorSize);
|
||||
u64 sectorBase = offset - (offset % m_sectorSize);
|
||||
size_t currSize = std::min<u64>(size, m_sectorSize);
|
||||
|
||||
this->readRaw(sectorBase, modifiedSectorBuffer.data(), modifiedSectorBuffer.size());
|
||||
std::memcpy(modifiedSectorBuffer.data() + ((offset - sectorBase) % this->m_sectorSize), reinterpret_cast<const u8 *>(buffer) + (startOffset - offset), currSize);
|
||||
std::memcpy(modifiedSectorBuffer.data() + ((offset - sectorBase) % m_sectorSize), reinterpret_cast<const u8 *>(buffer) + (startOffset - offset), currSize);
|
||||
|
||||
LARGE_INTEGER seekPosition;
|
||||
seekPosition.LowPart = (offset & 0xFFFF'FFFF) - (offset % this->m_sectorSize);
|
||||
seekPosition.LowPart = (offset & 0xFFFF'FFFF) - (offset % m_sectorSize);
|
||||
seekPosition.HighPart = offset >> 32;
|
||||
|
||||
::SetFilePointer(this->m_diskHandle, seekPosition.LowPart, &seekPosition.HighPart, FILE_BEGIN);
|
||||
::WriteFile(this->m_diskHandle, modifiedSectorBuffer.data(), modifiedSectorBuffer.size(), &bytesWritten, nullptr);
|
||||
::SetFilePointer(m_diskHandle, seekPosition.LowPart, &seekPosition.HighPart, FILE_BEGIN);
|
||||
::WriteFile(m_diskHandle, modifiedSectorBuffer.data(), modifiedSectorBuffer.size(), &bytesWritten, nullptr);
|
||||
|
||||
offset += currSize;
|
||||
size -= currSize;
|
||||
@@ -317,17 +317,17 @@ namespace hex::plugin::builtin {
|
||||
u64 startOffset = offset;
|
||||
|
||||
std::vector<u8> modifiedSectorBuffer;
|
||||
modifiedSectorBuffer.resize(this->m_sectorSize);
|
||||
modifiedSectorBuffer.resize(m_sectorSize);
|
||||
|
||||
while (size > 0) {
|
||||
u64 sectorBase = offset - (offset % this->m_sectorSize);
|
||||
size_t currSize = std::min<u64>(size, this->m_sectorSize);
|
||||
u64 sectorBase = offset - (offset % m_sectorSize);
|
||||
size_t currSize = std::min<u64>(size, m_sectorSize);
|
||||
|
||||
this->readRaw(sectorBase, modifiedSectorBuffer.data(), modifiedSectorBuffer.size());
|
||||
std::memcpy(modifiedSectorBuffer.data() + ((offset - sectorBase) % this->m_sectorSize), reinterpret_cast<const u8 *>(buffer) + (startOffset - offset), currSize);
|
||||
std::memcpy(modifiedSectorBuffer.data() + ((offset - sectorBase) % m_sectorSize), reinterpret_cast<const u8 *>(buffer) + (startOffset - offset), currSize);
|
||||
|
||||
::lseek(this->m_diskHandle, sectorBase, SEEK_SET);
|
||||
if (::write(this->m_diskHandle, modifiedSectorBuffer.data(), modifiedSectorBuffer.size()) < 0)
|
||||
::lseek(m_diskHandle, sectorBase, SEEK_SET);
|
||||
if (::write(m_diskHandle, modifiedSectorBuffer.data(), modifiedSectorBuffer.size()) < 0)
|
||||
break;
|
||||
|
||||
offset += currSize;
|
||||
@@ -338,21 +338,21 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
u64 DiskProvider::getActualSize() const {
|
||||
return this->m_diskSize;
|
||||
return m_diskSize;
|
||||
}
|
||||
|
||||
std::string DiskProvider::getName() const {
|
||||
if (this->m_friendlyName.empty())
|
||||
return wolv::util::toUTF8String(this->m_path);
|
||||
if (m_friendlyName.empty())
|
||||
return wolv::util::toUTF8String(m_path);
|
||||
else
|
||||
return this->m_friendlyName;
|
||||
return m_friendlyName;
|
||||
}
|
||||
|
||||
std::vector<DiskProvider::Description> DiskProvider::getDataDescription() const {
|
||||
return {
|
||||
{ "hex.builtin.provider.disk.selected_disk"_lang, wolv::util::toUTF8String(this->m_path) },
|
||||
{ "hex.builtin.provider.disk.disk_size"_lang, hex::toByteString(this->m_diskSize) },
|
||||
{ "hex.builtin.provider.disk.sector_size"_lang, hex::toByteString(this->m_sectorSize) }
|
||||
{ "hex.builtin.provider.disk.selected_disk"_lang, wolv::util::toUTF8String(m_path) },
|
||||
{ "hex.builtin.provider.disk.disk_size"_lang, hex::toByteString(m_diskSize) },
|
||||
{ "hex.builtin.provider.disk.sector_size"_lang, hex::toByteString(m_sectorSize) }
|
||||
};
|
||||
}
|
||||
|
||||
@@ -360,7 +360,7 @@ namespace hex::plugin::builtin {
|
||||
void DiskProvider::reloadDrives() {
|
||||
#if defined(OS_WINDOWS)
|
||||
|
||||
this->m_availableDrives.clear();
|
||||
m_availableDrives.clear();
|
||||
|
||||
std::array<TCHAR, MAX_DEVICE_ID_LEN> deviceInstanceID = {};
|
||||
std::array<TCHAR, 1024> description = {};
|
||||
@@ -412,7 +412,7 @@ namespace hex::plugin::builtin {
|
||||
|
||||
auto friendlyName = description.data();
|
||||
|
||||
this->m_availableDrives.insert({ path, friendlyName });
|
||||
m_availableDrives.insert({ path, friendlyName });
|
||||
}
|
||||
|
||||
// Add all logical drives
|
||||
@@ -420,7 +420,7 @@ namespace hex::plugin::builtin {
|
||||
for (char i = 0; i < 26; i++) {
|
||||
if (drives[i]) {
|
||||
char letter = 'A' + i;
|
||||
this->m_availableDrives.insert({ hex::format(R"(\\.\{:c}:)", letter), hex::format(R"({:c}:/)", letter) });
|
||||
m_availableDrives.insert({ hex::format(R"(\\.\{:c}:)", letter), hex::format(R"({:c}:/)", letter) });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -430,12 +430,12 @@ namespace hex::plugin::builtin {
|
||||
bool DiskProvider::drawLoadInterface() {
|
||||
#if defined(OS_WINDOWS)
|
||||
|
||||
if (this->m_availableDrives.empty()) {
|
||||
if (m_availableDrives.empty()) {
|
||||
this->reloadDrives();
|
||||
this->m_elevated = hex::isProcessElevated();
|
||||
m_elevated = hex::isProcessElevated();
|
||||
}
|
||||
|
||||
if (!this->m_elevated) {
|
||||
if (!m_elevated) {
|
||||
ImGui::PushTextWrapPos(0);
|
||||
ImGuiExt::TextFormattedColored(ImGuiExt::GetCustomColorU32(ImGuiCustomCol_LoggerError), ICON_VS_SHIELD "{}", "hex.builtin.provider.disk.elevation"_lang);
|
||||
ImGui::PopTextWrapPos();
|
||||
@@ -445,10 +445,10 @@ namespace hex::plugin::builtin {
|
||||
ImGui::PushItemWidth(300_scaled);
|
||||
if (ImGui::BeginListBox("hex.builtin.provider.disk.selected_disk"_lang)) {
|
||||
ImGui::PushID(1);
|
||||
for (const auto &[path, friendlyName] : this->m_availableDrives) {
|
||||
if (ImGui::Selectable(friendlyName.c_str(), this->m_path == path)) {
|
||||
this->m_path = path;
|
||||
this->m_friendlyName = friendlyName;
|
||||
for (const auto &[path, friendlyName] : m_availableDrives) {
|
||||
if (ImGui::Selectable(friendlyName.c_str(), m_path == path)) {
|
||||
m_path = path;
|
||||
m_friendlyName = friendlyName;
|
||||
}
|
||||
|
||||
ImGuiExt::InfoTooltip(path.c_str());
|
||||
@@ -467,20 +467,20 @@ namespace hex::plugin::builtin {
|
||||
|
||||
#else
|
||||
|
||||
if (ImGui::InputText("hex.builtin.provider.disk.selected_disk"_lang, this->m_pathBuffer.data(), this->m_pathBuffer.size(), ImGuiInputTextFlags_CallbackResize, ImGuiExt::UpdateStringSizeCallback, &this->m_pathBuffer)) {
|
||||
this->m_path = this->m_pathBuffer;
|
||||
this->m_friendlyName = this->m_pathBuffer;
|
||||
if (ImGui::InputText("hex.builtin.provider.disk.selected_disk"_lang, m_pathBuffer.data(), m_pathBuffer.size(), ImGuiInputTextFlags_CallbackResize, ImGuiExt::UpdateStringSizeCallback, &m_pathBuffer)) {
|
||||
m_path = m_pathBuffer;
|
||||
m_friendlyName = m_pathBuffer;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return !this->m_path.empty();
|
||||
return !m_path.empty();
|
||||
}
|
||||
|
||||
nlohmann::json DiskProvider::storeSettings(nlohmann::json settings) const {
|
||||
settings["path"] = wolv::util::toUTF8String(this->m_path);
|
||||
settings["path"] = wolv::util::toUTF8String(m_path);
|
||||
|
||||
settings["friendly_name"] = this->m_friendlyName;
|
||||
settings["friendly_name"] = m_friendlyName;
|
||||
|
||||
return Provider::storeSettings(settings);
|
||||
}
|
||||
@@ -491,7 +491,7 @@ namespace hex::plugin::builtin {
|
||||
auto path = settings.at("path").get<std::string>();
|
||||
|
||||
if (settings.contains("friendly_name"))
|
||||
this->m_friendlyName = settings.at("friendly_name").get<std::string>();
|
||||
m_friendlyName = settings.at("friendly_name").get<std::string>();
|
||||
|
||||
this->setPath(std::u8string(path.begin(), path.end()));
|
||||
this->reloadDrives();
|
||||
@@ -508,11 +508,11 @@ namespace hex::plugin::builtin {
|
||||
|
||||
std::variant<std::string, i128> DiskProvider::queryInformation(const std::string &category, const std::string &argument) {
|
||||
if (category == "file_path")
|
||||
return wolv::util::toUTF8String(this->m_path);
|
||||
return wolv::util::toUTF8String(m_path);
|
||||
else if (category == "sector_size")
|
||||
return this->m_sectorSize;
|
||||
return m_sectorSize;
|
||||
else if (category == "friendly_name")
|
||||
return this->m_friendlyName;
|
||||
return m_friendlyName;
|
||||
else
|
||||
return Provider::queryInformation(category, argument);
|
||||
}
|
||||
|
||||
@@ -27,11 +27,11 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
bool FileProvider::isReadable() const {
|
||||
return isAvailable() && this->m_readable;
|
||||
return isAvailable() && m_readable;
|
||||
}
|
||||
|
||||
bool FileProvider::isWritable() const {
|
||||
return isAvailable() && this->m_writable;
|
||||
return isAvailable() && m_writable;
|
||||
}
|
||||
|
||||
bool FileProvider::isResizable() const {
|
||||
@@ -39,7 +39,7 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
bool FileProvider::isSavable() const {
|
||||
return this->m_undoRedoStack.canUndo();
|
||||
return m_undoRedoStack.canUndo();
|
||||
}
|
||||
|
||||
void FileProvider::readRaw(u64 offset, void *buffer, size_t size) {
|
||||
@@ -47,14 +47,14 @@ namespace hex::plugin::builtin {
|
||||
if (actualSize == 0 || (offset + size) > actualSize || buffer == nullptr || size == 0)
|
||||
return;
|
||||
|
||||
std::memcpy(buffer, this->m_file.getMapping() + offset, size);
|
||||
std::memcpy(buffer, m_file.getMapping() + offset, size);
|
||||
}
|
||||
|
||||
void FileProvider::writeRaw(u64 offset, const void *buffer, size_t size) {
|
||||
if ((offset + size) > this->getActualSize() || buffer == nullptr || size == 0)
|
||||
return;
|
||||
|
||||
std::memcpy(this->m_file.getMapping() + offset, buffer, size);
|
||||
std::memcpy(m_file.getMapping() + offset, buffer, size);
|
||||
}
|
||||
|
||||
void FileProvider::save() {
|
||||
@@ -62,7 +62,7 @@ namespace hex::plugin::builtin {
|
||||
FILETIME ft;
|
||||
SYSTEMTIME st;
|
||||
|
||||
wolv::io::File file(this->m_path, wolv::io::File::Mode::Write);
|
||||
wolv::io::File file(m_path, wolv::io::File::Mode::Write);
|
||||
if (file.isValid()) {
|
||||
GetSystemTime(&st);
|
||||
if (SystemTimeToFileTime(&st, &ft)) {
|
||||
@@ -76,7 +76,7 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
void FileProvider::saveAs(const std::fs::path &path) {
|
||||
if (path == this->m_path)
|
||||
if (path == m_path)
|
||||
this->save();
|
||||
else
|
||||
Provider::saveAs(path);
|
||||
@@ -86,7 +86,7 @@ namespace hex::plugin::builtin {
|
||||
this->close();
|
||||
|
||||
{
|
||||
wolv::io::File file(this->m_path, wolv::io::File::Mode::Write);
|
||||
wolv::io::File file(m_path, wolv::io::File::Mode::Write);
|
||||
|
||||
file.setSize(newSize);
|
||||
}
|
||||
@@ -139,29 +139,29 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
u64 FileProvider::getActualSize() const {
|
||||
return this->m_fileSize;
|
||||
return m_fileSize;
|
||||
}
|
||||
|
||||
std::string FileProvider::getName() const {
|
||||
return wolv::util::toUTF8String(this->m_path.filename());
|
||||
return wolv::util::toUTF8String(m_path.filename());
|
||||
}
|
||||
|
||||
std::vector<FileProvider::Description> FileProvider::getDataDescription() const {
|
||||
std::vector<Description> result;
|
||||
|
||||
result.emplace_back("hex.builtin.provider.file.path"_lang, wolv::util::toUTF8String(this->m_path));
|
||||
result.emplace_back("hex.builtin.provider.file.path"_lang, wolv::util::toUTF8String(m_path));
|
||||
result.emplace_back("hex.builtin.provider.file.size"_lang, hex::toByteString(this->getActualSize()));
|
||||
|
||||
if (this->m_fileStats.has_value()) {
|
||||
if (m_fileStats.has_value()) {
|
||||
std::string creationTime, accessTime, modificationTime;
|
||||
|
||||
try { creationTime = hex::format("{:%Y-%m-%d %H:%M:%S}", fmt::localtime(this->m_fileStats->st_ctime)); }
|
||||
try { creationTime = hex::format("{:%Y-%m-%d %H:%M:%S}", fmt::localtime(m_fileStats->st_ctime)); }
|
||||
catch (const std::exception&) { creationTime = "???"; }
|
||||
|
||||
try { accessTime = hex::format("{:%Y-%m-%d %H:%M:%S}", fmt::localtime(this->m_fileStats->st_atime)); }
|
||||
try { accessTime = hex::format("{:%Y-%m-%d %H:%M:%S}", fmt::localtime(m_fileStats->st_atime)); }
|
||||
catch (const std::exception&) { accessTime = "???"; }
|
||||
|
||||
try { modificationTime = hex::format("{:%Y-%m-%d %H:%M:%S}", fmt::localtime(this->m_fileStats->st_mtime)); }
|
||||
try { modificationTime = hex::format("{:%Y-%m-%d %H:%M:%S}", fmt::localtime(m_fileStats->st_mtime)); }
|
||||
catch (const std::exception&) { modificationTime = "???"; }
|
||||
|
||||
result.emplace_back("hex.builtin.provider.file.creation"_lang, creationTime);
|
||||
@@ -174,19 +174,19 @@ namespace hex::plugin::builtin {
|
||||
|
||||
std::variant<std::string, i128> FileProvider::queryInformation(const std::string &category, const std::string &argument) {
|
||||
if (category == "file_path")
|
||||
return wolv::util::toUTF8String(this->m_path);
|
||||
return wolv::util::toUTF8String(m_path);
|
||||
else if (category == "file_name")
|
||||
return wolv::util::toUTF8String(this->m_path.filename());
|
||||
return wolv::util::toUTF8String(m_path.filename());
|
||||
else if (category == "file_extension")
|
||||
return wolv::util::toUTF8String(this->m_path.extension());
|
||||
return wolv::util::toUTF8String(m_path.extension());
|
||||
else if (category == "creation_time")
|
||||
return this->m_fileStats->st_ctime;
|
||||
return m_fileStats->st_ctime;
|
||||
else if (category == "access_time")
|
||||
return this->m_fileStats->st_atime;
|
||||
return m_fileStats->st_atime;
|
||||
else if (category == "modification_time")
|
||||
return this->m_fileStats->st_mtime;
|
||||
return m_fileStats->st_mtime;
|
||||
else if (category == "permissions")
|
||||
return this->m_fileStats->st_mode & 0777;
|
||||
return m_fileStats->st_mode & 0777;
|
||||
else
|
||||
return Provider::queryInformation(category, argument);
|
||||
}
|
||||
@@ -199,50 +199,50 @@ namespace hex::plugin::builtin {
|
||||
|
||||
std::vector<FileProvider::MenuEntry> FileProvider::getMenuEntries(){
|
||||
return {
|
||||
{ "hex.builtin.provider.file.menu.open_folder"_lang, [this] { fs::openFolderWithSelectionExternal(this->m_path); } },
|
||||
{ "hex.builtin.provider.file.menu.open_file"_lang, [this] { fs::openFileExternal(this->m_path); } },
|
||||
{ "hex.builtin.provider.file.menu.open_folder"_lang, [this] { fs::openFolderWithSelectionExternal(m_path); } },
|
||||
{ "hex.builtin.provider.file.menu.open_file"_lang, [this] { fs::openFileExternal(m_path); } },
|
||||
{ "hex.builtin.provider.file.menu.into_memory"_lang, [this] { this->convertToMemoryFile(); } }
|
||||
};
|
||||
}
|
||||
|
||||
void FileProvider::setPath(const std::fs::path &path) {
|
||||
this->m_path = path;
|
||||
m_path = path;
|
||||
}
|
||||
|
||||
bool FileProvider::open() {
|
||||
this->m_readable = true;
|
||||
this->m_writable = true;
|
||||
m_readable = true;
|
||||
m_writable = true;
|
||||
|
||||
if (!std::fs::exists(this->m_path)) {
|
||||
this->setErrorMessage(hex::format("hex.builtin.provider.file.error.open"_lang, this->m_path.string(), ::strerror(ENOENT)));
|
||||
if (!std::fs::exists(m_path)) {
|
||||
this->setErrorMessage(hex::format("hex.builtin.provider.file.error.open"_lang, m_path.string(), ::strerror(ENOENT)));
|
||||
return false;
|
||||
}
|
||||
|
||||
wolv::io::File file(this->m_path, wolv::io::File::Mode::Write);
|
||||
wolv::io::File file(m_path, wolv::io::File::Mode::Write);
|
||||
if (!file.isValid()) {
|
||||
this->m_writable = false;
|
||||
m_writable = false;
|
||||
|
||||
file = wolv::io::File(this->m_path, wolv::io::File::Mode::Read);
|
||||
file = wolv::io::File(m_path, wolv::io::File::Mode::Read);
|
||||
if (!file.isValid()) {
|
||||
this->m_readable = false;
|
||||
this->setErrorMessage(hex::format("hex.builtin.provider.file.error.open"_lang, this->m_path.string(), ::strerror(errno)));
|
||||
m_readable = false;
|
||||
this->setErrorMessage(hex::format("hex.builtin.provider.file.error.open"_lang, m_path.string(), ::strerror(errno)));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
this->m_fileStats = file.getFileInfo();
|
||||
this->m_file = std::move(file);
|
||||
m_fileStats = file.getFileInfo();
|
||||
m_file = std::move(file);
|
||||
|
||||
this->m_file.map();
|
||||
this->m_fileSize = this->m_file.getSize();
|
||||
m_file.map();
|
||||
m_fileSize = m_file.getSize();
|
||||
|
||||
this->m_file.close();
|
||||
m_file.close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void FileProvider::close() {
|
||||
this->m_file.unmap();
|
||||
m_file.unmap();
|
||||
}
|
||||
|
||||
void FileProvider::loadSettings(const nlohmann::json &settings) {
|
||||
@@ -258,7 +258,7 @@ namespace hex::plugin::builtin {
|
||||
try {
|
||||
this->setPath(projectPath.parent_path() / path);
|
||||
} catch (const std::fs::filesystem_error &e) {
|
||||
this->setErrorMessage(hex::format("hex.builtin.provider.file.error.open"_lang, this->m_path.string(), e.what()));
|
||||
this->setErrorMessage(hex::format("hex.builtin.provider.file.error.open"_lang, m_path.string(), e.what()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -269,9 +269,9 @@ namespace hex::plugin::builtin {
|
||||
nlohmann::json FileProvider::storeSettings(nlohmann::json settings) const {
|
||||
std::string path;
|
||||
if (auto projectPath = ProjectFile::getPath(); !projectPath.empty())
|
||||
path = wolv::util::toUTF8String(std::fs::proximate(this->m_path, projectPath.parent_path()));
|
||||
path = wolv::util::toUTF8String(std::fs::proximate(m_path, projectPath.parent_path()));
|
||||
if (path.empty())
|
||||
path = wolv::util::toUTF8String(this->m_path);
|
||||
path = wolv::util::toUTF8String(m_path);
|
||||
|
||||
settings["path"] = path;
|
||||
|
||||
|
||||
@@ -127,11 +127,11 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
bool GDBProvider::isAvailable() const {
|
||||
return this->m_socket.isConnected();
|
||||
return m_socket.isConnected();
|
||||
}
|
||||
|
||||
bool GDBProvider::isReadable() const {
|
||||
return this->m_socket.isConnected();
|
||||
return m_socket.isConnected();
|
||||
}
|
||||
|
||||
bool GDBProvider::isWritable() const {
|
||||
@@ -155,28 +155,28 @@ namespace hex::plugin::builtin {
|
||||
u64 alignedOffset = offset - (offset % CacheLineSize);
|
||||
|
||||
if (size <= CacheLineSize) {
|
||||
std::scoped_lock lock(this->m_cacheLock);
|
||||
std::scoped_lock lock(m_cacheLock);
|
||||
|
||||
const auto &cacheLine = std::find_if(this->m_cache.begin(), this->m_cache.end(), [&](auto &line) {
|
||||
const auto &cacheLine = std::find_if(m_cache.begin(), m_cache.end(), [&](auto &line) {
|
||||
return line.address == alignedOffset;
|
||||
});
|
||||
|
||||
if (cacheLine != this->m_cache.end()) {
|
||||
if (cacheLine != m_cache.end()) {
|
||||
// Cache hit
|
||||
|
||||
} else {
|
||||
// Cache miss
|
||||
|
||||
this->m_cache.push_back({ alignedOffset, { 0 } });
|
||||
m_cache.push_back({ alignedOffset, { 0 } });
|
||||
}
|
||||
|
||||
if (cacheLine != this->m_cache.end())
|
||||
if (cacheLine != m_cache.end())
|
||||
std::memcpy(buffer, &cacheLine->data[0] + (offset % CacheLineSize), std::min<u64>(size, cacheLine->data.size()));
|
||||
} else {
|
||||
while (size > 0) {
|
||||
size_t readSize = std::min<u64>(size, CacheLineSize);
|
||||
|
||||
auto data = gdb::readMemory(this->m_socket, offset, size);
|
||||
auto data = gdb::readMemory(m_socket, offset, size);
|
||||
if (!data.empty())
|
||||
std::memcpy(buffer, &data[0], data.size());
|
||||
|
||||
@@ -192,7 +192,7 @@ namespace hex::plugin::builtin {
|
||||
|
||||
offset -= this->getBaseAddress();
|
||||
|
||||
gdb::writeMemory(this->m_socket, offset, buffer, size);
|
||||
gdb::writeMemory(m_socket, offset, buffer, size);
|
||||
}
|
||||
|
||||
void GDBProvider::save() {
|
||||
@@ -200,7 +200,7 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
u64 GDBProvider::getActualSize() const {
|
||||
return this->m_size;
|
||||
return m_size;
|
||||
}
|
||||
|
||||
std::string GDBProvider::getName() const {
|
||||
@@ -208,8 +208,8 @@ namespace hex::plugin::builtin {
|
||||
std::string port = "-";
|
||||
|
||||
if (this->isConnected()) {
|
||||
address = this->m_ipAddress;
|
||||
port = std::to_string(this->m_port);
|
||||
address = m_ipAddress;
|
||||
port = std::to_string(m_port);
|
||||
}
|
||||
|
||||
return hex::format("hex.builtin.provider.gdb.name"_lang, address, port);
|
||||
@@ -217,46 +217,46 @@ namespace hex::plugin::builtin {
|
||||
|
||||
std::vector<GDBProvider::Description> GDBProvider::getDataDescription() const {
|
||||
return {
|
||||
{"hex.builtin.provider.gdb.server"_lang, hex::format("{}:{}", this->m_ipAddress, this->m_port)},
|
||||
{"hex.builtin.provider.gdb.server"_lang, hex::format("{}:{}", m_ipAddress, m_port)},
|
||||
};
|
||||
}
|
||||
|
||||
bool GDBProvider::open() {
|
||||
this->m_socket = wolv::net::SocketClient(wolv::net::SocketClient::Type::TCP);
|
||||
this->m_socket.connect(this->m_ipAddress, this->m_port);
|
||||
if (!gdb::enableNoAckMode(this->m_socket)) {
|
||||
this->m_socket.disconnect();
|
||||
m_socket = wolv::net::SocketClient(wolv::net::SocketClient::Type::TCP);
|
||||
m_socket.connect(m_ipAddress, m_port);
|
||||
if (!gdb::enableNoAckMode(m_socket)) {
|
||||
m_socket.disconnect();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this->m_socket.isConnected()) {
|
||||
gdb::continueExecution(this->m_socket);
|
||||
if (m_socket.isConnected()) {
|
||||
gdb::continueExecution(m_socket);
|
||||
|
||||
this->m_cacheUpdateThread = std::thread([this] {
|
||||
auto cacheLine = this->m_cache.begin();
|
||||
m_cacheUpdateThread = std::thread([this] {
|
||||
auto cacheLine = m_cache.begin();
|
||||
while (this->isConnected()) {
|
||||
{
|
||||
std::scoped_lock lock(this->m_cacheLock);
|
||||
std::scoped_lock lock(m_cacheLock);
|
||||
|
||||
if (this->m_resetCache) {
|
||||
this->m_cache.clear();
|
||||
this->m_resetCache = false;
|
||||
cacheLine = this->m_cache.begin();
|
||||
if (m_resetCache) {
|
||||
m_cache.clear();
|
||||
m_resetCache = false;
|
||||
cacheLine = m_cache.begin();
|
||||
}
|
||||
|
||||
if (cacheLine != this->m_cache.end()) {
|
||||
std::vector<u8> data = gdb::readMemory(this->m_socket, cacheLine->address, CacheLineSize);
|
||||
if (cacheLine != m_cache.end()) {
|
||||
std::vector<u8> data = gdb::readMemory(m_socket, cacheLine->address, CacheLineSize);
|
||||
|
||||
while (std::count_if(this->m_cache.begin(), this->m_cache.end(), [&](auto &line) { return !line.data.empty(); }) > 100) {
|
||||
this->m_cache.pop_front();
|
||||
cacheLine = this->m_cache.begin();
|
||||
while (std::count_if(m_cache.begin(), m_cache.end(), [&](auto &line) { return !line.data.empty(); }) > 100) {
|
||||
m_cache.pop_front();
|
||||
cacheLine = m_cache.begin();
|
||||
}
|
||||
|
||||
std::memcpy(cacheLine->data.data(), data.data(), data.size());
|
||||
}
|
||||
|
||||
if (cacheLine == this->m_cache.end())
|
||||
cacheLine = this->m_cache.begin();
|
||||
if (cacheLine == m_cache.end())
|
||||
cacheLine = m_cache.begin();
|
||||
else
|
||||
++cacheLine;
|
||||
}
|
||||
@@ -271,46 +271,46 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
void GDBProvider::close() {
|
||||
this->m_socket.disconnect();
|
||||
m_socket.disconnect();
|
||||
|
||||
if (this->m_cacheUpdateThread.joinable()) {
|
||||
this->m_cacheUpdateThread.join();
|
||||
if (m_cacheUpdateThread.joinable()) {
|
||||
m_cacheUpdateThread.join();
|
||||
}
|
||||
}
|
||||
|
||||
bool GDBProvider::isConnected() const {
|
||||
return this->m_socket.isConnected();
|
||||
return m_socket.isConnected();
|
||||
}
|
||||
|
||||
|
||||
bool GDBProvider::drawLoadInterface() {
|
||||
ImGui::InputText("hex.builtin.provider.gdb.ip"_lang, this->m_ipAddress);
|
||||
ImGui::InputInt("hex.builtin.provider.gdb.port"_lang, &this->m_port, 0, 0);
|
||||
ImGui::InputText("hex.builtin.provider.gdb.ip"_lang, m_ipAddress);
|
||||
ImGui::InputInt("hex.builtin.provider.gdb.port"_lang, &m_port, 0, 0);
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
ImGuiExt::InputHexadecimal("hex.builtin.common.size"_lang, &this->m_size, ImGuiInputTextFlags_CharsHexadecimal);
|
||||
ImGuiExt::InputHexadecimal("hex.builtin.common.size"_lang, &m_size, ImGuiInputTextFlags_CharsHexadecimal);
|
||||
|
||||
if (this->m_port < 0)
|
||||
this->m_port = 0;
|
||||
else if (this->m_port > 0xFFFF)
|
||||
this->m_port = 0xFFFF;
|
||||
if (m_port < 0)
|
||||
m_port = 0;
|
||||
else if (m_port > 0xFFFF)
|
||||
m_port = 0xFFFF;
|
||||
|
||||
return !this->m_ipAddress.empty() && this->m_port != 0;
|
||||
return !m_ipAddress.empty() && m_port != 0;
|
||||
}
|
||||
|
||||
void GDBProvider::loadSettings(const nlohmann::json &settings) {
|
||||
Provider::loadSettings(settings);
|
||||
|
||||
this->m_ipAddress = settings.at("ip").get<std::string>();
|
||||
this->m_port = settings.at("port").get<int>();
|
||||
this->m_size = settings.at("size").get<size_t>();
|
||||
m_ipAddress = settings.at("ip").get<std::string>();
|
||||
m_port = settings.at("port").get<int>();
|
||||
m_size = settings.at("size").get<size_t>();
|
||||
}
|
||||
|
||||
nlohmann::json GDBProvider::storeSettings(nlohmann::json settings) const {
|
||||
settings["ip"] = this->m_ipAddress;
|
||||
settings["port"] = this->m_port;
|
||||
settings["size"] = this->m_size;
|
||||
settings["ip"] = m_ipAddress;
|
||||
settings["port"] = m_port;
|
||||
settings["size"] = m_size;
|
||||
|
||||
return Provider::storeSettings(settings);
|
||||
}
|
||||
@@ -326,9 +326,9 @@ namespace hex::plugin::builtin {
|
||||
|
||||
std::variant<std::string, i128> GDBProvider::queryInformation(const std::string &category, const std::string &argument) {
|
||||
if (category == "ip")
|
||||
return this->m_ipAddress;
|
||||
return m_ipAddress;
|
||||
else if (category == "port")
|
||||
return this->m_port;
|
||||
return m_port;
|
||||
else
|
||||
return Provider::queryInformation(category, argument);
|
||||
}
|
||||
|
||||
@@ -160,19 +160,19 @@ namespace hex::plugin::builtin {
|
||||
void IntelHexProvider::setBaseAddress(u64 address) {
|
||||
auto oldBase = this->getBaseAddress();
|
||||
|
||||
auto regions = this->m_data.overlapping({ oldBase, oldBase + this->getActualSize() });
|
||||
auto regions = m_data.overlapping({ oldBase, oldBase + this->getActualSize() });
|
||||
|
||||
decltype(this->m_data) newIntervals;
|
||||
decltype(m_data) newIntervals;
|
||||
for (auto &[interval, data] : regions) {
|
||||
newIntervals.insert({ interval.start - oldBase + address, interval.end - oldBase + address }, *data);
|
||||
}
|
||||
this->m_data = newIntervals;
|
||||
m_data = newIntervals;
|
||||
|
||||
Provider::setBaseAddress(address);
|
||||
}
|
||||
|
||||
void IntelHexProvider::readRaw(u64 offset, void *buffer, size_t size) {
|
||||
auto intervals = this->m_data.overlapping({ offset, (offset + size) - 1 });
|
||||
auto intervals = m_data.overlapping({ offset, (offset + size) - 1 });
|
||||
|
||||
std::memset(buffer, 0x00, size);
|
||||
auto bytes = static_cast<u8*>(buffer);
|
||||
@@ -188,11 +188,11 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
u64 IntelHexProvider::getActualSize() const {
|
||||
return this->m_dataSize;
|
||||
return m_dataSize;
|
||||
}
|
||||
|
||||
bool IntelHexProvider::open() {
|
||||
auto file = wolv::io::File(this->m_sourceFilePath, wolv::io::File::Mode::Read);
|
||||
auto file = wolv::io::File(m_sourceFilePath, wolv::io::File::Mode::Read);
|
||||
if (!file.isValid())
|
||||
return false;
|
||||
|
||||
@@ -203,14 +203,14 @@ namespace hex::plugin::builtin {
|
||||
u64 maxAddress = 0x00;
|
||||
for (auto &[address, bytes] : data) {
|
||||
auto endAddress = (address + bytes.size()) - 1;
|
||||
this->m_data.emplace({ address, endAddress }, std::move(bytes));
|
||||
m_data.emplace({ address, endAddress }, std::move(bytes));
|
||||
|
||||
if (endAddress > maxAddress)
|
||||
maxAddress = endAddress;
|
||||
}
|
||||
|
||||
this->m_dataSize = maxAddress + 1;
|
||||
this->m_dataValid = true;
|
||||
m_dataSize = maxAddress + 1;
|
||||
m_dataValid = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -220,13 +220,13 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
[[nodiscard]] std::string IntelHexProvider::getName() const {
|
||||
return hex::format("hex.builtin.provider.intel_hex.name"_lang, wolv::util::toUTF8String(this->m_sourceFilePath.filename()));
|
||||
return hex::format("hex.builtin.provider.intel_hex.name"_lang, wolv::util::toUTF8String(m_sourceFilePath.filename()));
|
||||
}
|
||||
|
||||
[[nodiscard]] std::vector<IntelHexProvider::Description> IntelHexProvider::getDataDescription() const {
|
||||
std::vector<Description> result;
|
||||
|
||||
result.emplace_back("hex.builtin.provider.file.path"_lang, wolv::util::toUTF8String(this->m_sourceFilePath));
|
||||
result.emplace_back("hex.builtin.provider.file.path"_lang, wolv::util::toUTF8String(m_sourceFilePath));
|
||||
result.emplace_back("hex.builtin.provider.file.size"_lang, hex::toByteString(this->getActualSize()));
|
||||
|
||||
return result;
|
||||
@@ -247,25 +247,25 @@ namespace hex::plugin::builtin {
|
||||
{ "Intel Hex File", "a43" },
|
||||
{ "Intel Hex File", "a90" }
|
||||
}, [this](const std::fs::path &path) {
|
||||
this->m_sourceFilePath = path;
|
||||
m_sourceFilePath = path;
|
||||
}
|
||||
);
|
||||
|
||||
if (!picked)
|
||||
return false;
|
||||
if (!wolv::io::fs::isRegularFile(this->m_sourceFilePath))
|
||||
if (!wolv::io::fs::isRegularFile(m_sourceFilePath))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::pair<Region, bool> IntelHexProvider::getRegionValidity(u64 address) const {
|
||||
auto intervals = this->m_data.overlapping({ address, address });
|
||||
auto intervals = m_data.overlapping({ address, address });
|
||||
if (intervals.empty()) {
|
||||
return Provider::getRegionValidity(address);
|
||||
}
|
||||
|
||||
decltype(this->m_data)::Interval closestInterval = { 0, 0 };
|
||||
decltype(m_data)::Interval closestInterval = { 0, 0 };
|
||||
for (const auto &[interval, data] : intervals) {
|
||||
if (interval.start <= closestInterval.end)
|
||||
closestInterval = interval;
|
||||
@@ -278,11 +278,11 @@ namespace hex::plugin::builtin {
|
||||
Provider::loadSettings(settings);
|
||||
|
||||
auto path = settings.at("path").get<std::string>();
|
||||
this->m_sourceFilePath = std::u8string(path.begin(), path.end());
|
||||
m_sourceFilePath = std::u8string(path.begin(), path.end());
|
||||
}
|
||||
|
||||
nlohmann::json IntelHexProvider::storeSettings(nlohmann::json settings) const {
|
||||
settings["path"] = wolv::util::toUTF8String(this->m_sourceFilePath);
|
||||
settings["path"] = wolv::util::toUTF8String(m_sourceFilePath);
|
||||
|
||||
return Provider::storeSettings(settings);
|
||||
}
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
bool MemoryFileProvider::open() {
|
||||
if (this->m_data.empty()) {
|
||||
this->m_data.resize(1);
|
||||
if (m_data.empty()) {
|
||||
m_data.resize(1);
|
||||
this->markDirty();
|
||||
}
|
||||
|
||||
@@ -28,18 +28,18 @@ namespace hex::plugin::builtin {
|
||||
if (actualSize == 0 || (offset + size) > actualSize || buffer == nullptr || size == 0)
|
||||
return;
|
||||
|
||||
std::memcpy(buffer, &this->m_data.front() + offset, size);
|
||||
std::memcpy(buffer, &m_data.front() + offset, size);
|
||||
}
|
||||
|
||||
void MemoryFileProvider::writeRaw(u64 offset, const void *buffer, size_t size) {
|
||||
if ((offset + size) > this->getActualSize() || buffer == nullptr || size == 0)
|
||||
return;
|
||||
|
||||
std::memcpy(&this->m_data.front() + offset, buffer, size);
|
||||
std::memcpy(&m_data.front() + offset, buffer, size);
|
||||
}
|
||||
|
||||
void MemoryFileProvider::save() {
|
||||
if (!this->m_name.empty())
|
||||
if (!m_name.empty())
|
||||
return;
|
||||
|
||||
fs::openFileBrowser(fs::DialogMode::Save, { }, [this](const std::fs::path &path) {
|
||||
@@ -67,7 +67,7 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
void MemoryFileProvider::resizeRaw(u64 newSize) {
|
||||
this->m_data.resize(newSize);
|
||||
m_data.resize(newSize);
|
||||
}
|
||||
|
||||
void MemoryFileProvider::insertRaw(u64 offset, u64 size) {
|
||||
@@ -108,10 +108,10 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
[[nodiscard]] std::string MemoryFileProvider::getName() const {
|
||||
if (this->m_name.empty())
|
||||
if (m_name.empty())
|
||||
return Lang("hex.builtin.provider.mem_file.unsaved");
|
||||
else
|
||||
return this->m_name;
|
||||
return m_name;
|
||||
}
|
||||
|
||||
std::vector<MemoryFileProvider::MenuEntry> MemoryFileProvider::getMenuEntries() {
|
||||
@@ -132,22 +132,22 @@ namespace hex::plugin::builtin {
|
||||
void MemoryFileProvider::loadSettings(const nlohmann::json &settings) {
|
||||
Provider::loadSettings(settings);
|
||||
|
||||
this->m_data = settings["data"].get<std::vector<u8>>();
|
||||
this->m_name = settings["name"].get<std::string>();
|
||||
this->m_readOnly = settings["readOnly"].get<bool>();
|
||||
m_data = settings["data"].get<std::vector<u8>>();
|
||||
m_name = settings["name"].get<std::string>();
|
||||
m_readOnly = settings["readOnly"].get<bool>();
|
||||
}
|
||||
|
||||
[[nodiscard]] nlohmann::json MemoryFileProvider::storeSettings(nlohmann::json settings) const {
|
||||
settings["data"] = this->m_data;
|
||||
settings["name"] = this->m_name;
|
||||
settings["readOnly"] = this->m_readOnly;
|
||||
settings["data"] = m_data;
|
||||
settings["name"] = m_name;
|
||||
settings["readOnly"] = m_readOnly;
|
||||
|
||||
return Provider::storeSettings(settings);
|
||||
}
|
||||
|
||||
void MemoryFileProvider::renameFile() {
|
||||
PopupTextInput::open("hex.builtin.provider.mem_file.rename", "hex.builtin.provider.mem_file.rename.desc", [this](const std::string &name) {
|
||||
this->m_name = name;
|
||||
m_name = name;
|
||||
RequestUpdateWindowTitle::post();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -171,7 +171,7 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
bool MotorolaSRECProvider::open() {
|
||||
auto file = wolv::io::File(this->m_sourceFilePath, wolv::io::File::Mode::Read);
|
||||
auto file = wolv::io::File(m_sourceFilePath, wolv::io::File::Mode::Read);
|
||||
if (!file.isValid())
|
||||
return false;
|
||||
|
||||
@@ -182,14 +182,14 @@ namespace hex::plugin::builtin {
|
||||
u64 maxAddress = 0x00;
|
||||
for (auto &[address, bytes] : data) {
|
||||
auto endAddress = (address + bytes.size()) - 1;
|
||||
this->m_data.emplace({ address, endAddress }, std::move(bytes));
|
||||
m_data.emplace({ address, endAddress }, std::move(bytes));
|
||||
|
||||
if (endAddress > maxAddress)
|
||||
maxAddress = endAddress;
|
||||
}
|
||||
|
||||
this->m_dataSize = maxAddress + 1;
|
||||
this->m_dataValid = true;
|
||||
m_dataSize = maxAddress + 1;
|
||||
m_dataValid = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -199,14 +199,14 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
[[nodiscard]] std::string MotorolaSRECProvider::getName() const {
|
||||
return hex::format("hex.builtin.provider.motorola_srec.name"_lang, wolv::util::toUTF8String(this->m_sourceFilePath.filename()));
|
||||
return hex::format("hex.builtin.provider.motorola_srec.name"_lang, wolv::util::toUTF8String(m_sourceFilePath.filename()));
|
||||
}
|
||||
|
||||
|
||||
[[nodiscard]] std::vector<MotorolaSRECProvider::Description> MotorolaSRECProvider::getDataDescription() const {
|
||||
std::vector<Description> result;
|
||||
|
||||
result.emplace_back("hex.builtin.provider.file.path"_lang, wolv::util::toUTF8String(this->m_sourceFilePath));
|
||||
result.emplace_back("hex.builtin.provider.file.path"_lang, wolv::util::toUTF8String(m_sourceFilePath));
|
||||
result.emplace_back("hex.builtin.provider.file.size"_lang, hex::toByteString(this->getActualSize()));
|
||||
|
||||
return result;
|
||||
@@ -228,13 +228,13 @@ namespace hex::plugin::builtin {
|
||||
{ "Motorola SREC File", "mxt" }
|
||||
},
|
||||
[this](const std::fs::path &path) {
|
||||
this->m_sourceFilePath = path;
|
||||
m_sourceFilePath = path;
|
||||
}
|
||||
);
|
||||
|
||||
if (!picked)
|
||||
return false;
|
||||
if (!wolv::io::fs::isRegularFile(this->m_sourceFilePath))
|
||||
if (!wolv::io::fs::isRegularFile(m_sourceFilePath))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
||||
@@ -24,11 +24,11 @@ namespace hex::plugin::builtin {
|
||||
|
||||
bool ProcessMemoryProvider::open() {
|
||||
#if defined(OS_WINDOWS)
|
||||
this->m_processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, this->m_selectedProcess->id);
|
||||
if (this->m_processHandle == nullptr)
|
||||
m_processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, m_selectedProcess->id);
|
||||
if (m_processHandle == nullptr)
|
||||
return false;
|
||||
#elif defined(OS_LINUX)
|
||||
this->m_processId = pid_t(this->m_selectedProcess->id);
|
||||
m_processId = pid_t(m_selectedProcess->id);
|
||||
#endif
|
||||
|
||||
this->reloadProcessModules();
|
||||
@@ -38,16 +38,16 @@ namespace hex::plugin::builtin {
|
||||
|
||||
void ProcessMemoryProvider::close() {
|
||||
#if defined(OS_WINDOWS)
|
||||
CloseHandle(this->m_processHandle);
|
||||
this->m_processHandle = nullptr;
|
||||
CloseHandle(m_processHandle);
|
||||
m_processHandle = nullptr;
|
||||
#elif defined(OS_LINUX)
|
||||
this->m_processId = -1;
|
||||
m_processId = -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
void ProcessMemoryProvider::readRaw(u64 address, void *buffer, size_t size) {
|
||||
#if defined(OS_WINDOWS)
|
||||
ReadProcessMemory(this->m_processHandle, reinterpret_cast<LPCVOID>(address), buffer, size, nullptr);
|
||||
ReadProcessMemory(m_processHandle, reinterpret_cast<LPCVOID>(address), buffer, size, nullptr);
|
||||
#elif defined(OS_LINUX)
|
||||
const iovec local {
|
||||
.iov_base = buffer,
|
||||
@@ -58,7 +58,7 @@ namespace hex::plugin::builtin {
|
||||
.iov_len = size,
|
||||
};
|
||||
|
||||
auto read = process_vm_readv(this->m_processId, &local, 1, &remote, 1, 0);
|
||||
auto read = process_vm_readv(m_processId, &local, 1, &remote, 1, 0);
|
||||
|
||||
if (read == -1) {
|
||||
// TODO error handling strerror(errno)
|
||||
@@ -67,7 +67,7 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
void ProcessMemoryProvider::writeRaw(u64 address, const void *buffer, size_t size) {
|
||||
#if defined(OS_WINDOWS)
|
||||
WriteProcessMemory(this->m_processHandle, reinterpret_cast<LPVOID>(address), buffer, size, nullptr);
|
||||
WriteProcessMemory(m_processHandle, reinterpret_cast<LPVOID>(address), buffer, size, nullptr);
|
||||
#elif defined(OS_LINUX)
|
||||
const iovec local {
|
||||
.iov_base = const_cast<void*>(buffer),
|
||||
@@ -78,7 +78,7 @@ namespace hex::plugin::builtin {
|
||||
.iov_len = size,
|
||||
};
|
||||
|
||||
auto read = process_vm_writev(this->m_processId, &local, 1, &remote, 1, 0);
|
||||
auto read = process_vm_writev(m_processId, &local, 1, &remote, 1, 0);
|
||||
if (read == -1) {
|
||||
// TODO error handling strerror(errno)
|
||||
}
|
||||
@@ -86,13 +86,13 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
std::pair<Region, bool> ProcessMemoryProvider::getRegionValidity(u64 address) const {
|
||||
for (const auto &memoryRegion : this->m_memoryRegions) {
|
||||
for (const auto &memoryRegion : m_memoryRegions) {
|
||||
if (memoryRegion.region.overlaps({ address, 1 }))
|
||||
return { memoryRegion.region, true };
|
||||
}
|
||||
|
||||
Region lastRegion = Region::Invalid();
|
||||
for (const auto &memoryRegion : this->m_memoryRegions) {
|
||||
for (const auto &memoryRegion : m_memoryRegions) {
|
||||
|
||||
if (address < memoryRegion.region.getStartAddress())
|
||||
return { Region { lastRegion.getEndAddress() + 1, memoryRegion.region.getStartAddress() - lastRegion.getEndAddress() }, false };
|
||||
@@ -104,7 +104,7 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
bool ProcessMemoryProvider::drawLoadInterface() {
|
||||
if (this->m_processes.empty() && !this->m_enumerationFailed) {
|
||||
if (m_processes.empty() && !m_enumerationFailed) {
|
||||
#if defined(OS_WINDOWS)
|
||||
DWORD numProcesses = 0;
|
||||
std::vector<DWORD> processIds;
|
||||
@@ -113,7 +113,7 @@ namespace hex::plugin::builtin {
|
||||
processIds.resize(processIds.size() + 1024);
|
||||
if (EnumProcesses(processIds.data(), processIds.size() * sizeof(DWORD), &numProcesses) == FALSE) {
|
||||
processIds.clear();
|
||||
this->m_enumerationFailed = true;
|
||||
m_enumerationFailed = true;
|
||||
break;
|
||||
}
|
||||
} while (numProcesses == processIds.size() * sizeof(DWORD));
|
||||
@@ -172,7 +172,7 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
}
|
||||
|
||||
this->m_processes.push_back({ u32(processId), processName, std::move(texture) });
|
||||
m_processes.push_back({ u32(processId), processName, std::move(texture) });
|
||||
}
|
||||
#elif defined(OS_LINUX)
|
||||
for (const auto& entry : std::fs::directory_iterator("/proc")) {
|
||||
@@ -192,16 +192,16 @@ namespace hex::plugin::builtin {
|
||||
|
||||
std::string processName = file.readString(0xF'FFFF);
|
||||
|
||||
this->m_processes.emplace_back(processId, processName, ImGuiExt::Texture());
|
||||
m_processes.emplace_back(processId, processName, ImGuiExt::Texture());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (this->m_enumerationFailed) {
|
||||
if (m_enumerationFailed) {
|
||||
ImGui::TextUnformatted("hex.builtin.provider.process_memory.enumeration_failed"_lang);
|
||||
} else {
|
||||
ImGui::PushItemWidth(500_scaled);
|
||||
const auto &filtered = this->m_processSearchWidget.draw(this->m_processes);
|
||||
const auto &filtered = m_processSearchWidget.draw(m_processes);
|
||||
ImGui::PopItemWidth();
|
||||
if (ImGui::BeginTable("##process_table", 3, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_ScrollY, ImVec2(500_scaled, 500_scaled))) {
|
||||
ImGui::TableSetupColumn("##icon");
|
||||
@@ -222,8 +222,8 @@ namespace hex::plugin::builtin {
|
||||
ImGui::Text("%d", process->id);
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
if (ImGui::Selectable(process->name.c_str(), this->m_selectedProcess != nullptr && process->id == this->m_selectedProcess->id, ImGuiSelectableFlags_SpanAllColumns, ImVec2(0, process->icon.getSize().y)))
|
||||
this->m_selectedProcess = process;
|
||||
if (ImGui::Selectable(process->name.c_str(), m_selectedProcess != nullptr && process->id == m_selectedProcess->id, ImGuiSelectableFlags_SpanAllColumns, ImVec2(0, process->icon.getSize().y)))
|
||||
m_selectedProcess = process;
|
||||
|
||||
ImGui::PopID();
|
||||
}
|
||||
@@ -233,7 +233,7 @@ namespace hex::plugin::builtin {
|
||||
|
||||
}
|
||||
|
||||
return this->m_selectedProcess != nullptr;
|
||||
return m_selectedProcess != nullptr;
|
||||
}
|
||||
|
||||
void ProcessMemoryProvider::drawInterface() {
|
||||
@@ -241,7 +241,7 @@ namespace hex::plugin::builtin {
|
||||
|
||||
auto availableX = ImGui::GetContentRegionAvail().x;
|
||||
ImGui::PushItemWidth(availableX);
|
||||
const auto &filtered = this->m_regionSearchWidget.draw(this->m_memoryRegions);
|
||||
const auto &filtered = m_regionSearchWidget.draw(m_memoryRegions);
|
||||
ImGui::PopItemWidth();
|
||||
|
||||
#if defined(OS_WINDOWS)
|
||||
@@ -288,11 +288,11 @@ namespace hex::plugin::builtin {
|
||||
const auto &dllPath = path.native();
|
||||
const auto dllPathLength = (dllPath.length() + 1) * sizeof(std::fs::path::value_type);
|
||||
|
||||
if (auto pathAddress = VirtualAllocEx(this->m_processHandle, nullptr, dllPathLength, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); pathAddress != nullptr) {
|
||||
if (WriteProcessMemory(this->m_processHandle, pathAddress, dllPath.c_str(), dllPathLength, nullptr) != FALSE) {
|
||||
if (auto pathAddress = VirtualAllocEx(m_processHandle, nullptr, dllPathLength, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); pathAddress != nullptr) {
|
||||
if (WriteProcessMemory(m_processHandle, pathAddress, dllPath.c_str(), dllPathLength, nullptr) != FALSE) {
|
||||
auto loadLibraryW = reinterpret_cast<LPTHREAD_START_ROUTINE>(reinterpret_cast<void*>(GetProcAddress(GetModuleHandleA("kernel32.dll"), "LoadLibraryW")));
|
||||
if (loadLibraryW != nullptr) {
|
||||
if (auto threadHandle = CreateRemoteThread(this->m_processHandle, nullptr, 0, loadLibraryW, pathAddress, 0, nullptr); threadHandle != nullptr) {
|
||||
if (auto threadHandle = CreateRemoteThread(m_processHandle, nullptr, 0, loadLibraryW, pathAddress, 0, nullptr); threadHandle != nullptr) {
|
||||
WaitForSingleObject(threadHandle, INFINITE);
|
||||
RequestOpenErrorPopup::post(hex::format("hex.builtin.provider.process_memory.utils.inject_dll.success"_lang, path.filename().string()));
|
||||
this->reloadProcessModules();
|
||||
@@ -310,7 +310,7 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
void ProcessMemoryProvider::reloadProcessModules() {
|
||||
this->m_memoryRegions.clear();
|
||||
m_memoryRegions.clear();
|
||||
|
||||
#if defined(OS_WINDOWS)
|
||||
DWORD numModules = 0;
|
||||
@@ -318,7 +318,7 @@ namespace hex::plugin::builtin {
|
||||
|
||||
do {
|
||||
modules.resize(modules.size() + 1024);
|
||||
if (EnumProcessModules(this->m_processHandle, modules.data(), modules.size() * sizeof(HMODULE), &numModules) == FALSE) {
|
||||
if (EnumProcessModules(m_processHandle, modules.data(), modules.size() * sizeof(HMODULE), &numModules) == FALSE) {
|
||||
modules.clear();
|
||||
break;
|
||||
}
|
||||
@@ -328,19 +328,19 @@ namespace hex::plugin::builtin {
|
||||
|
||||
for (auto &module : modules) {
|
||||
MODULEINFO moduleInfo;
|
||||
if (GetModuleInformation(this->m_processHandle, module, &moduleInfo, sizeof(MODULEINFO)) == FALSE)
|
||||
if (GetModuleInformation(m_processHandle, module, &moduleInfo, sizeof(MODULEINFO)) == FALSE)
|
||||
continue;
|
||||
|
||||
char moduleName[MAX_PATH];
|
||||
if (GetModuleFileNameExA(this->m_processHandle, module, moduleName, MAX_PATH) == FALSE)
|
||||
if (GetModuleFileNameExA(m_processHandle, module, moduleName, MAX_PATH) == FALSE)
|
||||
continue;
|
||||
|
||||
this->m_memoryRegions.insert({ { u64(moduleInfo.lpBaseOfDll), size_t(moduleInfo.SizeOfImage) }, std::fs::path(moduleName).filename().string() });
|
||||
m_memoryRegions.insert({ { u64(moduleInfo.lpBaseOfDll), size_t(moduleInfo.SizeOfImage) }, std::fs::path(moduleName).filename().string() });
|
||||
}
|
||||
|
||||
MEMORY_BASIC_INFORMATION memoryInfo;
|
||||
for (u64 address = 0; address < this->getActualSize(); address += memoryInfo.RegionSize) {
|
||||
if (VirtualQueryEx(this->m_processHandle, reinterpret_cast<LPCVOID>(address), &memoryInfo, sizeof(MEMORY_BASIC_INFORMATION)) == 0)
|
||||
if (VirtualQueryEx(m_processHandle, reinterpret_cast<LPCVOID>(address), &memoryInfo, sizeof(MEMORY_BASIC_INFORMATION)) == 0)
|
||||
break;
|
||||
|
||||
std::string name;
|
||||
@@ -351,12 +351,12 @@ namespace hex::plugin::builtin {
|
||||
if (memoryInfo.State & MEM_PRIVATE) name += hex::format("{} ", "hex.builtin.provider.process_memory.region.private"_lang);
|
||||
if (memoryInfo.State & MEM_MAPPED) name += hex::format("{} ", "hex.builtin.provider.process_memory.region.mapped"_lang);
|
||||
|
||||
this->m_memoryRegions.insert({ { reinterpret_cast<u64>(memoryInfo.BaseAddress), reinterpret_cast<u64>(memoryInfo.BaseAddress) + memoryInfo.RegionSize }, name });
|
||||
m_memoryRegions.insert({ { reinterpret_cast<u64>(memoryInfo.BaseAddress), reinterpret_cast<u64>(memoryInfo.BaseAddress) + memoryInfo.RegionSize }, name });
|
||||
}
|
||||
|
||||
#elif defined(OS_LINUX)
|
||||
|
||||
wolv::io::File file(std::fs::path("/proc") / std::to_string(this->m_processId) / "maps", wolv::io::File::Mode::Read);
|
||||
wolv::io::File file(std::fs::path("/proc") / std::to_string(m_processId) / "maps", wolv::io::File::Mode::Read);
|
||||
|
||||
if (!file.isValid())
|
||||
return;
|
||||
@@ -370,7 +370,7 @@ namespace hex::plugin::builtin {
|
||||
const u64 end = std::stoull(split[0].substr(split[0].find('-') + 1), nullptr, 16);
|
||||
const auto &name = split[5];
|
||||
|
||||
this->m_memoryRegions.insert({ { start, end - start }, name });
|
||||
m_memoryRegions.insert({ { start, end - start }, name });
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -378,26 +378,26 @@ namespace hex::plugin::builtin {
|
||||
|
||||
std::variant<std::string, i128> ProcessMemoryProvider::queryInformation(const std::string &category, const std::string &argument) {
|
||||
auto findRegionByName = [this](const std::string &name) {
|
||||
return std::find_if(this->m_memoryRegions.begin(), this->m_memoryRegions.end(),
|
||||
return std::find_if(m_memoryRegions.begin(), m_memoryRegions.end(),
|
||||
[name](const auto ®ion) {
|
||||
return region.name == name;
|
||||
});
|
||||
};
|
||||
|
||||
if (category == "region_address") {
|
||||
if (auto iter = findRegionByName(argument); iter != this->m_memoryRegions.end())
|
||||
if (auto iter = findRegionByName(argument); iter != m_memoryRegions.end())
|
||||
return iter->region.getStartAddress();
|
||||
else
|
||||
return 0;
|
||||
} else if (category == "region_size") {
|
||||
if (auto iter = findRegionByName(argument); iter != this->m_memoryRegions.end())
|
||||
if (auto iter = findRegionByName(argument); iter != m_memoryRegions.end())
|
||||
return iter->region.getSize();
|
||||
else
|
||||
return 0;
|
||||
} else if (category == "process_id") {
|
||||
return this->m_selectedProcess->id;
|
||||
return m_selectedProcess->id;
|
||||
} else if (category == "process_name") {
|
||||
return this->m_selectedProcess->name;
|
||||
return m_selectedProcess->name;
|
||||
} else
|
||||
return Provider::queryInformation(category, argument);
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace hex::plugin::builtin::recent {
|
||||
if (entry.is_regular_file() && entry.path().extension() == ".hexproj") {
|
||||
wolv::io::File backupFile(entry.path(), wolv::io::File::Mode::Read);
|
||||
|
||||
this->m_backups.emplace_back(
|
||||
m_backups.emplace_back(
|
||||
hex::format("hex.builtin.welcome.start.recent.auto_backups.backup"_lang, fmt::gmtime(backupFile.getFileInfo()->st_ctime)),
|
||||
entry.path()
|
||||
);
|
||||
@@ -54,7 +54,7 @@ namespace hex::plugin::builtin::recent {
|
||||
|
||||
void drawContent() override {
|
||||
if (ImGui::BeginTable("AutoBackups", 1, ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersInnerV, ImVec2(0, ImGui::GetTextLineHeightWithSpacing() * 5))) {
|
||||
for (const auto &backup : this->m_backups | std::views::reverse | std::views::take(10)) {
|
||||
for (const auto &backup : m_backups | std::views::reverse | std::views::take(10)) {
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
if (ImGui::Selectable(backup.displayName.c_str())) {
|
||||
|
||||
@@ -31,10 +31,10 @@ namespace hex::plugin::builtin {
|
||||
class ServerContactWidget : public ContentRegistry::Settings::Widgets::Widget {
|
||||
public:
|
||||
bool draw(const std::string &name) override {
|
||||
bool enabled = this->m_value == 1;
|
||||
bool enabled = m_value == 1;
|
||||
|
||||
if (ImGui::Checkbox(name.data(), &enabled)) {
|
||||
this->m_value = enabled ? 1 : 0;
|
||||
m_value = enabled ? 1 : 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -43,11 +43,11 @@ namespace hex::plugin::builtin {
|
||||
|
||||
void load(const nlohmann::json &data) override {
|
||||
if (data.is_number())
|
||||
this->m_value = data.get<int>();
|
||||
m_value = data.get<int>();
|
||||
}
|
||||
|
||||
nlohmann::json store() override {
|
||||
return this->m_value;
|
||||
return m_value;
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -58,15 +58,15 @@ namespace hex::plugin::builtin {
|
||||
public:
|
||||
bool draw(const std::string &name) override {
|
||||
auto format = [this] -> std::string {
|
||||
if (this->m_value > 200)
|
||||
if (m_value > 200)
|
||||
return "hex.builtin.setting.interface.fps.unlocked"_lang;
|
||||
else if (this->m_value < 15)
|
||||
else if (m_value < 15)
|
||||
return "hex.builtin.setting.interface.fps.native"_lang;
|
||||
else
|
||||
return "%d FPS";
|
||||
}();
|
||||
|
||||
if (ImGui::SliderInt(name.data(), &this->m_value, 14, 201, format.c_str(), ImGuiSliderFlags_AlwaysClamp)) {
|
||||
if (ImGui::SliderInt(name.data(), &m_value, 14, 201, format.c_str(), ImGuiSliderFlags_AlwaysClamp)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -75,11 +75,11 @@ namespace hex::plugin::builtin {
|
||||
|
||||
void load(const nlohmann::json &data) override {
|
||||
if (data.is_number())
|
||||
this->m_value = data.get<int>();
|
||||
m_value = data.get<int>();
|
||||
}
|
||||
|
||||
nlohmann::json store() override {
|
||||
return this->m_value;
|
||||
return m_value;
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -94,10 +94,10 @@ namespace hex::plugin::builtin {
|
||||
if (!ImGui::BeginListBox("", ImVec2(-40_scaled, 280_scaled))) {
|
||||
return false;
|
||||
} else {
|
||||
for (size_t n = 0; n < this->m_paths.size(); n++) {
|
||||
const bool isSelected = (this->m_itemIndex == n);
|
||||
if (ImGui::Selectable(wolv::util::toUTF8String(this->m_paths[n]).c_str(), isSelected)) {
|
||||
this->m_itemIndex = n;
|
||||
for (size_t n = 0; n < m_paths.size(); n++) {
|
||||
const bool isSelected = (m_itemIndex == n);
|
||||
if (ImGui::Selectable(wolv::util::toUTF8String(m_paths[n]).c_str(), isSelected)) {
|
||||
m_itemIndex = n;
|
||||
}
|
||||
|
||||
if (isSelected) {
|
||||
@@ -111,9 +111,9 @@ namespace hex::plugin::builtin {
|
||||
|
||||
if (ImGuiExt::IconButton(ICON_VS_NEW_FOLDER, ImGui::GetStyleColorVec4(ImGuiCol_Text), ImVec2(30, 30))) {
|
||||
fs::openFileBrowser(fs::DialogMode::Folder, {}, [&](const std::fs::path &path) {
|
||||
if (std::find(this->m_paths.begin(), this->m_paths.end(), path) == this->m_paths.end()) {
|
||||
this->m_paths.emplace_back(path);
|
||||
ImHexApi::System::setAdditionalFolderPaths(this->m_paths);
|
||||
if (std::find(m_paths.begin(), m_paths.end(), path) == m_paths.end()) {
|
||||
m_paths.emplace_back(path);
|
||||
ImHexApi::System::setAdditionalFolderPaths(m_paths);
|
||||
|
||||
result = true;
|
||||
}
|
||||
@@ -122,9 +122,9 @@ namespace hex::plugin::builtin {
|
||||
ImGuiExt::InfoTooltip("hex.builtin.setting.folders.add_folder"_lang);
|
||||
|
||||
if (ImGuiExt::IconButton(ICON_VS_REMOVE_CLOSE, ImGui::GetStyleColorVec4(ImGuiCol_Text), ImVec2(30, 30))) {
|
||||
if (!this->m_paths.empty()) {
|
||||
this->m_paths.erase(std::next(this->m_paths.begin(), this->m_itemIndex));
|
||||
ImHexApi::System::setAdditionalFolderPaths(this->m_paths);
|
||||
if (!m_paths.empty()) {
|
||||
m_paths.erase(std::next(m_paths.begin(), m_itemIndex));
|
||||
ImHexApi::System::setAdditionalFolderPaths(m_paths);
|
||||
|
||||
result = true;
|
||||
}
|
||||
@@ -141,7 +141,7 @@ namespace hex::plugin::builtin {
|
||||
std::vector<std::string> pathStrings = data;
|
||||
|
||||
for (const auto &pathString : pathStrings) {
|
||||
this->m_paths.emplace_back(pathString);
|
||||
m_paths.emplace_back(pathString);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -149,7 +149,7 @@ namespace hex::plugin::builtin {
|
||||
nlohmann::json store() override {
|
||||
std::vector<std::string> pathStrings;
|
||||
|
||||
for (const auto &path : this->m_paths) {
|
||||
for (const auto &path : m_paths) {
|
||||
pathStrings.push_back(wolv::util::toUTF8String(path));
|
||||
}
|
||||
|
||||
@@ -165,13 +165,13 @@ namespace hex::plugin::builtin {
|
||||
public:
|
||||
bool draw(const std::string &name) override {
|
||||
auto format = [this] -> std::string {
|
||||
if (this->m_value == 0)
|
||||
if (m_value == 0)
|
||||
return "hex.builtin.setting.interface.scaling.native"_lang;
|
||||
else
|
||||
return "x%.1f";
|
||||
}();
|
||||
|
||||
if (ImGui::SliderFloat(name.data(), &this->m_value, 0, 10, format.c_str(), ImGuiSliderFlags_AlwaysClamp)) {
|
||||
if (ImGui::SliderFloat(name.data(), &m_value, 0, 10, format.c_str(), ImGuiSliderFlags_AlwaysClamp)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -180,11 +180,11 @@ namespace hex::plugin::builtin {
|
||||
|
||||
void load(const nlohmann::json &data) override {
|
||||
if (data.is_number())
|
||||
this->m_value = data.get<float>();
|
||||
m_value = data.get<float>();
|
||||
}
|
||||
|
||||
nlohmann::json store() override {
|
||||
return this->m_value;
|
||||
return m_value;
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -195,7 +195,7 @@ namespace hex::plugin::builtin {
|
||||
public:
|
||||
bool draw(const std::string &name) override {
|
||||
auto format = [this] -> std::string {
|
||||
auto value = this->m_value * 30;
|
||||
auto value = m_value * 30;
|
||||
if (value == 0)
|
||||
return "hex.builtin.common.off"_lang;
|
||||
else if (value < 60)
|
||||
@@ -204,7 +204,7 @@ namespace hex::plugin::builtin {
|
||||
return hex::format("hex.builtin.setting.general.auto_backup_time.format.extended"_lang, value / 60, value % 60);
|
||||
}();
|
||||
|
||||
if (ImGui::SliderInt(name.data(), &this->m_value, 0, (30 * 60) / 30, format.c_str(), ImGuiSliderFlags_AlwaysClamp | ImGuiSliderFlags_NoInput)) {
|
||||
if (ImGui::SliderInt(name.data(), &m_value, 0, (30 * 60) / 30, format.c_str(), ImGuiSliderFlags_AlwaysClamp | ImGuiSliderFlags_NoInput)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -213,11 +213,11 @@ namespace hex::plugin::builtin {
|
||||
|
||||
void load(const nlohmann::json &data) override {
|
||||
if (data.is_number())
|
||||
this->m_value = data.get<int>();
|
||||
m_value = data.get<int>();
|
||||
}
|
||||
|
||||
nlohmann::json store() override {
|
||||
return this->m_value;
|
||||
return m_value;
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -231,8 +231,8 @@ namespace hex::plugin::builtin {
|
||||
bool draw(const std::string &name) override {
|
||||
std::string label;
|
||||
|
||||
if (!this->m_editing)
|
||||
label = this->m_drawShortcut.toString();
|
||||
if (!m_editing)
|
||||
label = m_drawShortcut.toString();
|
||||
else
|
||||
label = "...";
|
||||
|
||||
@@ -240,14 +240,14 @@ namespace hex::plugin::builtin {
|
||||
label = "???";
|
||||
|
||||
|
||||
if (this->m_hasDuplicate)
|
||||
if (m_hasDuplicate)
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ImGuiExt::GetCustomColorVec4(ImGuiCustomCol_LoggerError));
|
||||
|
||||
ImGui::PushID(this);
|
||||
if (ImGui::Button(label.c_str(), ImVec2(250_scaled, 0))) {
|
||||
this->m_editing = !this->m_editing;
|
||||
m_editing = !m_editing;
|
||||
|
||||
if (this->m_editing)
|
||||
if (m_editing)
|
||||
ShortcutManager::pauseShortcuts();
|
||||
else
|
||||
ShortcutManager::resumeShortcuts();
|
||||
@@ -255,18 +255,18 @@ namespace hex::plugin::builtin {
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
if (this->m_hasDuplicate)
|
||||
if (m_hasDuplicate)
|
||||
ImGui::PopStyleColor();
|
||||
|
||||
bool settingChanged = false;
|
||||
|
||||
ImGui::BeginDisabled(this->m_drawShortcut == this->m_defaultShortcut);
|
||||
ImGui::BeginDisabled(m_drawShortcut == m_defaultShortcut);
|
||||
if (ImGuiExt::IconButton(ICON_VS_X, ImGui::GetStyleColorVec4(ImGuiCol_Text))) {
|
||||
this->m_hasDuplicate = !ShortcutManager::updateShortcut(this->m_shortcut, this->m_defaultShortcut, this->m_view);
|
||||
m_hasDuplicate = !ShortcutManager::updateShortcut(m_shortcut, m_defaultShortcut, m_view);
|
||||
|
||||
this->m_drawShortcut = this->m_defaultShortcut;
|
||||
if (!this->m_hasDuplicate) {
|
||||
this->m_shortcut = this->m_defaultShortcut;
|
||||
m_drawShortcut = m_defaultShortcut;
|
||||
if (!m_hasDuplicate) {
|
||||
m_shortcut = m_defaultShortcut;
|
||||
settingChanged = true;
|
||||
}
|
||||
|
||||
@@ -274,7 +274,7 @@ namespace hex::plugin::builtin {
|
||||
ImGui::EndDisabled();
|
||||
|
||||
if (!ImGui::IsItemHovered() && ImGui::IsMouseClicked(ImGuiMouseButton_Left)) {
|
||||
this->m_editing = false;
|
||||
m_editing = false;
|
||||
ShortcutManager::resumeShortcuts();
|
||||
}
|
||||
|
||||
@@ -284,13 +284,13 @@ namespace hex::plugin::builtin {
|
||||
|
||||
ImGui::PopID();
|
||||
|
||||
if (this->m_editing) {
|
||||
if (m_editing) {
|
||||
if (this->detectShortcut()) {
|
||||
this->m_editing = false;
|
||||
m_editing = false;
|
||||
ShortcutManager::resumeShortcuts();
|
||||
|
||||
settingChanged = true;
|
||||
if (!this->m_hasDuplicate) {
|
||||
if (!m_hasDuplicate) {
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -308,15 +308,15 @@ namespace hex::plugin::builtin {
|
||||
return;
|
||||
|
||||
auto newShortcut = Shortcut(keys);
|
||||
this->m_hasDuplicate = !ShortcutManager::updateShortcut(this->m_shortcut, newShortcut, this->m_view);
|
||||
this->m_shortcut = std::move(newShortcut);
|
||||
this->m_drawShortcut = this->m_shortcut;
|
||||
m_hasDuplicate = !ShortcutManager::updateShortcut(m_shortcut, newShortcut, m_view);
|
||||
m_shortcut = std::move(newShortcut);
|
||||
m_drawShortcut = m_shortcut;
|
||||
}
|
||||
|
||||
nlohmann::json store() override {
|
||||
std::vector<u32> keys;
|
||||
|
||||
for (const auto &key : this->m_shortcut.getKeys()) {
|
||||
for (const auto &key : m_shortcut.getKeys()) {
|
||||
if (key != CurrentView)
|
||||
keys.push_back(key.getKeyCode());
|
||||
}
|
||||
@@ -327,7 +327,7 @@ namespace hex::plugin::builtin {
|
||||
private:
|
||||
bool detectShortcut() {
|
||||
if (const auto &shortcut = ShortcutManager::getPreviousShortcut(); shortcut.has_value()) {
|
||||
auto keys = this->m_shortcut.getKeys();
|
||||
auto keys = m_shortcut.getKeys();
|
||||
std::erase_if(keys, [](Key key) {
|
||||
return key != AllowWhileTyping && key != CurrentView;
|
||||
});
|
||||
@@ -337,11 +337,11 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
auto newShortcut = Shortcut(std::move(keys));
|
||||
this->m_hasDuplicate = !ShortcutManager::updateShortcut(this->m_shortcut, newShortcut, this->m_view);
|
||||
this->m_drawShortcut = std::move(newShortcut);
|
||||
m_hasDuplicate = !ShortcutManager::updateShortcut(m_shortcut, newShortcut, m_view);
|
||||
m_drawShortcut = std::move(newShortcut);
|
||||
|
||||
if (!this->m_hasDuplicate) {
|
||||
this->m_shortcut = this->m_drawShortcut;
|
||||
if (!m_hasDuplicate) {
|
||||
m_shortcut = m_drawShortcut;
|
||||
log::info("Changed shortcut to {}", shortcut->toString());
|
||||
} else {
|
||||
log::warn("Changing shortcut failed as it overlapped with another one", shortcut->toString());
|
||||
|
||||
@@ -100,18 +100,18 @@ namespace hex::plugin::builtin {
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
// Draw the ImHex icon
|
||||
if (!this->m_logoTexture.isValid())
|
||||
this->m_logoTexture = ImGuiExt::Texture(romfs::get("assets/common/logo.png").span(), ImGuiExt::Texture::Filter::Linear);
|
||||
if (!m_logoTexture.isValid())
|
||||
m_logoTexture = ImGuiExt::Texture(romfs::get("assets/common/logo.png").span(), ImGuiExt::Texture::Filter::Linear);
|
||||
|
||||
ImGui::Image(this->m_logoTexture, scaled({ 100, 100 }));
|
||||
ImGui::Image(m_logoTexture, scaled({ 100, 100 }));
|
||||
if (ImGui::IsItemClicked()) {
|
||||
this->m_clickCount += 1;
|
||||
m_clickCount += 1;
|
||||
}
|
||||
|
||||
if (this->m_clickCount >= (2 * 3 + 4)) {
|
||||
if (m_clickCount >= (2 * 3 + 4)) {
|
||||
this->getWindowOpenState() = false;
|
||||
PopupEE::open();
|
||||
this->m_clickCount = 0;
|
||||
m_clickCount = 0;
|
||||
}
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
@@ -451,13 +451,13 @@ namespace hex::plugin::builtin {
|
||||
AT_FIRST_TIME {
|
||||
static HttpRequest request("GET", GitHubApiURL + std::string("/releases/tags/v") + ImHexApi::System::getImHexVersion(false));
|
||||
|
||||
this->m_releaseNoteRequest = request.execute();
|
||||
m_releaseNoteRequest = request.execute();
|
||||
};
|
||||
|
||||
// Wait for the request to finish and parse the response
|
||||
if (this->m_releaseNoteRequest.valid()) {
|
||||
if (this->m_releaseNoteRequest.wait_for(std::chrono::seconds(0)) == std::future_status::ready) {
|
||||
auto response = this->m_releaseNoteRequest.get();
|
||||
if (m_releaseNoteRequest.valid()) {
|
||||
if (m_releaseNoteRequest.wait_for(std::chrono::seconds(0)) == std::future_status::ready) {
|
||||
auto response = m_releaseNoteRequest.get();
|
||||
nlohmann::json json;
|
||||
|
||||
if (response.isSuccess()) {
|
||||
@@ -553,13 +553,13 @@ namespace hex::plugin::builtin {
|
||||
// Set up the request to get the commit history the first time the page is opened
|
||||
AT_FIRST_TIME {
|
||||
static HttpRequest request("GET", GitHubApiURL + std::string("/commits?per_page=100"));
|
||||
this->m_commitHistoryRequest = request.execute();
|
||||
m_commitHistoryRequest = request.execute();
|
||||
};
|
||||
|
||||
// Wait for the request to finish and parse the response
|
||||
if (this->m_commitHistoryRequest.valid()) {
|
||||
if (this->m_commitHistoryRequest.wait_for(std::chrono::seconds(0)) == std::future_status::ready) {
|
||||
auto response = this->m_commitHistoryRequest.get();
|
||||
if (m_commitHistoryRequest.valid()) {
|
||||
if (m_commitHistoryRequest.wait_for(std::chrono::seconds(0)) == std::future_status::ready) {
|
||||
auto response = m_commitHistoryRequest.get();
|
||||
nlohmann::json json;
|
||||
|
||||
if (response.isSuccess()) {
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace hex::plugin::builtin {
|
||||
|
||||
// Add newly unlocked achievements to the display queue
|
||||
EventAchievementUnlocked::subscribe(this, [this](const Achievement &achievement) {
|
||||
this->m_achievementUnlockQueue.push_back(&achievement);
|
||||
m_achievementUnlockQueue.push_back(&achievement);
|
||||
});
|
||||
|
||||
RequestOpenWindow::subscribe(this, [this](const std::string &name) {
|
||||
@@ -29,7 +29,7 @@ namespace hex::plugin::builtin {
|
||||
});
|
||||
|
||||
// Load settings
|
||||
this->m_showPopup = ContentRegistry::Settings::read("hex.builtin.setting.interface", "hex.builtin.setting.interface.achievement_popup", true);
|
||||
m_showPopup = ContentRegistry::Settings::read("hex.builtin.setting.interface", "hex.builtin.setting.interface.achievement_popup", true);
|
||||
}
|
||||
|
||||
ViewAchievements::~ViewAchievements() {
|
||||
@@ -273,9 +273,9 @@ namespace hex::plugin::builtin {
|
||||
drawList->AddBezierQuadratic(start, middle, end, color, 2_scaled);
|
||||
|
||||
// Handle jumping to an achievement
|
||||
if (this->m_achievementToGoto != nullptr) {
|
||||
if (this->m_achievementToGoto == node->achievement) {
|
||||
this->m_offset = position - scaled({ 100, 100 });
|
||||
if (m_achievementToGoto != nullptr) {
|
||||
if (m_achievementToGoto == node->achievement) {
|
||||
m_offset = position - scaled({ 100, 100 });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -331,8 +331,8 @@ namespace hex::plugin::builtin {
|
||||
ImGuiTabItemFlags flags = ImGuiTabItemFlags_None;
|
||||
|
||||
// Handle jumping to the category of an achievement
|
||||
if (this->m_achievementToGoto != nullptr) {
|
||||
if (this->m_achievementToGoto->getUnlocalizedCategory() == categoryName) {
|
||||
if (m_achievementToGoto != nullptr) {
|
||||
if (m_achievementToGoto->getUnlocalizedCategory() == categoryName) {
|
||||
flags |= ImGuiTabItemFlags_SetSelected;
|
||||
}
|
||||
}
|
||||
@@ -358,10 +358,10 @@ namespace hex::plugin::builtin {
|
||||
drawList->ChannelsSetCurrent(0);
|
||||
|
||||
// Draw achievement background
|
||||
drawBackground(drawList, innerWindowPos, innerWindowPos + innerWindowSize, this->m_offset);
|
||||
drawBackground(drawList, innerWindowPos, innerWindowPos + innerWindowSize, m_offset);
|
||||
|
||||
// Draw the achievement tree
|
||||
auto maxPos = drawAchievementTree(drawList, nullptr, achievements, innerWindowPos + scaled({ 100, 100 }) + this->m_offset);
|
||||
auto maxPos = drawAchievementTree(drawList, nullptr, achievements, innerWindowPos + scaled({ 100, 100 }) + m_offset);
|
||||
|
||||
drawList->ChannelsSetCurrent(3);
|
||||
|
||||
@@ -373,12 +373,12 @@ namespace hex::plugin::builtin {
|
||||
// Handle dragging the achievement tree around
|
||||
if (ImGui::IsMouseHoveringRect(innerWindowPos, innerWindowPos + innerWindowSize)) {
|
||||
auto dragDelta = ImGui::GetMouseDragDelta(ImGuiMouseButton_Left);
|
||||
this->m_offset += dragDelta;
|
||||
m_offset += dragDelta;
|
||||
ImGui::ResetMouseDragDelta(ImGuiMouseButton_Left);
|
||||
}
|
||||
|
||||
// Clamp the achievement tree to the window
|
||||
this->m_offset = -ImClamp(-this->m_offset, { 0, 0 }, ImMax(maxPos - innerWindowPos - innerWindowSize, { 0, 0 }));
|
||||
m_offset = -ImClamp(-m_offset, { 0, 0 }, ImMax(maxPos - innerWindowPos - innerWindowSize, { 0, 0 }));
|
||||
|
||||
drawList->PopClipRect();
|
||||
|
||||
@@ -386,8 +386,8 @@ namespace hex::plugin::builtin {
|
||||
ImGui::SetCursorScreenPos(innerWindowPos + ImVec2(0, innerWindowSize.y + windowPadding.y));
|
||||
ImGui::BeginGroup();
|
||||
{
|
||||
if (ImGui::Checkbox("Show popup", &this->m_showPopup))
|
||||
ContentRegistry::Settings::write("hex.builtin.setting.interface", "hex.builtin.setting.interface.achievement_popup", this->m_showPopup);
|
||||
if (ImGui::Checkbox("Show popup", &m_showPopup))
|
||||
ContentRegistry::Settings::write("hex.builtin.setting.interface", "hex.builtin.setting.interface.achievement_popup", m_showPopup);
|
||||
}
|
||||
ImGui::EndGroup();
|
||||
|
||||
@@ -398,17 +398,17 @@ namespace hex::plugin::builtin {
|
||||
ImGui::EndTabBar();
|
||||
}
|
||||
|
||||
this->m_achievementToGoto = nullptr;
|
||||
m_achievementToGoto = nullptr;
|
||||
}
|
||||
|
||||
void ViewAchievements::drawAlwaysVisibleContent() {
|
||||
|
||||
// Handle showing the achievement unlock popup
|
||||
if (this->m_achievementUnlockQueueTimer >= 0 && this->m_showPopup) {
|
||||
this->m_achievementUnlockQueueTimer -= ImGui::GetIO().DeltaTime;
|
||||
if (m_achievementUnlockQueueTimer >= 0 && m_showPopup) {
|
||||
m_achievementUnlockQueueTimer -= ImGui::GetIO().DeltaTime;
|
||||
|
||||
// Check if there's an achievement that can be drawn
|
||||
if (this->m_currAchievement != nullptr) {
|
||||
if (m_currAchievement != nullptr) {
|
||||
|
||||
const ImVec2 windowSize = scaled({ 200, 55 });
|
||||
ImGui::SetNextWindowPos(ImHexApi::System::getMainWindowPosition() + ImVec2 { ImHexApi::System::getMainWindowSize().x - windowSize.x - 100_scaled, 0 });
|
||||
@@ -420,34 +420,34 @@ namespace hex::plugin::builtin {
|
||||
ImGuiExt::TextFormattedColored(ImGuiExt::GetCustomColorVec4(ImGuiCustomCol_AchievementUnlocked), "{}", "hex.builtin.view.achievements.unlocked"_lang);
|
||||
|
||||
// Draw achievement icon
|
||||
ImGui::Image(this->m_currAchievement->getIcon(), scaled({ 20, 20 }));
|
||||
ImGui::Image(m_currAchievement->getIcon(), scaled({ 20, 20 }));
|
||||
|
||||
ImGui::SameLine();
|
||||
ImGui::SeparatorEx(ImGuiSeparatorFlags_Vertical);
|
||||
ImGui::SameLine();
|
||||
|
||||
// Draw name of achievement
|
||||
ImGuiExt::TextFormattedWrapped("{}", Lang(this->m_currAchievement->getUnlocalizedName()));
|
||||
ImGuiExt::TextFormattedWrapped("{}", Lang(m_currAchievement->getUnlocalizedName()));
|
||||
|
||||
// Handle clicking on the popup
|
||||
if (ImGui::IsWindowHovered() && ImGui::IsMouseReleased(ImGuiMouseButton_Left)) {
|
||||
// Open the achievement window and jump to the achievement
|
||||
this->getWindowOpenState() = true;
|
||||
this->m_achievementToGoto = this->m_currAchievement;
|
||||
m_achievementToGoto = m_currAchievement;
|
||||
}
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
} else {
|
||||
// Reset the achievement unlock queue timer
|
||||
this->m_achievementUnlockQueueTimer = -1.0F;
|
||||
this->m_currAchievement = nullptr;
|
||||
m_achievementUnlockQueueTimer = -1.0F;
|
||||
m_currAchievement = nullptr;
|
||||
|
||||
// If there are more achievements to draw, draw the next one
|
||||
if (!this->m_achievementUnlockQueue.empty()) {
|
||||
this->m_currAchievement = this->m_achievementUnlockQueue.front();
|
||||
this->m_achievementUnlockQueue.pop_front();
|
||||
this->m_achievementUnlockQueueTimer = 5.0F;
|
||||
if (!m_achievementUnlockQueue.empty()) {
|
||||
m_currAchievement = m_achievementUnlockQueue.front();
|
||||
m_achievementUnlockQueue.pop_front();
|
||||
m_achievementUnlockQueueTimer = 5.0F;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,8 +28,8 @@ namespace hex::plugin::builtin {
|
||||
if (color == 0x00)
|
||||
color = ImGui::GetColorU32(ImGuiCol_Header);
|
||||
|
||||
this->m_currBookmarkId += 1;
|
||||
u64 bookmarkId = this->m_currBookmarkId;
|
||||
m_currBookmarkId += 1;
|
||||
u64 bookmarkId = m_currBookmarkId;
|
||||
if (id != nullptr)
|
||||
*id = bookmarkId;
|
||||
|
||||
@@ -42,16 +42,16 @@ namespace hex::plugin::builtin {
|
||||
bookmarkId
|
||||
};
|
||||
|
||||
this->m_bookmarks->emplace_back(std::move(bookmark), TextEditor());
|
||||
m_bookmarks->emplace_back(std::move(bookmark), TextEditor());
|
||||
|
||||
ImHexApi::Provider::markDirty();
|
||||
|
||||
EventBookmarkCreated::post(this->m_bookmarks->back().entry);
|
||||
EventBookmarkCreated::post(m_bookmarks->back().entry);
|
||||
EventHighlightingChanged::post();
|
||||
});
|
||||
|
||||
RequestRemoveBookmark::subscribe([this](u64 id) {
|
||||
std::erase_if(this->m_bookmarks.get(), [id](const auto &bookmark) {
|
||||
std::erase_if(m_bookmarks.get(), [id](const auto &bookmark) {
|
||||
return bookmark.entry.id == id;
|
||||
});
|
||||
});
|
||||
@@ -61,7 +61,7 @@ namespace hex::plugin::builtin {
|
||||
hex::unused(data);
|
||||
|
||||
// Check all bookmarks for potential overlaps with the current address
|
||||
for (const auto &bookmark : *this->m_bookmarks) {
|
||||
for (const auto &bookmark : *m_bookmarks) {
|
||||
if (Region { address, size }.isWithin(bookmark.entry.region))
|
||||
return bookmark.entry.color;
|
||||
}
|
||||
@@ -74,7 +74,7 @@ namespace hex::plugin::builtin {
|
||||
hex::unused(data);
|
||||
|
||||
// Loop over all bookmarks
|
||||
for (const auto &[bookmark, editor] : *this->m_bookmarks) {
|
||||
for (const auto &[bookmark, editor] : *m_bookmarks) {
|
||||
// Make sure the bookmark overlaps the currently hovered address
|
||||
if (!Region { address, size }.isWithin(bookmark.region))
|
||||
continue;
|
||||
@@ -147,7 +147,7 @@ namespace hex::plugin::builtin {
|
||||
return true;
|
||||
|
||||
auto data = nlohmann::json::parse(fileContent.begin(), fileContent.end());
|
||||
this->m_bookmarks.get(provider).clear();
|
||||
m_bookmarks.get(provider).clear();
|
||||
return this->importBookmarks(provider, data);
|
||||
},
|
||||
.store = [this](prv::Provider *provider, const std::fs::path &basePath, Tar &tar) -> bool {
|
||||
@@ -163,7 +163,7 @@ namespace hex::plugin::builtin {
|
||||
ContentRegistry::Reports::addReportProvider([this](prv::Provider *provider) -> std::string {
|
||||
std::string result;
|
||||
|
||||
const auto &bookmarks = this->m_bookmarks.get(provider);
|
||||
const auto &bookmarks = m_bookmarks.get(provider);
|
||||
if (bookmarks.empty())
|
||||
return "";
|
||||
|
||||
@@ -243,27 +243,27 @@ namespace hex::plugin::builtin {
|
||||
|
||||
// Draw filter input
|
||||
ImGui::PushItemWidth(-1);
|
||||
ImGuiExt::InputTextIcon("##filter", ICON_VS_FILTER, this->m_currFilter);
|
||||
ImGuiExt::InputTextIcon("##filter", ICON_VS_FILTER, m_currFilter);
|
||||
ImGui::PopItemWidth();
|
||||
|
||||
ImGui::NewLine();
|
||||
|
||||
if (ImGui::BeginChild("##bookmarks")) {
|
||||
if (this->m_bookmarks->empty()) {
|
||||
if (m_bookmarks->empty()) {
|
||||
ImGuiExt::TextFormattedCentered("hex.builtin.view.bookmarks.no_bookmarks"_lang);
|
||||
}
|
||||
|
||||
int id = 1;
|
||||
auto bookmarkToRemove = this->m_bookmarks->end();
|
||||
auto bookmarkToRemove = m_bookmarks->end();
|
||||
|
||||
// Draw all bookmarks
|
||||
for (auto it = this->m_bookmarks->begin(); it != this->m_bookmarks->end(); ++it) {
|
||||
for (auto it = m_bookmarks->begin(); it != m_bookmarks->end(); ++it) {
|
||||
auto &[bookmark, editor] = *it;
|
||||
auto &[region, name, comment, color, locked, bookmarkId] = bookmark;
|
||||
|
||||
// Apply filter
|
||||
if (!this->m_currFilter.empty()) {
|
||||
if (!name.contains(this->m_currFilter) && !comment.contains(this->m_currFilter))
|
||||
if (!m_currFilter.empty()) {
|
||||
if (!name.contains(m_currFilter) && !comment.contains(m_currFilter))
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -288,18 +288,18 @@ namespace hex::plugin::builtin {
|
||||
// Handle dragging bookmarks up and down when they're collapsed
|
||||
|
||||
// Set the currently held bookmark as the one being dragged
|
||||
if (ImGui::IsMouseClicked(0) && ImGui::IsItemActivated() && this->m_dragStartIterator == this->m_bookmarks->end())
|
||||
this->m_dragStartIterator = it;
|
||||
if (ImGui::IsMouseClicked(0) && ImGui::IsItemActivated() && m_dragStartIterator == m_bookmarks->end())
|
||||
m_dragStartIterator = it;
|
||||
|
||||
// When the mouse moved away from the current bookmark, swap the dragged bookmark with the current one
|
||||
if (ImGui::IsItemHovered() && this->m_dragStartIterator != this->m_bookmarks->end()) {
|
||||
std::iter_swap(it, this->m_dragStartIterator);
|
||||
this->m_dragStartIterator = it;
|
||||
if (ImGui::IsItemHovered() && m_dragStartIterator != m_bookmarks->end()) {
|
||||
std::iter_swap(it, m_dragStartIterator);
|
||||
m_dragStartIterator = it;
|
||||
}
|
||||
|
||||
// When the mouse is released, reset the dragged bookmark
|
||||
if (!ImGui::IsMouseDown(0))
|
||||
this->m_dragStartIterator = this->m_bookmarks->end();
|
||||
m_dragStartIterator = m_bookmarks->end();
|
||||
} else {
|
||||
const auto rowHeight = ImGui::GetTextLineHeightWithSpacing() + 2 * ImGui::GetStyle().FramePadding.y;
|
||||
if (ImGui::BeginTable("##bookmark_table", 3, ImGuiTableFlags_RowBg | ImGuiTableFlags_SizingFixedFit)) {
|
||||
@@ -436,8 +436,8 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
// Remove the bookmark that was marked for removal
|
||||
if (bookmarkToRemove != this->m_bookmarks->end()) {
|
||||
this->m_bookmarks->erase(bookmarkToRemove);
|
||||
if (bookmarkToRemove != m_bookmarks->end()) {
|
||||
m_bookmarks->erase(bookmarkToRemove);
|
||||
EventHighlightingChanged::post();
|
||||
}
|
||||
}
|
||||
@@ -458,22 +458,22 @@ namespace hex::plugin::builtin {
|
||||
|
||||
TextEditor editor;
|
||||
editor.SetText(bookmark["comment"]);
|
||||
this->m_bookmarks.get(provider).push_back({
|
||||
m_bookmarks.get(provider).push_back({
|
||||
{
|
||||
.region = { region["address"], region["size"] },
|
||||
.name = bookmark["name"],
|
||||
.comment = bookmark["comment"],
|
||||
.color = bookmark["color"],
|
||||
.locked = bookmark["locked"],
|
||||
.id = bookmark.contains("id") ? bookmark["id"].get<u64>() : *this->m_currBookmarkId
|
||||
.id = bookmark.contains("id") ? bookmark["id"].get<u64>() : *m_currBookmarkId
|
||||
},
|
||||
editor
|
||||
});
|
||||
|
||||
if (bookmark.contains("id"))
|
||||
this->m_currBookmarkId = std::max<u64>(this->m_currBookmarkId, bookmark["id"].get<i64>() + 1);
|
||||
m_currBookmarkId = std::max<u64>(m_currBookmarkId, bookmark["id"].get<i64>() + 1);
|
||||
else
|
||||
this->m_currBookmarkId += 1;
|
||||
m_currBookmarkId += 1;
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -482,7 +482,7 @@ namespace hex::plugin::builtin {
|
||||
bool ViewBookmarks::exportBookmarks(prv::Provider *provider, nlohmann::json &json) {
|
||||
json["bookmarks"] = nlohmann::json::array();
|
||||
size_t index = 0;
|
||||
for (const auto &[bookmark, editor] : this->m_bookmarks.get(provider)) {
|
||||
for (const auto &[bookmark, editor] : m_bookmarks.get(provider)) {
|
||||
json["bookmarks"][index] = {
|
||||
{ "name", bookmark.name },
|
||||
{ "comment", editor.GetText() },
|
||||
@@ -536,7 +536,7 @@ namespace hex::plugin::builtin {
|
||||
wolv::io::File(path, wolv::io::File::Mode::Create).writeString(json.dump(4));
|
||||
});
|
||||
}, [this]{
|
||||
return ImHexApi::Provider::isValid() && !this->m_bookmarks->empty();
|
||||
return ImHexApi::Provider::isValid() && !m_bookmarks->empty();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -9,22 +9,22 @@ namespace hex::plugin::builtin {
|
||||
// Add global shortcut to open the command palette
|
||||
ShortcutManager::addGlobalShortcut(CTRLCMD + SHIFT + Keys::P, "hex.builtin.view.command_palette.name", [this] {
|
||||
RequestOpenPopup::post("hex.builtin.view.command_palette.name"_lang);
|
||||
this->m_commandPaletteOpen = true;
|
||||
this->m_justOpened = true;
|
||||
m_commandPaletteOpen = true;
|
||||
m_justOpened = true;
|
||||
});
|
||||
|
||||
EventSearchBoxClicked::subscribe([this](ImGuiMouseButton button) {
|
||||
if (button == ImGuiMouseButton_Left) {
|
||||
RequestOpenPopup::post("hex.builtin.view.command_palette.name"_lang);
|
||||
this->m_commandPaletteOpen = true;
|
||||
this->m_justOpened = true;
|
||||
m_commandPaletteOpen = true;
|
||||
m_justOpened = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void ViewCommandPalette::drawAlwaysVisibleContent() {
|
||||
// If the command palette is hidden, don't draw it
|
||||
if (!this->m_commandPaletteOpen) return;
|
||||
if (!m_commandPaletteOpen) return;
|
||||
|
||||
auto windowPos = ImHexApi::System::getMainWindowPosition();
|
||||
auto windowSize = ImHexApi::System::getMainWindowSize();
|
||||
@@ -52,8 +52,8 @@ namespace hex::plugin::builtin {
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0_scaled);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 4_scaled);
|
||||
|
||||
if (ImGui::InputText("##command_input", this->m_commandBuffer)) {
|
||||
this->m_lastResults = this->getCommandResults(this->m_commandBuffer);
|
||||
if (ImGui::InputText("##command_input", m_commandBuffer)) {
|
||||
m_lastResults = this->getCommandResults(m_commandBuffer);
|
||||
}
|
||||
|
||||
ImGui::PopStyleVar(2);
|
||||
@@ -61,40 +61,40 @@ namespace hex::plugin::builtin {
|
||||
ImGui::PopItemWidth();
|
||||
ImGui::SetItemDefaultFocus();
|
||||
|
||||
if (this->m_moveCursorToEnd) {
|
||||
if (m_moveCursorToEnd) {
|
||||
auto textState = ImGui::GetInputTextState(ImGui::GetID("##command_input"));
|
||||
if (textState != nullptr) {
|
||||
textState->Stb.cursor =
|
||||
textState->Stb.select_start =
|
||||
textState->Stb.select_end = this->m_commandBuffer.size();
|
||||
textState->Stb.select_end = m_commandBuffer.size();
|
||||
}
|
||||
this->m_moveCursorToEnd = false;
|
||||
m_moveCursorToEnd = false;
|
||||
}
|
||||
|
||||
// Handle giving back focus to the input text box
|
||||
if (this->m_focusInputTextBox) {
|
||||
if (m_focusInputTextBox) {
|
||||
ImGui::SetKeyboardFocusHere(-1);
|
||||
ImGui::ActivateItemByID(ImGui::GetID("##command_input"));
|
||||
|
||||
this->m_focusInputTextBox = false;
|
||||
this->m_moveCursorToEnd = true;
|
||||
m_focusInputTextBox = false;
|
||||
m_moveCursorToEnd = true;
|
||||
}
|
||||
|
||||
// Execute the currently selected command when pressing enter
|
||||
if (ImGui::IsItemFocused() && (ImGui::IsKeyPressed(ImGuiKey_Enter, false) || ImGui::IsKeyPressed(ImGuiKey_KeypadEnter, false))) {
|
||||
if (!this->m_lastResults.empty()) {
|
||||
auto &[displayResult, matchedCommand, callback] = this->m_lastResults.front();
|
||||
if (!m_lastResults.empty()) {
|
||||
auto &[displayResult, matchedCommand, callback] = m_lastResults.front();
|
||||
callback(matchedCommand);
|
||||
}
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
|
||||
// Focus the input text box when the popup is opened
|
||||
if (this->m_justOpened) {
|
||||
if (m_justOpened) {
|
||||
focusInputTextBox();
|
||||
this->m_lastResults = this->getCommandResults("");
|
||||
this->m_commandBuffer.clear();
|
||||
this->m_justOpened = false;
|
||||
m_lastResults = this->getCommandResults("");
|
||||
m_commandBuffer.clear();
|
||||
m_justOpened = false;
|
||||
}
|
||||
|
||||
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + ImGui::GetStyle().FramePadding.y);
|
||||
@@ -103,7 +103,7 @@ namespace hex::plugin::builtin {
|
||||
|
||||
// Draw the results
|
||||
if (ImGui::BeginChild("##results", ImGui::GetContentRegionAvail(), false, ImGuiWindowFlags_AlwaysVerticalScrollbar | ImGuiWindowFlags_NavFlattened)) {
|
||||
for (const auto &[displayResult, matchedCommand, callback] : this->m_lastResults) {
|
||||
for (const auto &[displayResult, matchedCommand, callback] : m_lastResults) {
|
||||
ImGui::PushTabStop(true);
|
||||
ON_SCOPE_EXIT { ImGui::PopTabStop(); };
|
||||
|
||||
@@ -122,7 +122,7 @@ namespace hex::plugin::builtin {
|
||||
|
||||
ImGui::EndPopup();
|
||||
} else {
|
||||
this->m_commandPaletteOpen = false;
|
||||
m_commandPaletteOpen = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,8 +155,8 @@ namespace hex::plugin::builtin {
|
||||
|
||||
auto AutoComplete = [this, currCommand = command](auto) {
|
||||
this->focusInputTextBox();
|
||||
this->m_commandBuffer = currCommand + " ";
|
||||
this->m_lastResults = this->getCommandResults(currCommand);
|
||||
m_commandBuffer = currCommand + " ";
|
||||
m_lastResults = this->getCommandResults(currCommand);
|
||||
};
|
||||
|
||||
if (type == ContentRegistry::CommandPaletteCommands::Type::SymbolCommand) {
|
||||
|
||||
@@ -17,8 +17,8 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
void ViewConstants::reloadConstants() {
|
||||
this->m_constants.clear();
|
||||
this->m_filterIndices.clear();
|
||||
m_constants.clear();
|
||||
m_filterIndices.clear();
|
||||
|
||||
for (const auto &path : fs::getDefaultPaths(fs::ImHexPath::Constants)) {
|
||||
if (!wolv::io::fs::exists(path)) continue;
|
||||
@@ -52,8 +52,8 @@ namespace hex::plugin::builtin {
|
||||
else
|
||||
throw std::runtime_error("Invalid type");
|
||||
|
||||
this->m_filterIndices.push_back(this->m_constants.size());
|
||||
this->m_constants.push_back(constant);
|
||||
m_filterIndices.push_back(m_constants.size());
|
||||
m_constants.push_back(constant);
|
||||
}
|
||||
} catch (...) {
|
||||
log::error("Failed to parse constants file {}", wolv::util::toUTF8String(file.path()));
|
||||
@@ -65,17 +65,17 @@ namespace hex::plugin::builtin {
|
||||
void ViewConstants::drawContent() {
|
||||
ImGui::PushItemWidth(-1);
|
||||
|
||||
if (ImGuiExt::InputTextIcon("##search", ICON_VS_FILTER, this->m_filter)) {
|
||||
this->m_filterIndices.clear();
|
||||
if (ImGuiExt::InputTextIcon("##search", ICON_VS_FILTER, m_filter)) {
|
||||
m_filterIndices.clear();
|
||||
|
||||
// Filter the constants according to the entered value
|
||||
for (u64 i = 0; i < this->m_constants.size(); i++) {
|
||||
auto &constant = this->m_constants[i];
|
||||
if (hex::containsIgnoreCase(constant.name, this->m_filter) ||
|
||||
hex::containsIgnoreCase(constant.category, this->m_filter) ||
|
||||
hex::containsIgnoreCase(constant.description, this->m_filter) ||
|
||||
hex::containsIgnoreCase(constant.value, this->m_filter))
|
||||
this->m_filterIndices.push_back(i);
|
||||
for (u64 i = 0; i < m_constants.size(); i++) {
|
||||
auto &constant = m_constants[i];
|
||||
if (hex::containsIgnoreCase(constant.name, m_filter) ||
|
||||
hex::containsIgnoreCase(constant.category, m_filter) ||
|
||||
hex::containsIgnoreCase(constant.description, m_filter) ||
|
||||
hex::containsIgnoreCase(constant.value, m_filter))
|
||||
m_filterIndices.push_back(i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ namespace hex::plugin::builtin {
|
||||
|
||||
// Handle table sorting
|
||||
if (sortSpecs->SpecsDirty) {
|
||||
std::sort(this->m_constants.begin(), this->m_constants.end(), [&sortSpecs](const Constant &left, const Constant &right) -> bool {
|
||||
std::sort(m_constants.begin(), m_constants.end(), [&sortSpecs](const Constant &left, const Constant &right) -> bool {
|
||||
if (sortSpecs->Specs->ColumnUserID == ImGui::GetID("category")) {
|
||||
if (sortSpecs->Specs->SortDirection == ImGuiSortDirection_Ascending)
|
||||
return left.category > right.category;
|
||||
@@ -124,12 +124,12 @@ namespace hex::plugin::builtin {
|
||||
ImGui::TableHeadersRow();
|
||||
|
||||
ImGuiListClipper clipper;
|
||||
clipper.Begin(this->m_filterIndices.size());
|
||||
clipper.Begin(m_filterIndices.size());
|
||||
|
||||
// Draw the constants table
|
||||
while (clipper.Step()) {
|
||||
for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) {
|
||||
auto &constant = this->m_constants[this->m_filterIndices[i]];
|
||||
auto &constant = m_constants[m_filterIndices[i]];
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::TextUnformatted(constant.category.c_str());
|
||||
|
||||
@@ -25,26 +25,26 @@ namespace hex::plugin::builtin {
|
||||
|
||||
// Save current selection
|
||||
if (!ImHexApi::Provider::isValid() || region == Region::Invalid()) {
|
||||
this->m_validBytes = 0;
|
||||
this->m_selectedProvider = nullptr;
|
||||
m_validBytes = 0;
|
||||
m_selectedProvider = nullptr;
|
||||
} else {
|
||||
this->m_validBytes = u64(region.getProvider()->getActualSize() - region.address);
|
||||
this->m_startAddress = region.address;
|
||||
this->m_selectedProvider = region.getProvider();
|
||||
m_validBytes = u64(region.getProvider()->getActualSize() - region.address);
|
||||
m_startAddress = region.address;
|
||||
m_selectedProvider = region.getProvider();
|
||||
}
|
||||
|
||||
// Invalidate inspector rows
|
||||
this->m_shouldInvalidate = true;
|
||||
m_shouldInvalidate = true;
|
||||
});
|
||||
|
||||
EventProviderClosed::subscribe(this, [this](const auto*) {
|
||||
this->m_selectedProvider = nullptr;
|
||||
m_selectedProvider = nullptr;
|
||||
});
|
||||
|
||||
EventSettingsChanged::subscribe(this, [this] {
|
||||
auto filterValues = ContentRegistry::Settings::read("hex.builtin.setting.data_inspector", "hex.builtin.setting.data_inspector.hidden_rows", nlohmann::json::array()).get<std::vector<std::string>>();
|
||||
|
||||
this->m_hiddenValues = std::set(filterValues.begin(), filterValues.end());
|
||||
m_hiddenValues = std::set(filterValues.begin(), filterValues.end());
|
||||
});
|
||||
}
|
||||
|
||||
@@ -56,10 +56,10 @@ namespace hex::plugin::builtin {
|
||||
|
||||
|
||||
void ViewDataInspector::updateInspectorRows() {
|
||||
this->m_updateTask = TaskManager::createBackgroundTask("Update Inspector", [this, validBytes = this->m_validBytes, startAddress = this->m_startAddress, endian = this->m_endian, invert = this->m_invert, numberDisplayStyle = this->m_numberDisplayStyle](auto &) {
|
||||
this->m_workData.clear();
|
||||
m_updateTask = TaskManager::createBackgroundTask("Update Inspector", [this, validBytes = m_validBytes, startAddress = m_startAddress, endian = m_endian, invert = m_invert, numberDisplayStyle = m_numberDisplayStyle](auto &) {
|
||||
m_workData.clear();
|
||||
|
||||
if (this->m_selectedProvider == nullptr)
|
||||
if (m_selectedProvider == nullptr)
|
||||
return;
|
||||
|
||||
// Decode bytes using registered inspectors
|
||||
@@ -69,7 +69,7 @@ namespace hex::plugin::builtin {
|
||||
|
||||
// Try to read as many bytes as requested and possible
|
||||
std::vector<u8> buffer(validBytes > entry.maxSize ? entry.maxSize : validBytes);
|
||||
this->m_selectedProvider->read(startAddress, buffer.data(), buffer.size());
|
||||
m_selectedProvider->read(startAddress, buffer.data(), buffer.size());
|
||||
|
||||
// Handle invert setting
|
||||
if (invert) {
|
||||
@@ -78,7 +78,7 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
// Insert processed data into the inspector list
|
||||
this->m_workData.push_back({
|
||||
m_workData.push_back({
|
||||
entry.unlocalizedName,
|
||||
entry.generatorFunction(buffer, endian, numberDisplayStyle),
|
||||
entry.editingFunction,
|
||||
@@ -94,13 +94,13 @@ namespace hex::plugin::builtin {
|
||||
};
|
||||
|
||||
// Setup a new pattern language runtime
|
||||
ContentRegistry::PatternLanguage::configureRuntime(this->m_runtime, this->m_selectedProvider);
|
||||
ContentRegistry::PatternLanguage::configureRuntime(m_runtime, m_selectedProvider);
|
||||
|
||||
// Setup the runtime to read from the selected provider
|
||||
this->m_runtime.setDataSource(this->m_selectedProvider->getBaseAddress(), this->m_selectedProvider->getActualSize(),
|
||||
m_runtime.setDataSource(m_selectedProvider->getBaseAddress(), m_selectedProvider->getActualSize(),
|
||||
[this, invert](u64 offset, u8 *buffer, size_t size) {
|
||||
// Read bytes from the selected provider
|
||||
this->m_selectedProvider->read(offset, buffer, size);
|
||||
m_selectedProvider->read(offset, buffer, size);
|
||||
|
||||
// Handle invert setting
|
||||
if (invert) {
|
||||
@@ -110,13 +110,13 @@ namespace hex::plugin::builtin {
|
||||
});
|
||||
|
||||
// Prevent dangerous function calls
|
||||
this->m_runtime.setDangerousFunctionCallHandler([] { return false; });
|
||||
m_runtime.setDangerousFunctionCallHandler([] { return false; });
|
||||
|
||||
// Set the default endianness based on the endian setting
|
||||
this->m_runtime.setDefaultEndian(endian);
|
||||
m_runtime.setDefaultEndian(endian);
|
||||
|
||||
// Set start address to the selected address
|
||||
this->m_runtime.setStartAddress(startAddress);
|
||||
m_runtime.setStartAddress(startAddress);
|
||||
|
||||
// Loop over all files in the inspectors folder and execute them
|
||||
for (const auto &folderPath : fs::getDefaultPaths(fs::ImHexPath::Inspectors)) {
|
||||
@@ -133,10 +133,10 @@ namespace hex::plugin::builtin {
|
||||
|
||||
// Execute the inspector file
|
||||
if (!inspectorCode.empty()) {
|
||||
if (this->m_runtime.executeString(inspectorCode, {}, inVariables, true)) {
|
||||
if (m_runtime.executeString(inspectorCode, {}, inVariables, true)) {
|
||||
|
||||
// Loop over patterns produced by the runtime
|
||||
const auto &patterns = this->m_runtime.getPatterns();
|
||||
const auto &patterns = m_runtime.getPatterns();
|
||||
for (const auto &pattern : patterns) {
|
||||
// Skip hidden patterns
|
||||
if (pattern->getVisibility() == pl::ptrn::Visibility::Hidden)
|
||||
@@ -166,7 +166,7 @@ namespace hex::plugin::builtin {
|
||||
};
|
||||
|
||||
// Insert the inspector into the list
|
||||
this->m_workData.push_back({
|
||||
m_workData.push_back({
|
||||
pattern->getDisplayName(),
|
||||
displayFunction,
|
||||
editingFunction,
|
||||
@@ -180,7 +180,7 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const auto& error = this->m_runtime.getError();
|
||||
const auto& error = m_runtime.getError();
|
||||
|
||||
log::error("Failed to execute custom inspector file '{}'!", wolv::util::toUTF8String(filePath));
|
||||
if (error.has_value())
|
||||
@@ -191,46 +191,46 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
}
|
||||
|
||||
this->m_dataValid = true;
|
||||
m_dataValid = true;
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
void ViewDataInspector::drawContent() {
|
||||
if (this->m_dataValid && !this->m_updateTask.isRunning()) {
|
||||
this->m_dataValid = false;
|
||||
this->m_cachedData = std::move(this->m_workData);
|
||||
if (m_dataValid && !m_updateTask.isRunning()) {
|
||||
m_dataValid = false;
|
||||
m_cachedData = std::move(m_workData);
|
||||
}
|
||||
|
||||
if (this->m_shouldInvalidate && !this->m_updateTask.isRunning()) {
|
||||
this->m_shouldInvalidate = false;
|
||||
if (m_shouldInvalidate && !m_updateTask.isRunning()) {
|
||||
m_shouldInvalidate = false;
|
||||
|
||||
this->updateInspectorRows();
|
||||
}
|
||||
|
||||
if (this->m_selectedProvider != nullptr && this->m_selectedProvider->isReadable() && this->m_validBytes > 0) {
|
||||
u32 validLineCount = this->m_cachedData.size();
|
||||
if (!this->m_tableEditingModeEnabled) {
|
||||
validLineCount = std::count_if(this->m_cachedData.begin(), this->m_cachedData.end(), [this](const auto &entry) {
|
||||
return !this->m_hiddenValues.contains(entry.filterValue);
|
||||
if (m_selectedProvider != nullptr && m_selectedProvider->isReadable() && m_validBytes > 0) {
|
||||
u32 validLineCount = m_cachedData.size();
|
||||
if (!m_tableEditingModeEnabled) {
|
||||
validLineCount = std::count_if(m_cachedData.begin(), m_cachedData.end(), [this](const auto &entry) {
|
||||
return !m_hiddenValues.contains(entry.filterValue);
|
||||
});
|
||||
}
|
||||
|
||||
if (ImGui::BeginTable("##datainspector", this->m_tableEditingModeEnabled ? 3 : 2, ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_RowBg, ImVec2(0, ImGui::GetTextLineHeightWithSpacing() * (validLineCount + 1)))) {
|
||||
if (ImGui::BeginTable("##datainspector", m_tableEditingModeEnabled ? 3 : 2, ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_RowBg, ImVec2(0, ImGui::GetTextLineHeightWithSpacing() * (validLineCount + 1)))) {
|
||||
ImGui::TableSetupScrollFreeze(0, 1);
|
||||
ImGui::TableSetupColumn("hex.builtin.view.data_inspector.table.name"_lang, ImGuiTableColumnFlags_WidthFixed);
|
||||
ImGui::TableSetupColumn("hex.builtin.view.data_inspector.table.value"_lang, ImGuiTableColumnFlags_WidthStretch);
|
||||
|
||||
if (this->m_tableEditingModeEnabled)
|
||||
if (m_tableEditingModeEnabled)
|
||||
ImGui::TableSetupColumn("##favorite", ImGuiTableColumnFlags_WidthFixed, ImGui::GetTextLineHeight());
|
||||
|
||||
ImGui::TableHeadersRow();
|
||||
|
||||
int inspectorRowId = 1;
|
||||
for (auto &[unlocalizedName, displayFunction, editingFunction, editing, filterValue] : this->m_cachedData) {
|
||||
for (auto &[unlocalizedName, displayFunction, editingFunction, editing, filterValue] : m_cachedData) {
|
||||
bool grayedOut = false;
|
||||
if (this->m_hiddenValues.contains(filterValue)) {
|
||||
if (!this->m_tableEditingModeEnabled)
|
||||
if (m_hiddenValues.contains(filterValue)) {
|
||||
if (!m_tableEditingModeEnabled)
|
||||
continue;
|
||||
else
|
||||
grayedOut = true;
|
||||
@@ -262,7 +262,7 @@ namespace hex::plugin::builtin {
|
||||
// Enter editing mode when double-clicking the row
|
||||
if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left) && editingFunction.has_value()) {
|
||||
editing = true;
|
||||
this->m_editingValue = copyValue;
|
||||
m_editingValue = copyValue;
|
||||
}
|
||||
|
||||
} else {
|
||||
@@ -273,49 +273,49 @@ namespace hex::plugin::builtin {
|
||||
ImGui::SetKeyboardFocusHere();
|
||||
|
||||
// Draw input text box
|
||||
if (ImGui::InputText("##InspectorLineEditing", this->m_editingValue, ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_AutoSelectAll)) {
|
||||
if (ImGui::InputText("##InspectorLineEditing", m_editingValue, ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_AutoSelectAll)) {
|
||||
// Turn the entered value into bytes
|
||||
auto bytes = editingFunction.value()(this->m_editingValue, this->m_endian);
|
||||
auto bytes = editingFunction.value()(m_editingValue, m_endian);
|
||||
|
||||
if (this->m_invert)
|
||||
if (m_invert)
|
||||
std::ranges::transform(bytes, bytes.begin(), [](auto byte) { return byte ^ 0xFF; });
|
||||
|
||||
// Write those bytes to the selected provider at the current address
|
||||
this->m_selectedProvider->write(this->m_startAddress, bytes.data(), bytes.size());
|
||||
m_selectedProvider->write(m_startAddress, bytes.data(), bytes.size());
|
||||
|
||||
// Disable editing mode
|
||||
this->m_editingValue.clear();
|
||||
m_editingValue.clear();
|
||||
editing = false;
|
||||
|
||||
// Reload all inspector rows
|
||||
this->m_shouldInvalidate = true;
|
||||
m_shouldInvalidate = true;
|
||||
}
|
||||
ImGui::PopStyleVar();
|
||||
|
||||
// Disable editing mode when clicking outside the input text box
|
||||
if (!ImGui::IsItemHovered() && ImGui::IsMouseClicked(ImGuiMouseButton_Left)) {
|
||||
this->m_editingValue.clear();
|
||||
m_editingValue.clear();
|
||||
editing = false;
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::EndDisabled();
|
||||
|
||||
if (this->m_tableEditingModeEnabled) {
|
||||
if (m_tableEditingModeEnabled) {
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImGui::GetStyleColorVec4(ImGuiCol_Text));
|
||||
|
||||
bool hidden = this->m_hiddenValues.contains(filterValue);
|
||||
bool hidden = m_hiddenValues.contains(filterValue);
|
||||
if (ImGuiExt::DimmedButton(hidden ? ICON_VS_EYE : ICON_VS_EYE_CLOSED)) {
|
||||
if (hidden)
|
||||
this->m_hiddenValues.erase(filterValue);
|
||||
m_hiddenValues.erase(filterValue);
|
||||
else
|
||||
this->m_hiddenValues.insert(filterValue);
|
||||
m_hiddenValues.insert(filterValue);
|
||||
|
||||
{
|
||||
std::vector filterValues(this->m_hiddenValues.begin(), this->m_hiddenValues.end());
|
||||
std::vector filterValues(m_hiddenValues.begin(), m_hiddenValues.end());
|
||||
|
||||
ContentRegistry::Settings::write("hex.builtin.setting.data_inspector", "hex.builtin.setting.data_inspector.hidden_rows", filterValues);
|
||||
}
|
||||
@@ -332,7 +332,7 @@ namespace hex::plugin::builtin {
|
||||
ImGui::EndTable();
|
||||
}
|
||||
|
||||
ImGuiExt::DimmedButtonToggle("hex.builtin.common.edit"_lang, &this->m_tableEditingModeEnabled, ImVec2(ImGui::GetContentRegionAvail().x, 0));
|
||||
ImGuiExt::DimmedButtonToggle("hex.builtin.common.edit"_lang, &m_tableEditingModeEnabled, ImVec2(ImGui::GetContentRegionAvail().x, 0));
|
||||
|
||||
ImGui::NewLine();
|
||||
ImGui::Separator();
|
||||
@@ -343,7 +343,7 @@ namespace hex::plugin::builtin {
|
||||
// Draw endian setting
|
||||
{
|
||||
int selection = [this] {
|
||||
switch (this->m_endian) {
|
||||
switch (m_endian) {
|
||||
default:
|
||||
case std::endian::little: return 0;
|
||||
case std::endian::big: return 1;
|
||||
@@ -353,12 +353,12 @@ namespace hex::plugin::builtin {
|
||||
std::array options = { "hex.builtin.common.little"_lang, "hex.builtin.common.big"_lang };
|
||||
|
||||
if (ImGui::SliderInt("hex.builtin.common.endian"_lang, &selection, 0, options.size() - 1, options[selection], ImGuiSliderFlags_NoInput)) {
|
||||
this->m_shouldInvalidate = true;
|
||||
m_shouldInvalidate = true;
|
||||
|
||||
switch (selection) {
|
||||
default:
|
||||
case 0: this->m_endian = std::endian::little; break;
|
||||
case 1: this->m_endian = std::endian::big; break;
|
||||
case 0: m_endian = std::endian::little; break;
|
||||
case 1: m_endian = std::endian::big; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -366,7 +366,7 @@ namespace hex::plugin::builtin {
|
||||
// Draw radix setting
|
||||
{
|
||||
int selection = [this] {
|
||||
switch (this->m_numberDisplayStyle) {
|
||||
switch (m_numberDisplayStyle) {
|
||||
default:
|
||||
case NumberDisplayStyle::Decimal: return 0;
|
||||
case NumberDisplayStyle::Hexadecimal: return 1;
|
||||
@@ -376,26 +376,26 @@ namespace hex::plugin::builtin {
|
||||
std::array options = { "hex.builtin.common.decimal"_lang, "hex.builtin.common.hexadecimal"_lang, "hex.builtin.common.octal"_lang };
|
||||
|
||||
if (ImGui::SliderInt("hex.builtin.common.number_format"_lang, &selection, 0, options.size() - 1, options[selection], ImGuiSliderFlags_NoInput)) {
|
||||
this->m_shouldInvalidate = true;
|
||||
m_shouldInvalidate = true;
|
||||
|
||||
switch (selection) {
|
||||
default:
|
||||
case 0: this->m_numberDisplayStyle = NumberDisplayStyle::Decimal; break;
|
||||
case 1: this->m_numberDisplayStyle = NumberDisplayStyle::Hexadecimal; break;
|
||||
case 2: this->m_numberDisplayStyle = NumberDisplayStyle::Octal; break;
|
||||
case 0: m_numberDisplayStyle = NumberDisplayStyle::Decimal; break;
|
||||
case 1: m_numberDisplayStyle = NumberDisplayStyle::Hexadecimal; break;
|
||||
case 2: m_numberDisplayStyle = NumberDisplayStyle::Octal; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Draw invert setting
|
||||
{
|
||||
int selection = this->m_invert ? 1 : 0;
|
||||
int selection = m_invert ? 1 : 0;
|
||||
std::array options = { "hex.builtin.common.no"_lang, "hex.builtin.common.yes"_lang };
|
||||
|
||||
if (ImGui::SliderInt("hex.builtin.view.data_inspector.invert"_lang, &selection, 0, options.size() - 1, options[selection], ImGuiSliderFlags_NoInput)) {
|
||||
this->m_shouldInvalidate = true;
|
||||
m_shouldInvalidate = true;
|
||||
|
||||
this->m_invert = selection == 1;
|
||||
m_invert = selection == 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -29,26 +29,26 @@ namespace hex::plugin::builtin {
|
||||
void drawNode() override {
|
||||
ImGui::PushItemWidth(100_scaled);
|
||||
// Draw combo box to select the type of the input
|
||||
if (ImGui::Combo("##type", &this->m_type, "Integer\0Float\0Buffer\0")) {
|
||||
if (ImGui::Combo("##type", &m_type, "Integer\0Float\0Buffer\0")) {
|
||||
this->setAttributes({
|
||||
{ dp::Attribute(dp::Attribute::IOType::Out, this->getType(), "hex.builtin.nodes.common.input") }
|
||||
});
|
||||
}
|
||||
|
||||
// Draw text input to set the name of the input
|
||||
if (ImGui::InputText("##name", this->m_name)) {
|
||||
this->setUnlocalizedTitle(this->m_name);
|
||||
if (ImGui::InputText("##name", m_name)) {
|
||||
this->setUnlocalizedTitle(m_name);
|
||||
}
|
||||
|
||||
ImGui::PopItemWidth();
|
||||
}
|
||||
|
||||
void setValue(auto value) { this->m_value = std::move(value); }
|
||||
void setValue(auto value) { m_value = std::move(value); }
|
||||
|
||||
const std::string &getName() const { return this->m_name; }
|
||||
const std::string &getName() const { return m_name; }
|
||||
|
||||
dp::Attribute::Type getType() const {
|
||||
switch (this->m_type) {
|
||||
switch (m_type) {
|
||||
default:
|
||||
case 0: return dp::Attribute::Type::Integer;
|
||||
case 1: return dp::Attribute::Type::Float;
|
||||
@@ -61,21 +61,21 @@ namespace hex::plugin::builtin {
|
||||
[this](i128 value) { this->setIntegerOnOutput(0, value); },
|
||||
[this](long double value) { this->setFloatOnOutput(0, value); },
|
||||
[this](const std::vector<u8> &value) { this->setBufferOnOutput(0, value); }
|
||||
}, this->m_value);
|
||||
}, m_value);
|
||||
}
|
||||
|
||||
void store(nlohmann::json &j) const override {
|
||||
j = nlohmann::json::object();
|
||||
|
||||
j["name"] = this->m_name;
|
||||
j["type"] = this->m_type;
|
||||
j["name"] = m_name;
|
||||
j["type"] = m_type;
|
||||
}
|
||||
|
||||
void load(const nlohmann::json &j) override {
|
||||
this->m_name = j.at("name").get<std::string>();
|
||||
this->m_type = j.at("type");
|
||||
m_name = j.at("name").get<std::string>();
|
||||
m_type = j.at("type");
|
||||
|
||||
this->setUnlocalizedTitle(this->m_name);
|
||||
this->setUnlocalizedTitle(m_name);
|
||||
this->setAttributes({
|
||||
{ dp::Attribute(dp::Attribute::IOType::Out, this->getType(), "hex.builtin.nodes.common.input") }
|
||||
});
|
||||
@@ -100,23 +100,23 @@ namespace hex::plugin::builtin {
|
||||
ImGui::PushItemWidth(100_scaled);
|
||||
|
||||
// Draw combo box to select the type of the output
|
||||
if (ImGui::Combo("##type", &this->m_type, "Integer\0Float\0Buffer\0")) {
|
||||
if (ImGui::Combo("##type", &m_type, "Integer\0Float\0Buffer\0")) {
|
||||
this->setAttributes({
|
||||
{ dp::Attribute(dp::Attribute::IOType::In, this->getType(), "hex.builtin.nodes.common.output") }
|
||||
});
|
||||
}
|
||||
|
||||
// Draw text input to set the name of the output
|
||||
if (ImGui::InputText("##name", this->m_name)) {
|
||||
this->setUnlocalizedTitle(this->m_name);
|
||||
if (ImGui::InputText("##name", m_name)) {
|
||||
this->setUnlocalizedTitle(m_name);
|
||||
}
|
||||
|
||||
ImGui::PopItemWidth();
|
||||
}
|
||||
|
||||
const std::string &getName() const { return this->m_name; }
|
||||
const std::string &getName() const { return m_name; }
|
||||
dp::Attribute::Type getType() const {
|
||||
switch (this->m_type) {
|
||||
switch (m_type) {
|
||||
case 0: return dp::Attribute::Type::Integer;
|
||||
case 1: return dp::Attribute::Type::Float;
|
||||
case 2: return dp::Attribute::Type::Buffer;
|
||||
@@ -126,26 +126,26 @@ namespace hex::plugin::builtin {
|
||||
|
||||
void process() override {
|
||||
switch (this->getType()) {
|
||||
case dp::Attribute::Type::Integer: this->m_value = this->getIntegerOnInput(0); break;
|
||||
case dp::Attribute::Type::Float: this->m_value = this->getFloatOnInput(0); break;
|
||||
case dp::Attribute::Type::Buffer: this->m_value = this->getBufferOnInput(0); break;
|
||||
case dp::Attribute::Type::Integer: m_value = this->getIntegerOnInput(0); break;
|
||||
case dp::Attribute::Type::Float: m_value = this->getFloatOnInput(0); break;
|
||||
case dp::Attribute::Type::Buffer: m_value = this->getBufferOnInput(0); break;
|
||||
}
|
||||
}
|
||||
|
||||
const auto& getValue() const { return this->m_value; }
|
||||
const auto& getValue() const { return m_value; }
|
||||
|
||||
void store(nlohmann::json &j) const override {
|
||||
j = nlohmann::json::object();
|
||||
|
||||
j["name"] = this->m_name;
|
||||
j["type"] = this->m_type;
|
||||
j["name"] = m_name;
|
||||
j["type"] = m_type;
|
||||
}
|
||||
|
||||
void load(const nlohmann::json &j) override {
|
||||
this->m_name = j.at("name").get<std::string>();
|
||||
this->m_type = j.at("type");
|
||||
m_name = j.at("name").get<std::string>();
|
||||
m_type = j.at("type");
|
||||
|
||||
this->setUnlocalizedTitle(this->m_name);
|
||||
this->setUnlocalizedTitle(m_name);
|
||||
this->setAttributes({
|
||||
{ dp::Attribute(dp::Attribute::IOType::In, this->getType(), "hex.builtin.nodes.common.output") }
|
||||
});
|
||||
@@ -168,8 +168,8 @@ namespace hex::plugin::builtin {
|
||||
|
||||
void drawNode() override {
|
||||
// Update attributes if we have to
|
||||
if (this->m_requiresAttributeUpdate) {
|
||||
this->m_requiresAttributeUpdate = false;
|
||||
if (m_requiresAttributeUpdate) {
|
||||
m_requiresAttributeUpdate = false;
|
||||
|
||||
// Find all input and output nodes that are used by the workspace of this node
|
||||
// and set the attributes of this node to the attributes of the input and output nodes
|
||||
@@ -179,9 +179,9 @@ namespace hex::plugin::builtin {
|
||||
ImGui::PushItemWidth(200_scaled);
|
||||
|
||||
bool editing = false;
|
||||
if (this->m_editable) {
|
||||
if (m_editable) {
|
||||
// Draw name input field
|
||||
ImGuiExt::InputTextIcon("##name", ICON_VS_SYMBOL_KEY, this->m_name);
|
||||
ImGuiExt::InputTextIcon("##name", ICON_VS_SYMBOL_KEY, m_name);
|
||||
|
||||
// Prevent editing mode from deactivating when the input field is focused
|
||||
editing = ImGui::IsItemActive();
|
||||
@@ -191,12 +191,12 @@ namespace hex::plugin::builtin {
|
||||
AchievementManager::unlockAchievement("hex.builtin.achievement.data_processor", "hex.builtin.achievement.data_processor.custom_node.name");
|
||||
|
||||
// Open the custom node's workspace
|
||||
this->m_dataProcessor->getWorkspaceStack().push_back(&this->m_workspace);
|
||||
m_dataProcessor->getWorkspaceStack().push_back(&m_workspace);
|
||||
|
||||
this->m_requiresAttributeUpdate = true;
|
||||
m_requiresAttributeUpdate = true;
|
||||
}
|
||||
} else {
|
||||
this->setUnlocalizedTitle(this->m_name);
|
||||
this->setUnlocalizedTitle(m_name);
|
||||
|
||||
if (this->getAttributes().empty()) {
|
||||
ImGui::TextUnformatted("hex.builtin.nodes.custom.custom.edit_hint"_lang);
|
||||
@@ -204,7 +204,7 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
// Enable editing mode when the shift button is pressed
|
||||
this->m_editable = ImGui::GetIO().KeyShift || editing;
|
||||
m_editable = ImGui::GetIO().KeyShift || editing;
|
||||
|
||||
ImGui::PopItemWidth();
|
||||
}
|
||||
@@ -220,7 +220,7 @@ namespace hex::plugin::builtin {
|
||||
};
|
||||
|
||||
auto prevContext = ImNodes::GetCurrentContext();
|
||||
ImNodes::SetCurrentContext(this->m_workspace.context.get());
|
||||
ImNodes::SetCurrentContext(m_workspace.context.get());
|
||||
ON_SCOPE_EXIT { ImNodes::SetCurrentContext(prevContext); };
|
||||
|
||||
// Forward inputs to input nodes values
|
||||
@@ -251,11 +251,11 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
// Process all nodes in our workspace
|
||||
for (auto &endNode : this->m_workspace.endNodes) {
|
||||
for (auto &endNode : m_workspace.endNodes) {
|
||||
endNode->resetOutputData();
|
||||
|
||||
// Reset processed inputs of all nodes
|
||||
for (auto &node : this->m_workspace.nodes)
|
||||
for (auto &node : m_workspace.nodes)
|
||||
node->resetProcessedInputs();
|
||||
|
||||
endNode->process();
|
||||
@@ -294,14 +294,14 @@ namespace hex::plugin::builtin {
|
||||
void store(nlohmann::json &j) const override {
|
||||
j = nlohmann::json::object();
|
||||
|
||||
j["nodes"] = this->m_dataProcessor->saveNodes(this->m_workspace);
|
||||
j["nodes"] = m_dataProcessor->saveNodes(m_workspace);
|
||||
}
|
||||
|
||||
void load(const nlohmann::json &j) override {
|
||||
this->m_dataProcessor->loadNodes(this->m_workspace, j.at("nodes"));
|
||||
m_dataProcessor->loadNodes(m_workspace, j.at("nodes"));
|
||||
|
||||
this->m_name = Lang(this->getUnlocalizedTitle()).get();
|
||||
this->m_requiresAttributeUpdate = true;
|
||||
m_name = Lang(this->getUnlocalizedTitle()).get();
|
||||
m_requiresAttributeUpdate = true;
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -309,7 +309,7 @@ namespace hex::plugin::builtin {
|
||||
std::vector<dp::Attribute> result;
|
||||
|
||||
// Search through all nodes in the workspace and add all input and output nodes to the result
|
||||
for (auto &node : this->m_workspace.nodes) {
|
||||
for (auto &node : m_workspace.nodes) {
|
||||
if (auto *inputNode = dynamic_cast<NodeCustomInput*>(node.get()); inputNode != nullptr)
|
||||
result.emplace_back(dp::Attribute::IOType::In, inputNode->getType(), inputNode->getName());
|
||||
else if (auto *outputNode = dynamic_cast<NodeCustomOutput*>(node.get()); outputNode != nullptr)
|
||||
@@ -320,7 +320,7 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
NodeCustomInput* findInput(const std::string &name) const {
|
||||
for (auto &node : this->m_workspace.nodes) {
|
||||
for (auto &node : m_workspace.nodes) {
|
||||
if (auto *inputNode = dynamic_cast<NodeCustomInput*>(node.get()); inputNode != nullptr && inputNode->getName() == name)
|
||||
return inputNode;
|
||||
}
|
||||
@@ -329,7 +329,7 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
NodeCustomOutput* findOutput(const std::string &name) const {
|
||||
for (auto &node : this->m_workspace.nodes) {
|
||||
for (auto &node : m_workspace.nodes) {
|
||||
if (auto *outputNode = dynamic_cast<NodeCustomOutput*>(node.get()); outputNode != nullptr && outputNode->getName() == name)
|
||||
return outputNode;
|
||||
}
|
||||
@@ -358,25 +358,25 @@ namespace hex::plugin::builtin {
|
||||
.load = [this](prv::Provider *provider, const std::fs::path &basePath, Tar &tar) {
|
||||
std::string save = tar.readString(basePath);
|
||||
|
||||
ViewDataProcessor::loadNodes(this->m_mainWorkspace.get(provider), nlohmann::json::parse(save));
|
||||
this->m_updateNodePositions = true;
|
||||
ViewDataProcessor::loadNodes(m_mainWorkspace.get(provider), nlohmann::json::parse(save));
|
||||
m_updateNodePositions = true;
|
||||
|
||||
return true;
|
||||
},
|
||||
.store = [this](prv::Provider *provider, const std::fs::path &basePath, Tar &tar) {
|
||||
tar.writeString(basePath, ViewDataProcessor::saveNodes(this->m_mainWorkspace.get(provider)).dump(4));
|
||||
tar.writeString(basePath, ViewDataProcessor::saveNodes(m_mainWorkspace.get(provider)).dump(4));
|
||||
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
EventProviderCreated::subscribe(this, [this](auto *provider) {
|
||||
this->m_mainWorkspace.get(provider) = { };
|
||||
this->m_workspaceStack.get(provider).push_back(&this->m_mainWorkspace.get(provider));
|
||||
m_mainWorkspace.get(provider) = { };
|
||||
m_workspaceStack.get(provider).push_back(&m_mainWorkspace.get(provider));
|
||||
});
|
||||
|
||||
EventProviderChanged::subscribe(this, [this](const auto *, const auto *) {
|
||||
for (auto *workspace : *this->m_workspaceStack) {
|
||||
for (auto *workspace : *m_workspaceStack) {
|
||||
for (auto &node : workspace->nodes) {
|
||||
node->setCurrentOverlay(nullptr);
|
||||
}
|
||||
@@ -384,11 +384,11 @@ namespace hex::plugin::builtin {
|
||||
workspace->dataOverlays.clear();
|
||||
}
|
||||
|
||||
this->m_updateNodePositions = true;
|
||||
m_updateNodePositions = true;
|
||||
});
|
||||
|
||||
EventDataChanged::subscribe(this, [this] {
|
||||
ViewDataProcessor::processNodes(*this->m_workspaceStack->back());
|
||||
ViewDataProcessor::processNodes(*m_workspaceStack->back());
|
||||
});
|
||||
|
||||
/* Import Nodes */
|
||||
@@ -397,8 +397,8 @@ namespace hex::plugin::builtin {
|
||||
[&](const std::fs::path &path) {
|
||||
wolv::io::File file(path, wolv::io::File::Mode::Read);
|
||||
if (file.isValid()) {
|
||||
ViewDataProcessor::loadNodes(*this->m_mainWorkspace, nlohmann::json::parse(file.readString()));
|
||||
this->m_updateNodePositions = true;
|
||||
ViewDataProcessor::loadNodes(*m_mainWorkspace, nlohmann::json::parse(file.readString()));
|
||||
m_updateNodePositions = true;
|
||||
}
|
||||
});
|
||||
}, ImHexApi::Provider::isValid);
|
||||
@@ -409,18 +409,18 @@ namespace hex::plugin::builtin {
|
||||
[&, this](const std::fs::path &path) {
|
||||
wolv::io::File file(path, wolv::io::File::Mode::Create);
|
||||
if (file.isValid())
|
||||
file.writeString(ViewDataProcessor::saveNodes(*this->m_mainWorkspace).dump(4));
|
||||
file.writeString(ViewDataProcessor::saveNodes(*m_mainWorkspace).dump(4));
|
||||
});
|
||||
}, [this]{
|
||||
return !this->m_workspaceStack->empty() && !this->m_workspaceStack->back()->nodes.empty() && ImHexApi::Provider::isValid();
|
||||
return !m_workspaceStack->empty() && !m_workspaceStack->back()->nodes.empty() && ImHexApi::Provider::isValid();
|
||||
});
|
||||
|
||||
ContentRegistry::FileHandler::add({ ".hexnode" }, [this](const auto &path) {
|
||||
wolv::io::File file(path, wolv::io::File::Mode::Read);
|
||||
if (!file.isValid()) return false;
|
||||
|
||||
ViewDataProcessor::loadNodes(*this->m_mainWorkspace, file.readString());
|
||||
this->m_updateNodePositions = true;
|
||||
ViewDataProcessor::loadNodes(*m_mainWorkspace, file.readString());
|
||||
m_updateNodePositions = true;
|
||||
|
||||
return true;
|
||||
});
|
||||
@@ -563,7 +563,7 @@ namespace hex::plugin::builtin {
|
||||
|
||||
void ViewDataProcessor::reloadCustomNodes() {
|
||||
// Delete all custom nodes
|
||||
this->m_customNodes.clear();
|
||||
m_customNodes.clear();
|
||||
|
||||
// Loop over all custom node folders
|
||||
for (const auto &basePath : fs::getDefaultPaths(fs::ImHexPath::Nodes)) {
|
||||
@@ -579,7 +579,7 @@ namespace hex::plugin::builtin {
|
||||
nlohmann::json nodeJson = nlohmann::json::parse(file.readString());
|
||||
|
||||
// Add the loaded node to the list of custom nodes
|
||||
this->m_customNodes.push_back(CustomNode { Lang(nodeJson.at("name").get<std::string>()), nodeJson });
|
||||
m_customNodes.push_back(CustomNode { Lang(nodeJson.at("name").get<std::string>()), nodeJson });
|
||||
} catch (nlohmann::json::exception &e) {
|
||||
log::warn("Failed to load custom node '{}': {}", entry.path().string(), e.what());
|
||||
}
|
||||
@@ -595,13 +595,13 @@ namespace hex::plugin::builtin {
|
||||
ImNodes::ClearLinkSelection();
|
||||
|
||||
// Save the current mouse position
|
||||
this->m_rightClickedCoords = ImGui::GetMousePos();
|
||||
m_rightClickedCoords = ImGui::GetMousePos();
|
||||
|
||||
// Show a different context menu depending on if a node, a link
|
||||
// or the background was right-clicked
|
||||
if (ImNodes::IsNodeHovered(&this->m_rightClickedId))
|
||||
if (ImNodes::IsNodeHovered(&m_rightClickedId))
|
||||
ImGui::OpenPopup("Node Menu");
|
||||
else if (ImNodes::IsLinkHovered(&this->m_rightClickedId))
|
||||
else if (ImNodes::IsLinkHovered(&m_rightClickedId))
|
||||
ImGui::OpenPopup("Link Menu");
|
||||
else {
|
||||
ImGui::OpenPopup("Context Menu");
|
||||
@@ -665,7 +665,7 @@ namespace hex::plugin::builtin {
|
||||
ImGui::Separator();
|
||||
|
||||
// Draw entries for each custom node
|
||||
for (auto &customNode : this->m_customNodes) {
|
||||
for (auto &customNode : m_customNodes) {
|
||||
if (ImGui::MenuItem(customNode.name.c_str())) {
|
||||
node = loadNode(customNode.data);
|
||||
}
|
||||
@@ -694,7 +694,7 @@ namespace hex::plugin::builtin {
|
||||
workspace.endNodes.push_back(node.get());
|
||||
|
||||
// Set the position of the node to the position where the user right-clicked
|
||||
ImNodes::SetNodeScreenSpacePos(node->getId(), this->m_rightClickedCoords);
|
||||
ImNodes::SetNodeScreenSpacePos(node->getId(), m_rightClickedCoords);
|
||||
workspace.nodes.push_back(std::move(node));
|
||||
|
||||
ImHexApi::Provider::markDirty();
|
||||
@@ -710,7 +710,7 @@ namespace hex::plugin::builtin {
|
||||
// Find the node that was right-clicked
|
||||
auto it = std::find_if(workspace.nodes.begin(), workspace.nodes.end(),
|
||||
[this](const auto &node) {
|
||||
return node->getId() == this->m_rightClickedId;
|
||||
return node->getId() == m_rightClickedId;
|
||||
});
|
||||
|
||||
// Check if the node was found
|
||||
@@ -728,7 +728,7 @@ namespace hex::plugin::builtin {
|
||||
ImGui::Separator();
|
||||
|
||||
if (ImGui::MenuItem("hex.builtin.view.data_processor.menu.remove_node"_lang))
|
||||
this->eraseNodes(workspace, { this->m_rightClickedId });
|
||||
this->eraseNodes(workspace, { m_rightClickedId });
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
@@ -736,7 +736,7 @@ namespace hex::plugin::builtin {
|
||||
// Draw link right click menu
|
||||
if (ImGui::BeginPopup("Link Menu")) {
|
||||
if (ImGui::MenuItem("hex.builtin.view.data_processor.menu.remove_link"_lang))
|
||||
this->eraseLink(workspace, this->m_rightClickedId);
|
||||
this->eraseLink(workspace, m_rightClickedId);
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
@@ -745,7 +745,7 @@ namespace hex::plugin::builtin {
|
||||
void ViewDataProcessor::drawNode(dp::Node &node) const {
|
||||
// If a node position update is pending, update the node position
|
||||
int nodeId = node.getId();
|
||||
if (this->m_updateNodePositions) {
|
||||
if (m_updateNodePositions) {
|
||||
ImNodes::SetNodeGridSpacePos(nodeId, node.getPosition());
|
||||
} else {
|
||||
if (ImNodes::ObjectPoolFind(ImNodes::EditorContextGet().Nodes, nodeId) >= 0)
|
||||
@@ -839,7 +839,7 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
void ViewDataProcessor::drawContent() {
|
||||
auto &workspace = *this->m_workspaceStack->back();
|
||||
auto &workspace = *m_workspaceStack->back();
|
||||
|
||||
bool popWorkspace = false;
|
||||
// Set the ImNodes context to the current workspace context
|
||||
@@ -879,7 +879,7 @@ namespace hex::plugin::builtin {
|
||||
ImNodes::PopColorStyle();
|
||||
}
|
||||
|
||||
this->m_updateNodePositions = false;
|
||||
m_updateNodePositions = false;
|
||||
|
||||
// Handle removing links that are connected to attributes that don't exist anymore
|
||||
{
|
||||
@@ -908,7 +908,7 @@ namespace hex::plugin::builtin {
|
||||
ImGuiExt::TextFormattedCentered("{}", "hex.builtin.view.data_processor.help_text"_lang);
|
||||
|
||||
// Draw a close button if there is more than one workspace on the stack
|
||||
if (this->m_workspaceStack->size() > 1) {
|
||||
if (m_workspaceStack->size() > 1) {
|
||||
ImGui::SetCursorPos(ImVec2(ImGui::GetContentRegionAvail().x - ImGui::GetTextLineHeightWithSpacing() * 1.5F, ImGui::GetTextLineHeightWithSpacing() * 0.2F));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(4.0F, 4.0F));
|
||||
if (ImGuiExt::DimmedIconButton(ICON_VS_CLOSE, ImGuiExt::GetCustomColorVec4(ImGuiCustomCol_ToolbarRed))) {
|
||||
@@ -923,12 +923,12 @@ namespace hex::plugin::builtin {
|
||||
|
||||
// Draw the control bar at the bottom
|
||||
{
|
||||
if (ImGuiExt::IconButton(ICON_VS_DEBUG_START, ImGuiExt::GetCustomColorVec4(ImGuiCustomCol_ToolbarGreen)) || this->m_continuousEvaluation)
|
||||
if (ImGuiExt::IconButton(ICON_VS_DEBUG_START, ImGuiExt::GetCustomColorVec4(ImGuiCustomCol_ToolbarGreen)) || m_continuousEvaluation)
|
||||
this->processNodes(workspace);
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::Checkbox("Continuous evaluation", &this->m_continuousEvaluation);
|
||||
ImGui::Checkbox("Continuous evaluation", &m_continuousEvaluation);
|
||||
}
|
||||
|
||||
|
||||
@@ -1016,8 +1016,8 @@ namespace hex::plugin::builtin {
|
||||
|
||||
// Remove the top-most workspace from the stack if requested
|
||||
if (popWorkspace) {
|
||||
this->m_workspaceStack->pop_back();
|
||||
this->m_updateNodePositions = true;
|
||||
m_workspaceStack->pop_back();
|
||||
m_updateNodePositions = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1192,7 +1192,7 @@ namespace hex::plugin::builtin {
|
||||
dp::Attribute::setIdCounter(maxAttrId + 1);
|
||||
dp::Link::setIdCounter(maxLinkId + 1);
|
||||
|
||||
this->m_updateNodePositions = true;
|
||||
m_updateNodePositions = true;
|
||||
} catch (nlohmann::json::exception &e) {
|
||||
PopupError::open(hex::format("Failed to load nodes: {}", e.what()));
|
||||
}
|
||||
|
||||
@@ -20,16 +20,16 @@ namespace hex::plugin::builtin {
|
||||
// Clear the selected diff providers when a provider is closed
|
||||
EventProviderClosed::subscribe(this, [this](prv::Provider *) {
|
||||
for (u8 i = 0; i < 2; i++) {
|
||||
this->m_columns[i].provider = -1;
|
||||
this->m_columns[i].hexEditor.setSelectionUnchecked(std::nullopt, std::nullopt);
|
||||
m_columns[i].provider = -1;
|
||||
m_columns[i].hexEditor.setSelectionUnchecked(std::nullopt, std::nullopt);
|
||||
}
|
||||
|
||||
this->m_diffs.clear();
|
||||
m_diffs.clear();
|
||||
});
|
||||
|
||||
// Set the background highlight callbacks for the two hex editor columns
|
||||
this->m_columns[0].hexEditor.setBackgroundHighlightCallback(this->createCompareFunction(1));
|
||||
this->m_columns[1].hexEditor.setBackgroundHighlightCallback(this->createCompareFunction(0));
|
||||
m_columns[0].hexEditor.setBackgroundHighlightCallback(this->createCompareFunction(1));
|
||||
m_columns[1].hexEditor.setBackgroundHighlightCallback(this->createCompareFunction(0));
|
||||
}
|
||||
|
||||
ViewDiff::~ViewDiff() {
|
||||
@@ -102,7 +102,7 @@ namespace hex::plugin::builtin {
|
||||
|
||||
return [this, otherIndex](u64 address, const u8 *data, size_t) -> std::optional<color_t> {
|
||||
const auto &providers = ImHexApi::Provider::getProviders();
|
||||
auto otherId = this->m_columns[otherIndex].provider;
|
||||
auto otherId = m_columns[otherIndex].provider;
|
||||
|
||||
// Check if the other provider is valid
|
||||
if (otherId < 0 || size_t(otherId) >= providers.size())
|
||||
@@ -133,7 +133,7 @@ namespace hex::plugin::builtin {
|
||||
|
||||
void ViewDiff::analyze(prv::Provider *providerA, prv::Provider *providerB) {
|
||||
auto commonSize = std::min(providerA->getActualSize(), providerB->getActualSize());
|
||||
this->m_diffTask = TaskManager::createTask("Diffing...", commonSize, [this, providerA, providerB](Task &task) {
|
||||
m_diffTask = TaskManager::createTask("Diffing...", commonSize, [this, providerA, providerB](Task &task) {
|
||||
std::vector<Diff> differences;
|
||||
|
||||
// Set up readers for both providers
|
||||
@@ -177,13 +177,13 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
// Move the calculated differences over so they can be displayed
|
||||
this->m_diffs = std::move(differences);
|
||||
this->m_analyzed = true;
|
||||
m_diffs = std::move(differences);
|
||||
m_analyzed = true;
|
||||
});
|
||||
}
|
||||
|
||||
void ViewDiff::drawContent() {
|
||||
auto &[a, b] = this->m_columns;
|
||||
auto &[a, b] = m_columns;
|
||||
|
||||
a.hexEditor.enableSyncScrolling(false);
|
||||
b.hexEditor.enableSyncScrolling(false);
|
||||
@@ -206,7 +206,7 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
// Analyze the providers if they are valid and the user selected a new provider
|
||||
if (!this->m_analyzed && a.provider != -1 && b.provider != -1 && !this->m_diffTask.isRunning()) {
|
||||
if (!m_analyzed && a.provider != -1 && b.provider != -1 && !m_diffTask.isRunning()) {
|
||||
const auto &providers = ImHexApi::Provider::getProviders();
|
||||
auto providerA = providers[a.provider];
|
||||
auto providerB = providers[b.provider];
|
||||
@@ -222,15 +222,15 @@ namespace hex::plugin::builtin {
|
||||
ImGui::TableSetupColumn("hex.builtin.view.diff.provider_b"_lang);
|
||||
ImGui::TableHeadersRow();
|
||||
|
||||
ImGui::BeginDisabled(this->m_diffTask.isRunning());
|
||||
ImGui::BeginDisabled(m_diffTask.isRunning());
|
||||
{
|
||||
// Draw first provider selector
|
||||
ImGui::TableNextColumn();
|
||||
if (drawProviderSelector(a)) this->m_analyzed = false;
|
||||
if (drawProviderSelector(a)) m_analyzed = false;
|
||||
|
||||
// Draw second provider selector
|
||||
ImGui::TableNextColumn();
|
||||
if (drawProviderSelector(b)) this->m_analyzed = false;
|
||||
if (drawProviderSelector(b)) m_analyzed = false;
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
|
||||
@@ -268,21 +268,21 @@ namespace hex::plugin::builtin {
|
||||
ImGui::TableHeadersRow();
|
||||
|
||||
// Draw the differences if the providers have been analyzed
|
||||
if (this->m_analyzed) {
|
||||
if (m_analyzed) {
|
||||
ImGuiListClipper clipper;
|
||||
clipper.Begin(int(this->m_diffs.size()));
|
||||
clipper.Begin(int(m_diffs.size()));
|
||||
|
||||
while (clipper.Step())
|
||||
for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) {
|
||||
ImGui::TableNextRow();
|
||||
|
||||
// Prevent the list from trying to access non-existing diffs
|
||||
if (size_t(i) >= this->m_diffs.size())
|
||||
if (size_t(i) >= m_diffs.size())
|
||||
break;
|
||||
|
||||
ImGui::PushID(i);
|
||||
|
||||
const auto &diff = this->m_diffs[i];
|
||||
const auto &diff = m_diffs[i];
|
||||
|
||||
// Draw a clickable row for each difference that will select the difference in both hex editors
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace hex::plugin::builtin {
|
||||
|
||||
ViewDisassembler::ViewDisassembler() : View::Window("hex.builtin.view.disassembler.name") {
|
||||
EventProviderDeleted::subscribe(this, [this](const auto*) {
|
||||
this->m_disassembly.clear();
|
||||
m_disassembly.clear();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -22,23 +22,23 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
void ViewDisassembler::disassemble() {
|
||||
this->m_disassembly.clear();
|
||||
m_disassembly.clear();
|
||||
|
||||
this->m_disassemblerTask = TaskManager::createTask("hex.builtin.view.disassembler.disassembling", this->m_codeRegion.getSize(), [this](auto &task) {
|
||||
m_disassemblerTask = TaskManager::createTask("hex.builtin.view.disassembler.disassembling", m_codeRegion.getSize(), [this](auto &task) {
|
||||
csh capstoneHandle;
|
||||
cs_insn *instructions = nullptr;
|
||||
|
||||
cs_mode mode = this->m_mode;
|
||||
cs_mode mode = m_mode;
|
||||
|
||||
// Create a capstone disassembler instance
|
||||
if (cs_open(Disassembler::toCapstoneArchitecture(this->m_architecture), mode, &capstoneHandle) == CS_ERR_OK) {
|
||||
if (cs_open(Disassembler::toCapstoneArchitecture(m_architecture), mode, &capstoneHandle) == CS_ERR_OK) {
|
||||
|
||||
// Tell capstone to skip data bytes
|
||||
cs_option(capstoneHandle, CS_OPT_SKIPDATA, CS_OPT_ON);
|
||||
|
||||
auto provider = ImHexApi::Provider::get();
|
||||
std::vector<u8> buffer(2048, 0x00);
|
||||
size_t size = this->m_codeRegion.getSize();
|
||||
size_t size = m_codeRegion.getSize();
|
||||
|
||||
// Read the data in chunks and disassemble it
|
||||
for (u64 address = 0; address < size; address += 2048) {
|
||||
@@ -46,15 +46,15 @@ namespace hex::plugin::builtin {
|
||||
|
||||
// Read a chunk of data
|
||||
size_t bufferSize = std::min(u64(2048), (size - address));
|
||||
provider->read(this->m_codeRegion.getStartAddress() + address, buffer.data(), bufferSize);
|
||||
provider->read(m_codeRegion.getStartAddress() + address, buffer.data(), bufferSize);
|
||||
|
||||
// Ask capstone to disassemble the data
|
||||
size_t instructionCount = cs_disasm(capstoneHandle, buffer.data(), bufferSize, this->m_baseAddress + address, 0, &instructions);
|
||||
size_t instructionCount = cs_disasm(capstoneHandle, buffer.data(), bufferSize, m_baseAddress + address, 0, &instructions);
|
||||
if (instructionCount == 0)
|
||||
break;
|
||||
|
||||
// Reserve enough space for the disassembly
|
||||
this->m_disassembly.reserve(this->m_disassembly.size() + instructionCount);
|
||||
m_disassembly.reserve(m_disassembly.size() + instructionCount);
|
||||
|
||||
// Convert the capstone instructions to our disassembly format
|
||||
u64 usedBytes = 0;
|
||||
@@ -62,7 +62,7 @@ namespace hex::plugin::builtin {
|
||||
const auto &instr = instructions[i];
|
||||
Disassembly disassembly = { };
|
||||
disassembly.address = instr.address;
|
||||
disassembly.offset = this->m_codeRegion.getStartAddress() + address + usedBytes;
|
||||
disassembly.offset = m_codeRegion.getStartAddress() + address + usedBytes;
|
||||
disassembly.size = instr.size;
|
||||
disassembly.mnemonic = instr.mnemonic;
|
||||
disassembly.operators = instr.op_str;
|
||||
@@ -71,7 +71,7 @@ namespace hex::plugin::builtin {
|
||||
disassembly.bytes += hex::format("{0:02X} ", instr.bytes[j]);
|
||||
disassembly.bytes.pop_back();
|
||||
|
||||
this->m_disassembly.push_back(disassembly);
|
||||
m_disassembly.push_back(disassembly);
|
||||
|
||||
usedBytes += instr.size;
|
||||
}
|
||||
@@ -96,18 +96,18 @@ namespace hex::plugin::builtin {
|
||||
ImGuiExt::Header("hex.builtin.view.disassembler.position"_lang, true);
|
||||
|
||||
// Draw base address input
|
||||
ImGuiExt::InputHexadecimal("hex.builtin.view.disassembler.base"_lang, &this->m_baseAddress, ImGuiInputTextFlags_CharsHexadecimal);
|
||||
ImGuiExt::InputHexadecimal("hex.builtin.view.disassembler.base"_lang, &m_baseAddress, ImGuiInputTextFlags_CharsHexadecimal);
|
||||
|
||||
// Draw region selection picker
|
||||
ui::regionSelectionPicker(&this->m_codeRegion, provider, &this->m_range);
|
||||
ui::regionSelectionPicker(&m_codeRegion, provider, &m_range);
|
||||
|
||||
// Draw settings
|
||||
{
|
||||
ImGuiExt::Header("hex.builtin.common.settings"_lang);
|
||||
|
||||
// Draw architecture selector
|
||||
if (ImGui::Combo("hex.builtin.view.disassembler.arch"_lang, reinterpret_cast<int *>(&this->m_architecture), Disassembler::ArchitectureNames.data(), Disassembler::getArchitectureSupportedCount()))
|
||||
this->m_mode = cs_mode(0);
|
||||
if (ImGui::Combo("hex.builtin.view.disassembler.arch"_lang, reinterpret_cast<int *>(&m_architecture), Disassembler::ArchitectureNames.data(), Disassembler::getArchitectureSupportedCount()))
|
||||
m_mode = cs_mode(0);
|
||||
|
||||
// Draw sub-settings for each architecture
|
||||
if (ImGuiExt::BeginBox()) {
|
||||
@@ -121,7 +121,7 @@ namespace hex::plugin::builtin {
|
||||
ImGui::NewLine();
|
||||
|
||||
// Draw architecture specific settings
|
||||
switch (this->m_architecture) {
|
||||
switch (m_architecture) {
|
||||
case Architecture::ARM:
|
||||
{
|
||||
static int mode = CS_MODE_ARM;
|
||||
@@ -136,7 +136,7 @@ namespace hex::plugin::builtin {
|
||||
ImGui::SameLine();
|
||||
ImGui::RadioButton("hex.builtin.view.disassembler.arm.armv8"_lang, &extraMode, CS_MODE_V8);
|
||||
|
||||
this->m_mode = cs_mode(mode | extraMode);
|
||||
m_mode = cs_mode(mode | extraMode);
|
||||
}
|
||||
break;
|
||||
case Architecture::MIPS:
|
||||
@@ -155,7 +155,7 @@ namespace hex::plugin::builtin {
|
||||
static bool microMode;
|
||||
ImGui::Checkbox("hex.builtin.view.disassembler.mips.micro"_lang, µMode);
|
||||
|
||||
this->m_mode = cs_mode(mode | (microMode ? CS_MODE_MICRO : cs_mode(0)));
|
||||
m_mode = cs_mode(mode | (microMode ? CS_MODE_MICRO : cs_mode(0)));
|
||||
}
|
||||
break;
|
||||
case Architecture::X86:
|
||||
@@ -167,7 +167,7 @@ namespace hex::plugin::builtin {
|
||||
ImGui::SameLine();
|
||||
ImGui::RadioButton("hex.builtin.view.disassembler.64bit"_lang, &mode, CS_MODE_64);
|
||||
|
||||
this->m_mode = cs_mode(mode);
|
||||
m_mode = cs_mode(mode);
|
||||
}
|
||||
break;
|
||||
case Architecture::PPC:
|
||||
@@ -186,9 +186,9 @@ namespace hex::plugin::builtin {
|
||||
static bool booke = false;
|
||||
ImGui::Checkbox("hex.builtin.view.disassembler.ppc.booke"_lang, &booke);
|
||||
|
||||
this->m_mode = cs_mode(mode | (qpx ? CS_MODE_QPX : cs_mode(0)) | (spe ? CS_MODE_SPE : cs_mode(0)) | (booke ? CS_MODE_BOOKE : cs_mode(0)));
|
||||
m_mode = cs_mode(mode | (qpx ? CS_MODE_QPX : cs_mode(0)) | (spe ? CS_MODE_SPE : cs_mode(0)) | (booke ? CS_MODE_BOOKE : cs_mode(0)));
|
||||
#else
|
||||
this->m_mode = cs_mode(mode | (qpx ? CS_MODE_QPX : cs_mode(0)));
|
||||
m_mode = cs_mode(mode | (qpx ? CS_MODE_QPX : cs_mode(0)));
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
@@ -197,7 +197,7 @@ namespace hex::plugin::builtin {
|
||||
static bool v9Mode = false;
|
||||
ImGui::Checkbox("hex.builtin.view.disassembler.sparc.v9"_lang, &v9Mode);
|
||||
|
||||
this->m_mode = cs_mode(v9Mode ? CS_MODE_V9 : cs_mode(0));
|
||||
m_mode = cs_mode(v9Mode ? CS_MODE_V9 : cs_mode(0));
|
||||
}
|
||||
break;
|
||||
#if CS_API_MAJOR >= 5
|
||||
@@ -211,7 +211,7 @@ namespace hex::plugin::builtin {
|
||||
static bool compressed = false;
|
||||
ImGui::Checkbox("hex.builtin.view.disassembler.riscv.compressed"_lang, &compressed);
|
||||
|
||||
this->m_mode = cs_mode(mode | (compressed ? CS_MODE_RISCVC : cs_mode(0)));
|
||||
m_mode = cs_mode(mode | (compressed ? CS_MODE_RISCVC : cs_mode(0)));
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
@@ -236,7 +236,7 @@ namespace hex::plugin::builtin {
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
|
||||
this->m_mode = cs_mode(modes[selectedMode].second);
|
||||
m_mode = cs_mode(modes[selectedMode].second);
|
||||
}
|
||||
break;
|
||||
case Architecture::M680X:
|
||||
@@ -264,7 +264,7 @@ namespace hex::plugin::builtin {
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
|
||||
this->m_mode = cs_mode(modes[selectedMode].second);
|
||||
m_mode = cs_mode(modes[selectedMode].second);
|
||||
}
|
||||
break;
|
||||
#if CS_API_MAJOR >= 5
|
||||
@@ -290,7 +290,7 @@ namespace hex::plugin::builtin {
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
|
||||
this->m_mode = cs_mode(modes[selectedMode].second);
|
||||
m_mode = cs_mode(modes[selectedMode].second);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
@@ -302,7 +302,7 @@ namespace hex::plugin::builtin {
|
||||
ImGui::SameLine();
|
||||
ImGui::RadioButton("hex.builtin.view.disassembler.bpf.extended"_lang, &mode, CS_MODE_BPF_EXTENDED);
|
||||
|
||||
this->m_mode = cs_mode(mode);
|
||||
m_mode = cs_mode(mode);
|
||||
}
|
||||
break;
|
||||
case Architecture::SH:
|
||||
@@ -331,7 +331,7 @@ namespace hex::plugin::builtin {
|
||||
ImGui::SameLine();
|
||||
ImGui::Checkbox("hex.builtin.view.disassembler.sh.dsp"_lang, &dsp);
|
||||
|
||||
this->m_mode = cs_mode(modes[selectionMode].second | (fpu ? CS_MODE_SHFPU : cs_mode(0)) | (dsp ? CS_MODE_SHDSP : cs_mode(0)));
|
||||
m_mode = cs_mode(modes[selectionMode].second | (fpu ? CS_MODE_SHFPU : cs_mode(0)) | (dsp ? CS_MODE_SHDSP : cs_mode(0)));
|
||||
}
|
||||
break;
|
||||
case Architecture::TRICORE:
|
||||
@@ -356,7 +356,7 @@ namespace hex::plugin::builtin {
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
|
||||
this->m_mode = cs_mode(modes[selectionMode].second);
|
||||
m_mode = cs_mode(modes[selectionMode].second);
|
||||
}
|
||||
break;
|
||||
case Architecture::WASM:
|
||||
@@ -366,7 +366,7 @@ namespace hex::plugin::builtin {
|
||||
case Architecture::ARM64:
|
||||
case Architecture::SYSZ:
|
||||
case Architecture::XCORE:
|
||||
this->m_mode = cs_mode(0);
|
||||
m_mode = cs_mode(0);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -375,7 +375,7 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
// Draw disassemble button
|
||||
ImGui::BeginDisabled(this->m_disassemblerTask.isRunning());
|
||||
ImGui::BeginDisabled(m_disassemblerTask.isRunning());
|
||||
{
|
||||
if (ImGui::Button("hex.builtin.view.disassembler.disassemble"_lang))
|
||||
this->disassemble();
|
||||
@@ -383,7 +383,7 @@ namespace hex::plugin::builtin {
|
||||
ImGui::EndDisabled();
|
||||
|
||||
// Draw a spinner if the disassembler is running
|
||||
if (this->m_disassemblerTask.isRunning()) {
|
||||
if (m_disassemblerTask.isRunning()) {
|
||||
ImGui::SameLine();
|
||||
ImGuiExt::TextSpinner("hex.builtin.view.disassembler.disassembling"_lang);
|
||||
}
|
||||
@@ -401,14 +401,14 @@ namespace hex::plugin::builtin {
|
||||
ImGui::TableSetupColumn("hex.builtin.view.disassembler.disassembly.bytes"_lang);
|
||||
ImGui::TableSetupColumn("hex.builtin.view.disassembler.disassembly.title"_lang);
|
||||
|
||||
if (!this->m_disassemblerTask.isRunning()) {
|
||||
if (!m_disassemblerTask.isRunning()) {
|
||||
ImGuiListClipper clipper;
|
||||
clipper.Begin(this->m_disassembly.size());
|
||||
clipper.Begin(m_disassembly.size());
|
||||
|
||||
ImGui::TableHeadersRow();
|
||||
while (clipper.Step()) {
|
||||
for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) {
|
||||
const auto &instruction = this->m_disassembly[i];
|
||||
const auto &instruction = m_disassembly[i];
|
||||
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
@@ -20,10 +20,10 @@ namespace hex::plugin::builtin {
|
||||
ImHexApi::HexEditor::addBackgroundHighlightingProvider([this](u64 address, const u8* data, size_t size, bool) -> std::optional<color_t> {
|
||||
hex::unused(data, size);
|
||||
|
||||
if (this->m_searchTask.isRunning())
|
||||
if (m_searchTask.isRunning())
|
||||
return { };
|
||||
|
||||
if (!this->m_occurrenceTree->overlapping({ address, address + size }).empty())
|
||||
if (!m_occurrenceTree->overlapping({ address, address + size }).empty())
|
||||
return HighlightColor();
|
||||
else
|
||||
return std::nullopt;
|
||||
@@ -32,10 +32,10 @@ namespace hex::plugin::builtin {
|
||||
ImHexApi::HexEditor::addTooltipProvider([this](u64 address, const u8* data, size_t size) {
|
||||
hex::unused(data, size);
|
||||
|
||||
if (this->m_searchTask.isRunning())
|
||||
if (m_searchTask.isRunning())
|
||||
return;
|
||||
|
||||
auto occurrences = this->m_occurrenceTree->overlapping({ address, address + size });
|
||||
auto occurrences = m_occurrenceTree->overlapping({ address, address + size });
|
||||
if (occurrences.empty())
|
||||
return;
|
||||
|
||||
@@ -94,12 +94,12 @@ namespace hex::plugin::builtin {
|
||||
});
|
||||
|
||||
ShortcutManager::addShortcut(this, CTRLCMD + Keys::A, "hex.builtin.view.find.shortcut.select_all", [this] {
|
||||
if (this->m_filterTask.isRunning())
|
||||
if (m_filterTask.isRunning())
|
||||
return;
|
||||
if (this->m_searchTask.isRunning())
|
||||
if (m_searchTask.isRunning())
|
||||
return;
|
||||
|
||||
for (auto &occurrence : *this->m_sortedOccurrences)
|
||||
for (auto &occurrence : *m_sortedOccurrences)
|
||||
occurrence.selected = true;
|
||||
});
|
||||
}
|
||||
@@ -440,46 +440,46 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
void ViewFind::runSearch() {
|
||||
Region searchRegion = this->m_searchSettings.region;
|
||||
Region searchRegion = m_searchSettings.region;
|
||||
|
||||
if (this->m_searchSettings.mode == SearchSettings::Mode::Strings)
|
||||
if (m_searchSettings.mode == SearchSettings::Mode::Strings)
|
||||
AchievementManager::unlockAchievement("hex.builtin.achievement.find", "hex.builtin.achievement.find.find_strings.name");
|
||||
else if (this->m_searchSettings.mode == SearchSettings::Mode::Sequence)
|
||||
else if (m_searchSettings.mode == SearchSettings::Mode::Sequence)
|
||||
AchievementManager::unlockAchievement("hex.builtin.achievement.find", "hex.builtin.achievement.find.find_specific_string.name");
|
||||
else if (this->m_searchSettings.mode == SearchSettings::Mode::Value) {
|
||||
if (this->m_searchSettings.value.inputMin == "250" && this->m_searchSettings.value.inputMax == "1000")
|
||||
else if (m_searchSettings.mode == SearchSettings::Mode::Value) {
|
||||
if (m_searchSettings.value.inputMin == "250" && m_searchSettings.value.inputMax == "1000")
|
||||
AchievementManager::unlockAchievement("hex.builtin.achievement.find", "hex.builtin.achievement.find.find_numeric.name");
|
||||
}
|
||||
|
||||
this->m_occurrenceTree->clear();
|
||||
m_occurrenceTree->clear();
|
||||
EventHighlightingChanged::post();
|
||||
|
||||
this->m_searchTask = TaskManager::createTask("hex.builtin.view.find.searching", searchRegion.getSize(), [this, settings = this->m_searchSettings, searchRegion](auto &task) {
|
||||
m_searchTask = TaskManager::createTask("hex.builtin.view.find.searching", searchRegion.getSize(), [this, settings = m_searchSettings, searchRegion](auto &task) {
|
||||
auto provider = ImHexApi::Provider::get();
|
||||
|
||||
switch (settings.mode) {
|
||||
using enum SearchSettings::Mode;
|
||||
case Strings:
|
||||
this->m_foundOccurrences.get(provider) = searchStrings(task, provider, searchRegion, settings.strings);
|
||||
m_foundOccurrences.get(provider) = searchStrings(task, provider, searchRegion, settings.strings);
|
||||
break;
|
||||
case Sequence:
|
||||
this->m_foundOccurrences.get(provider) = searchSequence(task, provider, searchRegion, settings.bytes);
|
||||
m_foundOccurrences.get(provider) = searchSequence(task, provider, searchRegion, settings.bytes);
|
||||
break;
|
||||
case Regex:
|
||||
this->m_foundOccurrences.get(provider) = searchRegex(task, provider, searchRegion, settings.regex);
|
||||
m_foundOccurrences.get(provider) = searchRegex(task, provider, searchRegion, settings.regex);
|
||||
break;
|
||||
case BinaryPattern:
|
||||
this->m_foundOccurrences.get(provider) = searchBinaryPattern(task, provider, searchRegion, settings.binaryPattern);
|
||||
m_foundOccurrences.get(provider) = searchBinaryPattern(task, provider, searchRegion, settings.binaryPattern);
|
||||
break;
|
||||
case Value:
|
||||
this->m_foundOccurrences.get(provider) = searchValue(task, provider, searchRegion, settings.value);
|
||||
m_foundOccurrences.get(provider) = searchValue(task, provider, searchRegion, settings.value);
|
||||
break;
|
||||
}
|
||||
|
||||
this->m_sortedOccurrences.get(provider) = this->m_foundOccurrences.get(provider);
|
||||
m_sortedOccurrences.get(provider) = m_foundOccurrences.get(provider);
|
||||
|
||||
for (const auto &occurrence : this->m_foundOccurrences.get(provider))
|
||||
this->m_occurrenceTree->insert({ occurrence.region.getStartAddress(), occurrence.region.getEndAddress() }, occurrence);
|
||||
for (const auto &occurrence : m_foundOccurrences.get(provider))
|
||||
m_occurrenceTree->insert({ occurrence.region.getStartAddress(), occurrence.region.getEndAddress() }, occurrence);
|
||||
|
||||
TaskManager::doLater([] {
|
||||
EventHighlightingChanged::post();
|
||||
@@ -492,7 +492,7 @@ namespace hex::plugin::builtin {
|
||||
provider->read(occurrence.region.getStartAddress(), bytes.data(), bytes.size());
|
||||
|
||||
std::string result;
|
||||
switch (this->m_decodeSettings.mode) {
|
||||
switch (m_decodeSettings.mode) {
|
||||
using enum SearchSettings::Mode;
|
||||
|
||||
case Value:
|
||||
@@ -540,7 +540,7 @@ namespace hex::plugin::builtin {
|
||||
if (ImGui::IsMouseClicked(ImGuiMouseButton_Right) && ImGui::IsItemHovered()) {
|
||||
ImGui::OpenPopup("FindContextMenu");
|
||||
target.selected = true;
|
||||
this->m_replaceBuffer.clear();
|
||||
m_replaceBuffer.clear();
|
||||
}
|
||||
|
||||
if (ImGui::BeginPopup("FindContextMenu")) {
|
||||
@@ -551,14 +551,14 @@ namespace hex::plugin::builtin {
|
||||
if (ImGui::BeginMenu("hex.builtin.view.find.context.replace"_lang)) {
|
||||
if (ImGui::BeginTabBar("##replace_tabs")) {
|
||||
if (ImGui::BeginTabItem("hex.builtin.view.find.context.replace.hex"_lang)) {
|
||||
ImGuiExt::InputTextIcon("##replace_input", ICON_VS_SYMBOL_NAMESPACE, this->m_replaceBuffer);
|
||||
ImGuiExt::InputTextIcon("##replace_input", ICON_VS_SYMBOL_NAMESPACE, m_replaceBuffer);
|
||||
|
||||
ImGui::BeginDisabled(this->m_replaceBuffer.empty());
|
||||
ImGui::BeginDisabled(m_replaceBuffer.empty());
|
||||
if (ImGui::Button("hex.builtin.view.find.context.replace"_lang)) {
|
||||
auto provider = ImHexApi::Provider::get();
|
||||
auto bytes = parseHexString(this->m_replaceBuffer);
|
||||
auto bytes = parseHexString(m_replaceBuffer);
|
||||
|
||||
for (const auto &occurrence : *this->m_sortedOccurrences) {
|
||||
for (const auto &occurrence : *m_sortedOccurrences) {
|
||||
if (occurrence.selected) {
|
||||
size_t size = std::min<size_t>(occurrence.region.size, bytes.size());
|
||||
provider->write(occurrence.region.getStartAddress(), bytes.data(), size);
|
||||
@@ -571,14 +571,14 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
if (ImGui::BeginTabItem("hex.builtin.view.find.context.replace.ascii"_lang)) {
|
||||
ImGuiExt::InputTextIcon("##replace_input", ICON_VS_SYMBOL_KEY, this->m_replaceBuffer);
|
||||
ImGuiExt::InputTextIcon("##replace_input", ICON_VS_SYMBOL_KEY, m_replaceBuffer);
|
||||
|
||||
ImGui::BeginDisabled(this->m_replaceBuffer.empty());
|
||||
ImGui::BeginDisabled(m_replaceBuffer.empty());
|
||||
if (ImGui::Button("hex.builtin.view.find.context.replace"_lang)) {
|
||||
auto provider = ImHexApi::Provider::get();
|
||||
auto bytes = decodeByteString(this->m_replaceBuffer);
|
||||
auto bytes = decodeByteString(m_replaceBuffer);
|
||||
|
||||
for (const auto &occurrence : *this->m_sortedOccurrences) {
|
||||
for (const auto &occurrence : *m_sortedOccurrences) {
|
||||
if (occurrence.selected) {
|
||||
size_t size = std::min<size_t>(occurrence.region.size, bytes.size());
|
||||
provider->write(occurrence.region.getStartAddress(), bytes.data(), size);
|
||||
@@ -603,9 +603,9 @@ namespace hex::plugin::builtin {
|
||||
void ViewFind::drawContent() {
|
||||
auto provider = ImHexApi::Provider::get();
|
||||
|
||||
ImGui::BeginDisabled(this->m_searchTask.isRunning());
|
||||
ImGui::BeginDisabled(m_searchTask.isRunning());
|
||||
{
|
||||
ui::regionSelectionPicker(&this->m_searchSettings.region, provider, &this->m_searchSettings.range, true, true);
|
||||
ui::regionSelectionPicker(&m_searchSettings.region, provider, &m_searchSettings.range, true, true);
|
||||
|
||||
ImGui::NewLine();
|
||||
|
||||
@@ -618,9 +618,9 @@ namespace hex::plugin::builtin {
|
||||
hex::format("{} + {}", "hex.builtin.common.encoding.ascii"_lang, "hex.builtin.common.encoding.utf16be"_lang)
|
||||
};
|
||||
|
||||
auto &mode = this->m_searchSettings.mode;
|
||||
auto &mode = m_searchSettings.mode;
|
||||
if (ImGui::BeginTabItem("hex.builtin.view.find.strings"_lang)) {
|
||||
auto &settings = this->m_searchSettings.strings;
|
||||
auto &settings = m_searchSettings.strings;
|
||||
mode = SearchSettings::Mode::Strings;
|
||||
|
||||
ImGui::InputInt("hex.builtin.view.find.strings.min_length"_lang, &settings.minLength, 1, 1);
|
||||
@@ -650,23 +650,23 @@ namespace hex::plugin::builtin {
|
||||
ImGui::Checkbox(hex::format("{} [\\r\\n]", "hex.builtin.view.find.strings.line_feeds"_lang.get()).c_str(), &settings.lineFeeds);
|
||||
}
|
||||
|
||||
this->m_settingsValid = true;
|
||||
m_settingsValid = true;
|
||||
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
if (ImGui::BeginTabItem("hex.builtin.view.find.sequences"_lang)) {
|
||||
auto &settings = this->m_searchSettings.bytes;
|
||||
auto &settings = m_searchSettings.bytes;
|
||||
|
||||
mode = SearchSettings::Mode::Sequence;
|
||||
|
||||
ImGuiExt::InputTextIcon("hex.builtin.common.value"_lang, ICON_VS_SYMBOL_KEY, settings.sequence);
|
||||
|
||||
this->m_settingsValid = !settings.sequence.empty() && !hex::decodeByteString(settings.sequence).empty();
|
||||
m_settingsValid = !settings.sequence.empty() && !hex::decodeByteString(settings.sequence).empty();
|
||||
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
if (ImGui::BeginTabItem("hex.builtin.view.find.regex"_lang)) {
|
||||
auto &settings = this->m_searchSettings.regex;
|
||||
auto &settings = m_searchSettings.regex;
|
||||
|
||||
mode = SearchSettings::Mode::Regex;
|
||||
|
||||
@@ -692,20 +692,20 @@ namespace hex::plugin::builtin {
|
||||
|
||||
try {
|
||||
std::regex regex(settings.pattern);
|
||||
this->m_settingsValid = true;
|
||||
m_settingsValid = true;
|
||||
} catch (const std::regex_error &) {
|
||||
this->m_settingsValid = false;
|
||||
m_settingsValid = false;
|
||||
}
|
||||
|
||||
if (settings.pattern.empty())
|
||||
this->m_settingsValid = false;
|
||||
m_settingsValid = false;
|
||||
|
||||
ImGui::Checkbox("hex.builtin.view.find.regex.full_match"_lang, &settings.fullMatch);
|
||||
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
if (ImGui::BeginTabItem("hex.builtin.view.find.binary_pattern"_lang)) {
|
||||
auto &settings = this->m_searchSettings.binaryPattern;
|
||||
auto &settings = m_searchSettings.binaryPattern;
|
||||
|
||||
mode = SearchSettings::Mode::BinaryPattern;
|
||||
|
||||
@@ -715,12 +715,12 @@ namespace hex::plugin::builtin {
|
||||
ImGui::SliderScalar("hex.builtin.view.find.binary_pattern.alignment"_lang, ImGuiDataType_U32, &settings.alignment, &min, &max);
|
||||
|
||||
settings.pattern = hex::BinaryPattern(settings.input);
|
||||
this->m_settingsValid = settings.pattern.isValid() && settings.alignment > 0;
|
||||
m_settingsValid = settings.pattern.isValid() && settings.alignment > 0;
|
||||
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
if (ImGui::BeginTabItem("hex.builtin.view.find.value"_lang)) {
|
||||
auto &settings = this->m_searchSettings.value;
|
||||
auto &settings = m_searchSettings.value;
|
||||
|
||||
mode = SearchSettings::Mode::Value;
|
||||
|
||||
@@ -796,11 +796,11 @@ namespace hex::plugin::builtin {
|
||||
auto [minValid, min, minSize] = parseNumericValueInput(settings.inputMin, settings.type);
|
||||
auto [maxValid, max, maxSize] = parseNumericValueInput(settings.inputMax, settings.type);
|
||||
|
||||
this->m_settingsValid = minValid && maxValid && minSize == maxSize;
|
||||
m_settingsValid = minValid && maxValid && minSize == maxSize;
|
||||
}
|
||||
|
||||
if (settings.inputMin.empty())
|
||||
this->m_settingsValid = false;
|
||||
m_settingsValid = false;
|
||||
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
@@ -810,25 +810,25 @@ namespace hex::plugin::builtin {
|
||||
|
||||
ImGui::NewLine();
|
||||
|
||||
ImGui::BeginDisabled(!this->m_settingsValid);
|
||||
ImGui::BeginDisabled(!m_settingsValid);
|
||||
{
|
||||
if (ImGui::Button("hex.builtin.view.find.search"_lang)) {
|
||||
this->runSearch();
|
||||
|
||||
this->m_decodeSettings = this->m_searchSettings;
|
||||
m_decodeSettings = m_searchSettings;
|
||||
}
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
|
||||
ImGui::SameLine();
|
||||
ImGuiExt::TextFormatted("hex.builtin.view.find.search.entries"_lang, this->m_foundOccurrences->size());
|
||||
ImGuiExt::TextFormatted("hex.builtin.view.find.search.entries"_lang, m_foundOccurrences->size());
|
||||
|
||||
ImGui::BeginDisabled(this->m_foundOccurrences->empty());
|
||||
ImGui::BeginDisabled(m_foundOccurrences->empty());
|
||||
{
|
||||
if (ImGui::Button("hex.builtin.view.find.search.reset"_lang)) {
|
||||
this->m_foundOccurrences->clear();
|
||||
this->m_sortedOccurrences->clear();
|
||||
this->m_occurrenceTree->clear();
|
||||
m_foundOccurrences->clear();
|
||||
m_sortedOccurrences->clear();
|
||||
m_occurrenceTree->clear();
|
||||
|
||||
EventHighlightingChanged::post();
|
||||
}
|
||||
@@ -841,25 +841,25 @@ namespace hex::plugin::builtin {
|
||||
ImGui::Separator();
|
||||
ImGui::NewLine();
|
||||
|
||||
auto &currOccurrences = *this->m_sortedOccurrences;
|
||||
auto &currOccurrences = *m_sortedOccurrences;
|
||||
|
||||
ImGui::PushItemWidth(-1);
|
||||
auto prevFilterLength = this->m_currFilter->length();
|
||||
if (ImGuiExt::InputTextIcon("##filter", ICON_VS_FILTER, *this->m_currFilter)) {
|
||||
if (prevFilterLength > this->m_currFilter->length())
|
||||
*this->m_sortedOccurrences = *this->m_foundOccurrences;
|
||||
auto prevFilterLength = m_currFilter->length();
|
||||
if (ImGuiExt::InputTextIcon("##filter", ICON_VS_FILTER, *m_currFilter)) {
|
||||
if (prevFilterLength > m_currFilter->length())
|
||||
*m_sortedOccurrences = *m_foundOccurrences;
|
||||
|
||||
if (this->m_filterTask.isRunning())
|
||||
this->m_filterTask.interrupt();
|
||||
if (m_filterTask.isRunning())
|
||||
m_filterTask.interrupt();
|
||||
|
||||
if (!this->m_currFilter->empty()) {
|
||||
this->m_filterTask = TaskManager::createTask("Filtering", currOccurrences.size(), [this, provider, &currOccurrences](Task &task) {
|
||||
if (!m_currFilter->empty()) {
|
||||
m_filterTask = TaskManager::createTask("Filtering", currOccurrences.size(), [this, provider, &currOccurrences](Task &task) {
|
||||
u64 progress = 0;
|
||||
std::erase_if(currOccurrences, [this, provider, &task, &progress](const auto ®ion) {
|
||||
task.update(progress);
|
||||
progress += 1;
|
||||
|
||||
return !hex::containsIgnoreCase(this->decodeValue(provider, region), this->m_currFilter.get(provider));
|
||||
return !hex::containsIgnoreCase(this->decodeValue(provider, region), m_currFilter.get(provider));
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -925,7 +925,7 @@ namespace hex::plugin::builtin {
|
||||
if (ImGui::GetIO().KeyCtrl) {
|
||||
foundItem.selected = !foundItem.selected;
|
||||
} else {
|
||||
for (auto &occurrence : *this->m_sortedOccurrences)
|
||||
for (auto &occurrence : *m_sortedOccurrences)
|
||||
occurrence.selected = false;
|
||||
foundItem.selected = true;
|
||||
ImHexApi::HexEditor::setSelection(foundItem.region.getStartAddress(), foundItem.region.getSize());
|
||||
|
||||
@@ -22,19 +22,19 @@ namespace hex::plugin::builtin {
|
||||
ImGuiExt::Header(this->getUnlocalizedName(), true);
|
||||
|
||||
ImGui::PushItemWidth(-1);
|
||||
if (ImGui::InputTextMultiline("##input", this->m_input)) {
|
||||
if (ImGui::InputTextMultiline("##input", m_input)) {
|
||||
auto provider = std::make_unique<MemoryFileProvider>();
|
||||
provider->resize(this->m_input.size());
|
||||
provider->writeRaw(0x00, this->m_input.data(), this->m_input.size());
|
||||
provider->resize(m_input.size());
|
||||
provider->writeRaw(0x00, m_input.data(), m_input.size());
|
||||
|
||||
this->m_hash.reset();
|
||||
auto bytes = this->m_hash.get(Region { 0x00, provider->getActualSize() }, provider.get());
|
||||
m_hash.reset();
|
||||
auto bytes = m_hash.get(Region { 0x00, provider->getActualSize() }, provider.get());
|
||||
|
||||
this->m_result = crypt::encode16(bytes);
|
||||
m_result = crypt::encode16(bytes);
|
||||
}
|
||||
|
||||
ImGui::NewLine();
|
||||
ImGui::InputText("##result", this->m_result, ImGuiInputTextFlags_ReadOnly);
|
||||
ImGui::InputText("##result", m_result, ImGuiInputTextFlags_ReadOnly);
|
||||
ImGui::PopItemWidth();
|
||||
|
||||
if (ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Escape)))
|
||||
@@ -59,7 +59,7 @@ namespace hex::plugin::builtin {
|
||||
|
||||
ViewHashes::ViewHashes() : View::Window("hex.builtin.view.hashes.name") {
|
||||
EventRegionSelected::subscribe(this, [this](const auto &providerRegion) {
|
||||
for (auto &function : this->m_hashFunctions.get(providerRegion.getProvider()))
|
||||
for (auto &function : m_hashFunctions.get(providerRegion.getProvider()))
|
||||
function.reset();
|
||||
});
|
||||
|
||||
@@ -69,7 +69,7 @@ namespace hex::plugin::builtin {
|
||||
auto selection = ImHexApi::HexEditor::getSelection();
|
||||
|
||||
if (selection.has_value() && ImGui::GetIO().KeyShift) {
|
||||
auto &hashFunctions = this->m_hashFunctions.get(selection->getProvider());
|
||||
auto &hashFunctions = m_hashFunctions.get(selection->getProvider());
|
||||
if (!hashFunctions.empty() && selection.has_value() && selection->overlaps(Region { address, size })) {
|
||||
ImGui::BeginTooltip();
|
||||
|
||||
@@ -117,7 +117,7 @@ namespace hex::plugin::builtin {
|
||||
return true;
|
||||
|
||||
auto data = nlohmann::json::parse(fileContent.begin(), fileContent.end());
|
||||
this->m_hashFunctions->clear();
|
||||
m_hashFunctions->clear();
|
||||
|
||||
return this->importHashes(provider, data);
|
||||
},
|
||||
@@ -140,29 +140,29 @@ namespace hex::plugin::builtin {
|
||||
void ViewHashes::drawContent() {
|
||||
const auto &hashes = ContentRegistry::Hashes::impl::getHashes();
|
||||
|
||||
if (this->m_selectedHash == nullptr && !hashes.empty()) {
|
||||
this->m_selectedHash = hashes.front().get();
|
||||
if (m_selectedHash == nullptr && !hashes.empty()) {
|
||||
m_selectedHash = hashes.front().get();
|
||||
}
|
||||
|
||||
if (ImGui::BeginCombo("hex.builtin.view.hashes.function"_lang, this->m_selectedHash != nullptr ? Lang(this->m_selectedHash->getUnlocalizedName()) : "")) {
|
||||
if (ImGui::BeginCombo("hex.builtin.view.hashes.function"_lang, m_selectedHash != nullptr ? Lang(m_selectedHash->getUnlocalizedName()) : "")) {
|
||||
|
||||
for (const auto &hash : hashes) {
|
||||
if (ImGui::Selectable(Lang(hash->getUnlocalizedName()), this->m_selectedHash == hash.get())) {
|
||||
this->m_selectedHash = hash.get();
|
||||
this->m_newHashName.clear();
|
||||
if (ImGui::Selectable(Lang(hash->getUnlocalizedName()), m_selectedHash == hash.get())) {
|
||||
m_selectedHash = hash.get();
|
||||
m_newHashName.clear();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
|
||||
if (this->m_newHashName.empty() && this->m_selectedHash != nullptr)
|
||||
this->m_newHashName = hex::format("{} {}", Lang(this->m_selectedHash->getUnlocalizedName()), static_cast<const char *>("hex.builtin.view.hashes.hash"_lang));
|
||||
if (m_newHashName.empty() && m_selectedHash != nullptr)
|
||||
m_newHashName = hex::format("{} {}", Lang(m_selectedHash->getUnlocalizedName()), static_cast<const char *>("hex.builtin.view.hashes.hash"_lang));
|
||||
|
||||
if (ImGui::BeginChild("##settings", ImVec2(ImGui::GetContentRegionAvail().x, 200_scaled), true)) {
|
||||
if (this->m_selectedHash != nullptr) {
|
||||
if (m_selectedHash != nullptr) {
|
||||
auto startPos = ImGui::GetCursorPosY();
|
||||
this->m_selectedHash->draw();
|
||||
m_selectedHash->draw();
|
||||
|
||||
// Check if no elements have been added
|
||||
if (startPos == ImGui::GetCursorPosY()) {
|
||||
@@ -173,13 +173,13 @@ namespace hex::plugin::builtin {
|
||||
ImGui::EndChild();
|
||||
|
||||
|
||||
ImGuiExt::InputTextIcon("##hash_name", ICON_VS_SYMBOL_KEY, this->m_newHashName);
|
||||
ImGuiExt::InputTextIcon("##hash_name", ICON_VS_SYMBOL_KEY, m_newHashName);
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::BeginDisabled(this->m_newHashName.empty() || this->m_selectedHash == nullptr);
|
||||
ImGui::BeginDisabled(m_newHashName.empty() || m_selectedHash == nullptr);
|
||||
if (ImGuiExt::IconButton(ICON_VS_ADD, ImGui::GetStyleColorVec4(ImGuiCol_Text))) {
|
||||
if (this->m_selectedHash != nullptr) {
|
||||
this->m_hashFunctions->push_back(this->m_selectedHash->create(this->m_newHashName));
|
||||
if (m_selectedHash != nullptr) {
|
||||
m_hashFunctions->push_back(m_selectedHash->create(m_newHashName));
|
||||
AchievementManager::unlockAchievement("hex.builtin.achievement.misc", "hex.builtin.achievement.misc.create_hash.name");
|
||||
}
|
||||
}
|
||||
@@ -200,8 +200,8 @@ namespace hex::plugin::builtin {
|
||||
auto selection = ImHexApi::HexEditor::getSelection();
|
||||
|
||||
std::optional<u32> indexToRemove;
|
||||
for (u32 i = 0; i < this->m_hashFunctions->size(); i++) {
|
||||
auto &function = (*this->m_hashFunctions)[i];
|
||||
for (u32 i = 0; i < m_hashFunctions->size(); i++) {
|
||||
auto &function = (*m_hashFunctions)[i];
|
||||
|
||||
ImGui::PushID(i);
|
||||
|
||||
@@ -242,7 +242,7 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
if (indexToRemove.has_value()) {
|
||||
this->m_hashFunctions->erase(this->m_hashFunctions->begin() + indexToRemove.value());
|
||||
m_hashFunctions->erase(m_hashFunctions->begin() + indexToRemove.value());
|
||||
}
|
||||
|
||||
ImGui::EndTable();
|
||||
@@ -265,7 +265,7 @@ namespace hex::plugin::builtin {
|
||||
auto newFunction = newHash->create(hash["name"]);
|
||||
newFunction.getType()->load(hash["settings"]);
|
||||
|
||||
this->m_hashFunctions.get(provider).push_back(std::move(newFunction));
|
||||
m_hashFunctions.get(provider).push_back(std::move(newFunction));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -277,7 +277,7 @@ namespace hex::plugin::builtin {
|
||||
bool ViewHashes::exportHashes(prv::Provider *provider, nlohmann::json &json) {
|
||||
json["hashes"] = nlohmann::json::array();
|
||||
size_t index = 0;
|
||||
for (const auto &hashFunction : this->m_hashFunctions.get(provider)) {
|
||||
for (const auto &hashFunction : m_hashFunctions.get(provider)) {
|
||||
json["hashes"][index] = {
|
||||
{ "name", hashFunction.getName() },
|
||||
{ "type", hashFunction.getType()->getUnlocalizedName() },
|
||||
|
||||
@@ -30,39 +30,39 @@ namespace hex::plugin::builtin {
|
||||
ImGui::TextUnformatted("hex.builtin.view.hex_editor.menu.file.goto"_lang);
|
||||
if (ImGui::BeginTabBar("goto_tabs")) {
|
||||
if (ImGui::BeginTabItem("hex.builtin.view.hex_editor.goto.offset.absolute"_lang)) {
|
||||
this->m_mode = Mode::Absolute;
|
||||
m_mode = Mode::Absolute;
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
ImGui::BeginDisabled(!editor->isSelectionValid());
|
||||
if (ImGui::BeginTabItem("hex.builtin.view.hex_editor.goto.offset.relative"_lang)) {
|
||||
this->m_mode = Mode::Relative;
|
||||
m_mode = Mode::Relative;
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
|
||||
if (ImGui::BeginTabItem("hex.builtin.view.hex_editor.goto.offset.begin"_lang)) {
|
||||
this->m_mode = Mode::Begin;
|
||||
m_mode = Mode::Begin;
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
if (ImGui::BeginTabItem("hex.builtin.view.hex_editor.goto.offset.end"_lang)) {
|
||||
this->m_mode = Mode::End;
|
||||
m_mode = Mode::End;
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
if (this->m_requestFocus){
|
||||
if (m_requestFocus){
|
||||
ImGui::SetKeyboardFocusHere();
|
||||
this->m_requestFocus = false;
|
||||
m_requestFocus = false;
|
||||
}
|
||||
if (ImGuiExt::InputTextIcon("##input", ICON_VS_SYMBOL_OPERATOR, this->m_input, ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_AutoSelectAll)) {
|
||||
if (auto result = this->m_evaluator.evaluate(this->m_input); result.has_value()) {
|
||||
if (ImGuiExt::InputTextIcon("##input", ICON_VS_SYMBOL_OPERATOR, m_input, ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_AutoSelectAll)) {
|
||||
if (auto result = m_evaluator.evaluate(m_input); result.has_value()) {
|
||||
const auto inputResult = result.value();
|
||||
u64 newAddress = 0x00;
|
||||
|
||||
auto provider = ImHexApi::Provider::get();
|
||||
|
||||
switch (this->m_mode) {
|
||||
switch (m_mode) {
|
||||
case Mode::Absolute: {
|
||||
newAddress = inputResult;
|
||||
}
|
||||
@@ -115,34 +115,34 @@ namespace hex::plugin::builtin {
|
||||
ImGui::TextUnformatted("hex.builtin.view.hex_editor.menu.file.select"_lang);
|
||||
if (ImGui::BeginTabBar("select_tabs")) {
|
||||
if (ImGui::BeginTabItem("hex.builtin.view.hex_editor.select.offset.region"_lang)) {
|
||||
u64 inputA = this->m_region.getStartAddress();
|
||||
u64 inputB = this->m_region.getEndAddress();
|
||||
u64 inputA = m_region.getStartAddress();
|
||||
u64 inputB = m_region.getEndAddress();
|
||||
ImGuiExt::InputHexadecimal("hex.builtin.view.hex_editor.select.offset.begin"_lang, &inputA, ImGuiInputTextFlags_AutoSelectAll);
|
||||
ImGuiExt::InputHexadecimal("hex.builtin.view.hex_editor.select.offset.end"_lang, &inputB, ImGuiInputTextFlags_AutoSelectAll);
|
||||
|
||||
if (inputB < inputA)
|
||||
inputB = inputA;
|
||||
|
||||
this->m_region = { inputA, (inputB - inputA) + 1 };
|
||||
m_region = { inputA, (inputB - inputA) + 1 };
|
||||
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
if (ImGui::BeginTabItem("hex.builtin.view.hex_editor.select.offset.size"_lang)) {
|
||||
u64 inputA = this->m_region.getStartAddress();
|
||||
u64 inputB = this->m_region.getSize();
|
||||
u64 inputA = m_region.getStartAddress();
|
||||
u64 inputB = m_region.getSize();
|
||||
ImGuiExt::InputHexadecimal("hex.builtin.view.hex_editor.select.offset.begin"_lang, &inputA, ImGuiInputTextFlags_AutoSelectAll);
|
||||
ImGuiExt::InputHexadecimal("hex.builtin.view.hex_editor.select.offset.size"_lang, &inputB, ImGuiInputTextFlags_AutoSelectAll);
|
||||
|
||||
if (inputB <= 0)
|
||||
inputB = 1;
|
||||
|
||||
this->m_region = { inputA, inputB };
|
||||
m_region = { inputA, inputB };
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
if (ImGui::Button("hex.builtin.view.hex_editor.select.select"_lang) || (ImGui::IsItemFocused() && (ImGui::IsKeyPressed(ImGuiKey_Enter) || ImGui::IsKeyPressed(ImGuiKey_Enter)))) {
|
||||
editor->setSelection(this->m_region.getStartAddress(), this->m_region.getEndAddress());
|
||||
editor->setSelection(m_region.getStartAddress(), m_region.getEndAddress());
|
||||
editor->jumpToSelection();
|
||||
}
|
||||
|
||||
@@ -158,8 +158,8 @@ namespace hex::plugin::builtin {
|
||||
public:
|
||||
PopupFind() {
|
||||
EventRegionSelected::subscribe(this, [this](Region region) {
|
||||
this->m_searchPosition = this->m_nextSearchPosition.value_or(region.getStartAddress());
|
||||
this->m_nextSearchPosition.reset();
|
||||
m_searchPosition = m_nextSearchPosition.value_or(region.getStartAddress());
|
||||
m_nextSearchPosition.reset();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -173,35 +173,35 @@ namespace hex::plugin::builtin {
|
||||
ImGui::TextUnformatted("hex.builtin.view.hex_editor.menu.file.search"_lang);
|
||||
if (ImGui::BeginTabBar("##find_tabs")) {
|
||||
if (ImGui::BeginTabItem("hex.builtin.view.hex_editor.search.hex"_lang)) {
|
||||
if (ImGuiExt::InputTextIcon("##input", ICON_VS_SYMBOL_NUMERIC, this->m_input, ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_CharsHexadecimal)) {
|
||||
if (!this->m_input.empty()) {
|
||||
this->m_shouldSearch = true;
|
||||
this->m_backwards = false;
|
||||
if (ImGuiExt::InputTextIcon("##input", ICON_VS_SYMBOL_NUMERIC, m_input, ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_CharsHexadecimal)) {
|
||||
if (!m_input.empty()) {
|
||||
m_shouldSearch = true;
|
||||
m_backwards = false;
|
||||
}
|
||||
}
|
||||
|
||||
this->drawButtons();
|
||||
|
||||
if (this->m_shouldSearch) {
|
||||
searchSequence = crypt::decode16(this->m_input);
|
||||
if (m_shouldSearch) {
|
||||
searchSequence = crypt::decode16(m_input);
|
||||
}
|
||||
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
if (ImGui::BeginTabItem("hex.builtin.view.hex_editor.search.string"_lang)) {
|
||||
if (ImGuiExt::InputTextIcon("##input", ICON_VS_SYMBOL_KEY, this->m_input, ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_AutoSelectAll)) {
|
||||
if (!this->m_input.empty()) {
|
||||
this->m_shouldSearch = true;
|
||||
this->m_backwards = false;
|
||||
if (ImGuiExt::InputTextIcon("##input", ICON_VS_SYMBOL_KEY, m_input, ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_AutoSelectAll)) {
|
||||
if (!m_input.empty()) {
|
||||
m_shouldSearch = true;
|
||||
m_backwards = false;
|
||||
}
|
||||
}
|
||||
|
||||
this->drawButtons();
|
||||
|
||||
if (this->m_shouldSearch) {
|
||||
if (m_shouldSearch) {
|
||||
searchSequence.clear();
|
||||
std::copy(this->m_input.begin(), this->m_input.end(), std::back_inserter(searchSequence));
|
||||
std::copy(m_input.begin(), m_input.end(), std::back_inserter(searchSequence));
|
||||
|
||||
if (!searchSequence.empty() && searchSequence.back() == 0x00)
|
||||
searchSequence.pop_back();
|
||||
@@ -213,16 +213,16 @@ namespace hex::plugin::builtin {
|
||||
ImGui::EndTabBar();
|
||||
}
|
||||
|
||||
if (!this->m_searchTask.isRunning() && !searchSequence.empty() && this->m_shouldSearch) {
|
||||
this->m_searchTask = TaskManager::createTask("hex.builtin.common.processing", ImHexApi::Provider::get()->getActualSize(), [this, editor, searchSequence](auto &) {
|
||||
if (!m_searchTask.isRunning() && !searchSequence.empty() && m_shouldSearch) {
|
||||
m_searchTask = TaskManager::createTask("hex.builtin.common.processing", ImHexApi::Provider::get()->getActualSize(), [this, editor, searchSequence](auto &) {
|
||||
for (u8 retry = 0; retry < 2; retry++) {
|
||||
auto region = this->findSequence(searchSequence, this->m_backwards);
|
||||
auto region = this->findSequence(searchSequence, m_backwards);
|
||||
|
||||
if (region.has_value()) {
|
||||
if (editor->getSelection() == region) {
|
||||
if (this->m_nextSearchPosition.has_value())
|
||||
this->m_searchPosition = this->m_nextSearchPosition.value();
|
||||
this->m_nextSearchPosition.reset();
|
||||
if (m_nextSearchPosition.has_value())
|
||||
m_searchPosition = m_nextSearchPosition.value();
|
||||
m_nextSearchPosition.reset();
|
||||
} else {
|
||||
TaskManager::doLater([editor, region]{
|
||||
editor->setSelection(region->getStartAddress(), region->getEndAddress());
|
||||
@@ -232,12 +232,12 @@ namespace hex::plugin::builtin {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
this->m_reachedEnd = true;
|
||||
m_reachedEnd = true;
|
||||
}
|
||||
}
|
||||
|
||||
this->m_shouldSearch = false;
|
||||
this->m_requestFocus = true;
|
||||
m_shouldSearch = false;
|
||||
m_requestFocus = true;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -247,42 +247,42 @@ namespace hex::plugin::builtin {
|
||||
const auto ButtonSize = ImVec2(ImGui::CalcTextSize(ICON_VS_SEARCH).x, ImGui::GetTextLineHeight()) + ImGui::GetStyle().CellPadding * 2;
|
||||
const auto ButtonColor = ImGui::GetStyleColorVec4(ImGuiCol_Text);
|
||||
|
||||
if (this->m_requestFocus) {
|
||||
if (m_requestFocus) {
|
||||
ImGui::SetKeyboardFocusHere(-1);
|
||||
this->m_requestFocus = false;
|
||||
m_requestFocus = false;
|
||||
}
|
||||
|
||||
ImGui::BeginDisabled(this->m_searchTask.isRunning());
|
||||
ImGui::BeginDisabled(m_searchTask.isRunning());
|
||||
{
|
||||
ImGui::SameLine();
|
||||
if (ImGuiExt::IconButton(ICON_VS_SEARCH "##search", ButtonColor, ButtonSize)) {
|
||||
this->m_shouldSearch = true;
|
||||
this->m_backwards = false;
|
||||
this->m_reachedEnd = false;
|
||||
this->m_searchPosition.reset();
|
||||
this->m_nextSearchPosition.reset();
|
||||
m_shouldSearch = true;
|
||||
m_backwards = false;
|
||||
m_reachedEnd = false;
|
||||
m_searchPosition.reset();
|
||||
m_nextSearchPosition.reset();
|
||||
}
|
||||
|
||||
ImGui::BeginDisabled(!this->m_searchPosition.has_value());
|
||||
ImGui::BeginDisabled(!m_searchPosition.has_value());
|
||||
{
|
||||
ImGui::BeginDisabled(this->m_reachedEnd && this->m_backwards);
|
||||
ImGui::BeginDisabled(m_reachedEnd && m_backwards);
|
||||
{
|
||||
if (ImGuiExt::IconButton(ICON_VS_ARROW_UP "##up", ButtonColor, ButtonSize)) {
|
||||
this->m_shouldSearch = true;
|
||||
this->m_backwards = true;
|
||||
this->m_reachedEnd = false;
|
||||
m_shouldSearch = true;
|
||||
m_backwards = true;
|
||||
m_reachedEnd = false;
|
||||
}
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::BeginDisabled(this->m_reachedEnd && !this->m_backwards);
|
||||
ImGui::BeginDisabled(m_reachedEnd && !m_backwards);
|
||||
{
|
||||
if (ImGuiExt::IconButton(ICON_VS_ARROW_DOWN "##down", ButtonColor, ButtonSize)) {
|
||||
this->m_shouldSearch = true;
|
||||
this->m_backwards = false;
|
||||
this->m_reachedEnd = false;
|
||||
m_shouldSearch = true;
|
||||
m_backwards = false;
|
||||
m_reachedEnd = false;
|
||||
}
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
@@ -298,7 +298,7 @@ namespace hex::plugin::builtin {
|
||||
|
||||
prv::ProviderReader reader(provider);
|
||||
|
||||
reader.seek(this->m_searchPosition.value_or(provider->getBaseAddress()));
|
||||
reader.seek(m_searchPosition.value_or(provider->getBaseAddress()));
|
||||
|
||||
constexpr static auto searchFunction = [](const auto &haystackBegin, const auto &haystackEnd, const auto &needleBegin, const auto &needleEnd) {
|
||||
return std::search(haystackBegin, haystackEnd, std::boyer_moore_horspool_searcher(needleBegin, needleEnd));
|
||||
@@ -307,16 +307,16 @@ namespace hex::plugin::builtin {
|
||||
if (!backwards) {
|
||||
auto occurrence = searchFunction(reader.begin(), reader.end(), sequence.begin(), sequence.end());
|
||||
if (occurrence != reader.end()) {
|
||||
this->m_nextSearchPosition = occurrence.getAddress() + sequence.size();
|
||||
m_nextSearchPosition = occurrence.getAddress() + sequence.size();
|
||||
return Region { occurrence.getAddress(), sequence.size() };
|
||||
}
|
||||
} else {
|
||||
auto occurrence = searchFunction(reader.rbegin(), reader.rend(), sequence.rbegin(), sequence.rend());
|
||||
if (occurrence != reader.rend()) {
|
||||
if (occurrence.getAddress() < sequence.size())
|
||||
this->m_nextSearchPosition = 0x00;
|
||||
m_nextSearchPosition = 0x00;
|
||||
else
|
||||
this->m_nextSearchPosition = occurrence.getAddress() - sequence.size();
|
||||
m_nextSearchPosition = occurrence.getAddress() - sequence.size();
|
||||
|
||||
return Region { occurrence.getAddress() - (sequence.size() - 1), sequence.size() };
|
||||
}
|
||||
@@ -343,15 +343,15 @@ namespace hex::plugin::builtin {
|
||||
void draw(ViewHexEditor *editor) override {
|
||||
ImGui::TextUnformatted("hex.builtin.view.hex_editor.menu.edit.set_base"_lang);
|
||||
|
||||
ImGuiExt::InputHexadecimal("##base_address", &this->m_baseAddress);
|
||||
ImGuiExt::InputHexadecimal("##base_address", &m_baseAddress);
|
||||
if (ImGui::IsItemFocused() && (ImGui::IsKeyPressed(ImGuiKey_Enter) || ImGui::IsKeyPressed(ImGuiKey_KeypadEnter))) {
|
||||
setBaseAddress(this->m_baseAddress);
|
||||
setBaseAddress(m_baseAddress);
|
||||
editor->closePopup();
|
||||
}
|
||||
|
||||
ImGuiExt::ConfirmButtons("hex.builtin.common.set"_lang, "hex.builtin.common.cancel"_lang,
|
||||
[&, this]{
|
||||
setBaseAddress(this->m_baseAddress);
|
||||
setBaseAddress(m_baseAddress);
|
||||
editor->closePopup();
|
||||
},
|
||||
[&]{
|
||||
@@ -377,15 +377,15 @@ namespace hex::plugin::builtin {
|
||||
void draw(ViewHexEditor *editor) override {
|
||||
ImGui::TextUnformatted("hex.builtin.view.hex_editor.menu.edit.set_page_size"_lang);
|
||||
|
||||
ImGuiExt::InputHexadecimal("##page_size", &this->m_pageSize);
|
||||
ImGuiExt::InputHexadecimal("##page_size", &m_pageSize);
|
||||
if (ImGui::IsItemFocused() && (ImGui::IsKeyPressed(ImGuiKey_Enter) || ImGui::IsKeyPressed(ImGuiKey_KeypadEnter))) {
|
||||
setPageSize(this->m_pageSize);
|
||||
setPageSize(m_pageSize);
|
||||
editor->closePopup();
|
||||
}
|
||||
|
||||
ImGuiExt::ConfirmButtons("hex.builtin.common.set"_lang, "hex.builtin.common.cancel"_lang,
|
||||
[&, this]{
|
||||
setPageSize(this->m_pageSize);
|
||||
setPageSize(m_pageSize);
|
||||
editor->closePopup();
|
||||
},
|
||||
[&]{
|
||||
@@ -415,15 +415,15 @@ namespace hex::plugin::builtin {
|
||||
void draw(ViewHexEditor *editor) override {
|
||||
ImGui::TextUnformatted("hex.builtin.view.hex_editor.menu.edit.resize"_lang);
|
||||
|
||||
ImGuiExt::InputHexadecimal("##resize", &this->m_size);
|
||||
ImGuiExt::InputHexadecimal("##resize", &m_size);
|
||||
if (ImGui::IsItemFocused() && (ImGui::IsKeyPressed(ImGuiKey_Enter) || ImGui::IsKeyPressed(ImGuiKey_KeypadEnter))) {
|
||||
this->resize(this->m_size);
|
||||
this->resize(m_size);
|
||||
editor->closePopup();
|
||||
}
|
||||
|
||||
ImGuiExt::ConfirmButtons("hex.builtin.common.set"_lang, "hex.builtin.common.cancel"_lang,
|
||||
[&, this]{
|
||||
this->resize(this->m_size);
|
||||
this->resize(m_size);
|
||||
editor->closePopup();
|
||||
},
|
||||
[&]{
|
||||
@@ -448,12 +448,12 @@ namespace hex::plugin::builtin {
|
||||
void draw(ViewHexEditor *editor) override {
|
||||
ImGui::TextUnformatted("hex.builtin.view.hex_editor.menu.edit.insert"_lang);
|
||||
|
||||
ImGuiExt::InputHexadecimal("hex.builtin.common.address"_lang, &this->m_address);
|
||||
ImGuiExt::InputHexadecimal("hex.builtin.common.size"_lang, &this->m_size);
|
||||
ImGuiExt::InputHexadecimal("hex.builtin.common.address"_lang, &m_address);
|
||||
ImGuiExt::InputHexadecimal("hex.builtin.common.size"_lang, &m_size);
|
||||
|
||||
ImGuiExt::ConfirmButtons("hex.builtin.common.set"_lang, "hex.builtin.common.cancel"_lang,
|
||||
[&, this]{
|
||||
insert(this->m_address, this->m_size);
|
||||
insert(m_address, m_size);
|
||||
editor->closePopup();
|
||||
},
|
||||
[&]{
|
||||
@@ -479,12 +479,12 @@ namespace hex::plugin::builtin {
|
||||
void draw(ViewHexEditor *editor) override {
|
||||
ImGui::TextUnformatted("hex.builtin.view.hex_editor.menu.edit.remove"_lang);
|
||||
|
||||
ImGuiExt::InputHexadecimal("hex.builtin.common.address"_lang, &this->m_address);
|
||||
ImGuiExt::InputHexadecimal("hex.builtin.common.size"_lang, &this->m_size);
|
||||
ImGuiExt::InputHexadecimal("hex.builtin.common.address"_lang, &m_address);
|
||||
ImGuiExt::InputHexadecimal("hex.builtin.common.size"_lang, &m_size);
|
||||
|
||||
ImGuiExt::ConfirmButtons("hex.builtin.common.set"_lang, "hex.builtin.common.cancel"_lang,
|
||||
[&, this]{
|
||||
remove(this->m_address, this->m_size);
|
||||
remove(m_address, m_size);
|
||||
editor->closePopup();
|
||||
},
|
||||
[&]{
|
||||
@@ -510,16 +510,16 @@ namespace hex::plugin::builtin {
|
||||
void draw(ViewHexEditor *editor) override {
|
||||
ImGui::TextUnformatted("hex.builtin.view.hex_editor.menu.edit.fill"_lang);
|
||||
|
||||
ImGuiExt::InputHexadecimal("hex.builtin.common.address"_lang, &this->m_address);
|
||||
ImGuiExt::InputHexadecimal("hex.builtin.common.size"_lang, &this->m_size);
|
||||
ImGuiExt::InputHexadecimal("hex.builtin.common.address"_lang, &m_address);
|
||||
ImGuiExt::InputHexadecimal("hex.builtin.common.size"_lang, &m_size);
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
ImGuiExt::InputTextIcon("hex.builtin.common.bytes"_lang, ICON_VS_SYMBOL_NAMESPACE, this->m_input);
|
||||
ImGuiExt::InputTextIcon("hex.builtin.common.bytes"_lang, ICON_VS_SYMBOL_NAMESPACE, m_input);
|
||||
|
||||
ImGuiExt::ConfirmButtons("hex.builtin.common.set"_lang, "hex.builtin.common.cancel"_lang,
|
||||
[&, this] {
|
||||
fill(this->m_address, this->m_size, this->m_input);
|
||||
fill(m_address, m_size, m_input);
|
||||
editor->closePopup();
|
||||
},
|
||||
[&] {
|
||||
@@ -558,8 +558,8 @@ namespace hex::plugin::builtin {
|
||||
/* Hex Editor */
|
||||
|
||||
ViewHexEditor::ViewHexEditor() : View::Window("hex.builtin.view.hex_editor.name") {
|
||||
this->m_hexEditor.setForegroundHighlightCallback([this](u64 address, const u8 *data, size_t size) -> std::optional<color_t> {
|
||||
if (auto highlight = this->m_foregroundHighlights->find(address); highlight != this->m_foregroundHighlights->end())
|
||||
m_hexEditor.setForegroundHighlightCallback([this](u64 address, const u8 *data, size_t size) -> std::optional<color_t> {
|
||||
if (auto highlight = m_foregroundHighlights->find(address); highlight != m_foregroundHighlights->end())
|
||||
return highlight->second;
|
||||
|
||||
std::optional<color_t> result;
|
||||
@@ -576,13 +576,13 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
if (result.has_value())
|
||||
this->m_foregroundHighlights->insert({ address, result.value() });
|
||||
m_foregroundHighlights->insert({ address, result.value() });
|
||||
|
||||
return result;
|
||||
});
|
||||
|
||||
this->m_hexEditor.setBackgroundHighlightCallback([this](u64 address, const u8 *data, size_t size) -> std::optional<color_t> {
|
||||
if (auto highlight = this->m_backgroundHighlights->find(address); highlight != this->m_backgroundHighlights->end())
|
||||
m_hexEditor.setBackgroundHighlightCallback([this](u64 address, const u8 *data, size_t size) -> std::optional<color_t> {
|
||||
if (auto highlight = m_backgroundHighlights->find(address); highlight != m_backgroundHighlights->end())
|
||||
return highlight->second;
|
||||
|
||||
std::optional<color_t> result;
|
||||
@@ -599,12 +599,12 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
if (result.has_value())
|
||||
this->m_backgroundHighlights->insert({ address, result.value() });
|
||||
m_backgroundHighlights->insert({ address, result.value() });
|
||||
|
||||
return result;
|
||||
});
|
||||
|
||||
this->m_hexEditor.setTooltipCallback([](u64 address, const u8 *data, size_t size) {
|
||||
m_hexEditor.setTooltipCallback([](u64 address, const u8 *data, size_t size) {
|
||||
for (const auto &[id, callback] : ImHexApi::HexEditor::impl::getTooltipFunctions()) {
|
||||
callback(address, data, size);
|
||||
}
|
||||
@@ -644,8 +644,8 @@ namespace hex::plugin::builtin {
|
||||
|
||||
void ViewHexEditor::drawPopup() {
|
||||
// Popup windows
|
||||
if (this->m_shouldOpenPopup) {
|
||||
this->m_shouldOpenPopup = false;
|
||||
if (m_shouldOpenPopup) {
|
||||
m_shouldOpenPopup = false;
|
||||
ImGui::OpenPopup("##hex_editor_popup");
|
||||
}
|
||||
|
||||
@@ -663,8 +663,8 @@ namespace hex::plugin::builtin {
|
||||
justOpened = false;
|
||||
}
|
||||
|
||||
if (this->m_currPopup != nullptr)
|
||||
this->m_currPopup->draw(this);
|
||||
if (m_currPopup != nullptr)
|
||||
m_currPopup->draw(this);
|
||||
else
|
||||
ImGui::CloseCurrentPopup();
|
||||
|
||||
@@ -680,9 +680,9 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
void ViewHexEditor::drawContent() {
|
||||
this->m_hexEditor.setProvider(ImHexApi::Provider::get());
|
||||
m_hexEditor.setProvider(ImHexApi::Provider::get());
|
||||
|
||||
this->m_hexEditor.draw();
|
||||
m_hexEditor.draw();
|
||||
|
||||
this->drawPopup();
|
||||
}
|
||||
@@ -771,185 +771,185 @@ namespace hex::plugin::builtin {
|
||||
// Remove selection
|
||||
ShortcutManager::addShortcut(this, Keys::Escape, "hex.builtin.view.hex_editor.shortcut.remove_selection", [this] {
|
||||
auto provider = ImHexApi::Provider::get();
|
||||
this->m_selectionStart->reset();
|
||||
this->m_selectionEnd->reset();
|
||||
m_selectionStart->reset();
|
||||
m_selectionEnd->reset();
|
||||
|
||||
this->m_hexEditor.setSelectionUnchecked(std::nullopt, std::nullopt);
|
||||
m_hexEditor.setSelectionUnchecked(std::nullopt, std::nullopt);
|
||||
|
||||
EventRegionSelected::post(ImHexApi::HexEditor::ProviderRegion{ Region::Invalid(), provider });
|
||||
});
|
||||
|
||||
ShortcutManager::addShortcut(this, Keys::Enter, "hex.builtin.view.hex_editor.shortcut.enter_editing", [this] {
|
||||
if (auto cursor = this->m_hexEditor.getCursorPosition(); cursor.has_value())
|
||||
this->m_hexEditor.setEditingAddress(cursor.value());
|
||||
if (auto cursor = m_hexEditor.getCursorPosition(); cursor.has_value())
|
||||
m_hexEditor.setEditingAddress(cursor.value());
|
||||
});
|
||||
|
||||
// Move cursor around
|
||||
ShortcutManager::addShortcut(this, Keys::Up, "hex.builtin.view.hex_editor.shortcut.cursor_up", [this] {
|
||||
auto selection = getSelection();
|
||||
auto cursor = this->m_hexEditor.getCursorPosition().value_or(selection.getEndAddress());
|
||||
auto cursor = m_hexEditor.getCursorPosition().value_or(selection.getEndAddress());
|
||||
|
||||
if (cursor >= this->m_hexEditor.getBytesPerRow()) {
|
||||
auto pos = cursor - this->m_hexEditor.getBytesPerRow();
|
||||
if (cursor >= m_hexEditor.getBytesPerRow()) {
|
||||
auto pos = cursor - m_hexEditor.getBytesPerRow();
|
||||
this->setSelection(pos, pos);
|
||||
this->m_hexEditor.scrollToSelection();
|
||||
this->m_hexEditor.jumpIfOffScreen();
|
||||
m_hexEditor.scrollToSelection();
|
||||
m_hexEditor.jumpIfOffScreen();
|
||||
}
|
||||
});
|
||||
ShortcutManager::addShortcut(this, Keys::Down, "hex.builtin.view.hex_editor.shortcut.cursor_down", [this] {
|
||||
auto selection = getSelection();
|
||||
auto cursor = this->m_hexEditor.getCursorPosition().value_or(selection.getEndAddress());
|
||||
auto cursor = m_hexEditor.getCursorPosition().value_or(selection.getEndAddress());
|
||||
|
||||
auto pos = cursor + this->m_hexEditor.getBytesPerRow();
|
||||
auto pos = cursor + m_hexEditor.getBytesPerRow();
|
||||
this->setSelection(pos, pos);
|
||||
this->m_hexEditor.scrollToSelection();
|
||||
this->m_hexEditor.jumpIfOffScreen();
|
||||
m_hexEditor.scrollToSelection();
|
||||
m_hexEditor.jumpIfOffScreen();
|
||||
});
|
||||
ShortcutManager::addShortcut(this, Keys::Left, "hex.builtin.view.hex_editor.shortcut.cursor_left", [this] {
|
||||
auto selection = getSelection();
|
||||
auto cursor = this->m_hexEditor.getCursorPosition().value_or(selection.getEndAddress());
|
||||
auto cursor = m_hexEditor.getCursorPosition().value_or(selection.getEndAddress());
|
||||
|
||||
if (cursor > 0) {
|
||||
auto pos = cursor - this->m_hexEditor.getBytesPerCell();
|
||||
auto pos = cursor - m_hexEditor.getBytesPerCell();
|
||||
this->setSelection(pos, pos);
|
||||
this->m_hexEditor.scrollToSelection();
|
||||
this->m_hexEditor.jumpIfOffScreen();
|
||||
m_hexEditor.scrollToSelection();
|
||||
m_hexEditor.jumpIfOffScreen();
|
||||
}
|
||||
});
|
||||
ShortcutManager::addShortcut(this, Keys::Right, "hex.builtin.view.hex_editor.shortcut.cursor_right", [this] {
|
||||
auto selection = getSelection();
|
||||
auto cursor = this->m_hexEditor.getCursorPosition().value_or(selection.getEndAddress());
|
||||
auto cursor = m_hexEditor.getCursorPosition().value_or(selection.getEndAddress());
|
||||
|
||||
auto pos = cursor + this->m_hexEditor.getBytesPerCell();
|
||||
auto pos = cursor + m_hexEditor.getBytesPerCell();
|
||||
this->setSelection(pos, pos);
|
||||
this->m_hexEditor.scrollToSelection();
|
||||
this->m_hexEditor.jumpIfOffScreen();
|
||||
m_hexEditor.scrollToSelection();
|
||||
m_hexEditor.jumpIfOffScreen();
|
||||
});
|
||||
|
||||
ShortcutManager::addShortcut(this, Keys::PageUp, "hex.builtin.view.hex_editor.shortcut.cursor_page_up", [this] {
|
||||
auto selection = getSelection();
|
||||
auto cursor = this->m_hexEditor.getCursorPosition().value_or(selection.getEndAddress());
|
||||
auto cursor = m_hexEditor.getCursorPosition().value_or(selection.getEndAddress());
|
||||
|
||||
u64 visibleByteCount = this->m_hexEditor.getBytesPerRow() * this->m_hexEditor.getVisibleRowCount();
|
||||
u64 visibleByteCount = m_hexEditor.getBytesPerRow() * m_hexEditor.getVisibleRowCount();
|
||||
if (cursor >= visibleByteCount) {
|
||||
auto pos = cursor - visibleByteCount;
|
||||
this->setSelection(pos, (pos + this->m_hexEditor.getBytesPerCell()) - 1);
|
||||
this->m_hexEditor.scrollToSelection();
|
||||
this->m_hexEditor.jumpIfOffScreen();
|
||||
this->setSelection(pos, (pos + m_hexEditor.getBytesPerCell()) - 1);
|
||||
m_hexEditor.scrollToSelection();
|
||||
m_hexEditor.jumpIfOffScreen();
|
||||
}
|
||||
});
|
||||
ShortcutManager::addShortcut(this, Keys::PageDown, "hex.builtin.view.hex_editor.shortcut.cursor_page_down", [this] {
|
||||
auto selection = getSelection();
|
||||
auto cursor = this->m_hexEditor.getCursorPosition().value_or(selection.getEndAddress());
|
||||
auto cursor = m_hexEditor.getCursorPosition().value_or(selection.getEndAddress());
|
||||
|
||||
auto pos = cursor + (this->m_hexEditor.getBytesPerRow() * this->m_hexEditor.getVisibleRowCount());
|
||||
this->setSelection(pos, (pos + this->m_hexEditor.getBytesPerCell()) - 1);
|
||||
this->m_hexEditor.scrollToSelection();
|
||||
this->m_hexEditor.jumpIfOffScreen();
|
||||
auto pos = cursor + (m_hexEditor.getBytesPerRow() * m_hexEditor.getVisibleRowCount());
|
||||
this->setSelection(pos, (pos + m_hexEditor.getBytesPerCell()) - 1);
|
||||
m_hexEditor.scrollToSelection();
|
||||
m_hexEditor.jumpIfOffScreen();
|
||||
});
|
||||
|
||||
// Move selection around
|
||||
ShortcutManager::addShortcut(this, SHIFT + Keys::Up, "hex.builtin.view.hex_editor.shortcut.selection_up", [this] {
|
||||
auto selection = getSelection();
|
||||
auto cursor = this->m_hexEditor.getCursorPosition();
|
||||
auto cursor = m_hexEditor.getCursorPosition();
|
||||
|
||||
if (cursor != selection.getStartAddress()) {
|
||||
auto newCursor = std::max<u64>(cursor.value_or(selection.getEndAddress()), this->m_hexEditor.getBytesPerRow()) - this->m_hexEditor.getBytesPerRow();
|
||||
auto newCursor = std::max<u64>(cursor.value_or(selection.getEndAddress()), m_hexEditor.getBytesPerRow()) - m_hexEditor.getBytesPerRow();
|
||||
setSelection(selection.getStartAddress(), newCursor);
|
||||
this->m_hexEditor.setCursorPosition(newCursor);
|
||||
m_hexEditor.setCursorPosition(newCursor);
|
||||
} else {
|
||||
auto newCursor = std::max<u64>(cursor.value_or(selection.getEndAddress()), this->m_hexEditor.getBytesPerRow()) - this->m_hexEditor.getBytesPerRow();
|
||||
auto newCursor = std::max<u64>(cursor.value_or(selection.getEndAddress()), m_hexEditor.getBytesPerRow()) - m_hexEditor.getBytesPerRow();
|
||||
setSelection(newCursor, selection.getEndAddress());
|
||||
this->m_hexEditor.setCursorPosition(newCursor);
|
||||
m_hexEditor.setCursorPosition(newCursor);
|
||||
}
|
||||
|
||||
this->m_hexEditor.scrollToSelection();
|
||||
this->m_hexEditor.jumpIfOffScreen();
|
||||
m_hexEditor.scrollToSelection();
|
||||
m_hexEditor.jumpIfOffScreen();
|
||||
});
|
||||
ShortcutManager::addShortcut(this, SHIFT + Keys::Down, "hex.builtin.view.hex_editor.shortcut.selection_down", [this] {
|
||||
auto selection = getSelection();
|
||||
auto cursor = this->m_hexEditor.getCursorPosition();
|
||||
auto cursor = m_hexEditor.getCursorPosition();
|
||||
|
||||
if (cursor != selection.getStartAddress()) {
|
||||
auto newCursor = cursor.value_or(selection.getEndAddress()) + this->m_hexEditor.getBytesPerRow();
|
||||
auto newCursor = cursor.value_or(selection.getEndAddress()) + m_hexEditor.getBytesPerRow();
|
||||
setSelection(selection.getStartAddress(), newCursor);
|
||||
this->m_hexEditor.setCursorPosition(newCursor);
|
||||
m_hexEditor.setCursorPosition(newCursor);
|
||||
} else {
|
||||
auto newCursor = cursor.value_or(selection.getEndAddress()) + this->m_hexEditor.getBytesPerRow();
|
||||
auto newCursor = cursor.value_or(selection.getEndAddress()) + m_hexEditor.getBytesPerRow();
|
||||
setSelection(newCursor, selection.getEndAddress());
|
||||
this->m_hexEditor.setCursorPosition(newCursor);
|
||||
m_hexEditor.setCursorPosition(newCursor);
|
||||
}
|
||||
|
||||
this->m_hexEditor.scrollToSelection();
|
||||
this->m_hexEditor.jumpIfOffScreen();
|
||||
m_hexEditor.scrollToSelection();
|
||||
m_hexEditor.jumpIfOffScreen();
|
||||
});
|
||||
ShortcutManager::addShortcut(this, SHIFT + Keys::Left, "hex.builtin.view.hex_editor.shortcut.selection_left", [this] {
|
||||
auto selection = getSelection();
|
||||
auto cursor = this->m_hexEditor.getCursorPosition();
|
||||
auto cursor = m_hexEditor.getCursorPosition();
|
||||
|
||||
if (cursor != selection.getStartAddress()) {
|
||||
auto newCursor = cursor.value_or(selection.getEndAddress()) - this->m_hexEditor.getBytesPerCell();
|
||||
auto newCursor = cursor.value_or(selection.getEndAddress()) - m_hexEditor.getBytesPerCell();
|
||||
setSelection(selection.getStartAddress(), newCursor);
|
||||
this->m_hexEditor.setCursorPosition(newCursor);
|
||||
m_hexEditor.setCursorPosition(newCursor);
|
||||
} else {
|
||||
auto newCursor = cursor.value_or(selection.getEndAddress()) - this->m_hexEditor.getBytesPerCell();
|
||||
auto newCursor = cursor.value_or(selection.getEndAddress()) - m_hexEditor.getBytesPerCell();
|
||||
setSelection(newCursor, selection.getEndAddress());
|
||||
this->m_hexEditor.setCursorPosition(newCursor);
|
||||
m_hexEditor.setCursorPosition(newCursor);
|
||||
}
|
||||
|
||||
this->m_hexEditor.scrollToSelection();
|
||||
this->m_hexEditor.jumpIfOffScreen();
|
||||
m_hexEditor.scrollToSelection();
|
||||
m_hexEditor.jumpIfOffScreen();
|
||||
});
|
||||
ShortcutManager::addShortcut(this, SHIFT + Keys::Right, "hex.builtin.view.hex_editor.shortcut.selection_right", [this] {
|
||||
auto selection = getSelection();
|
||||
auto cursor = this->m_hexEditor.getCursorPosition();
|
||||
auto cursor = m_hexEditor.getCursorPosition();
|
||||
|
||||
if (cursor != selection.getStartAddress()) {
|
||||
auto newCursor = cursor.value_or(selection.getEndAddress()) + this->m_hexEditor.getBytesPerCell();
|
||||
auto newCursor = cursor.value_or(selection.getEndAddress()) + m_hexEditor.getBytesPerCell();
|
||||
setSelection(selection.getStartAddress(), newCursor);
|
||||
this->m_hexEditor.setCursorPosition(newCursor);
|
||||
m_hexEditor.setCursorPosition(newCursor);
|
||||
} else {
|
||||
auto newCursor = cursor.value_or(selection.getEndAddress()) + this->m_hexEditor.getBytesPerCell();
|
||||
auto newCursor = cursor.value_or(selection.getEndAddress()) + m_hexEditor.getBytesPerCell();
|
||||
setSelection(newCursor, selection.getEndAddress());
|
||||
this->m_hexEditor.setCursorPosition(newCursor);
|
||||
m_hexEditor.setCursorPosition(newCursor);
|
||||
}
|
||||
|
||||
this->m_hexEditor.scrollToSelection();
|
||||
this->m_hexEditor.jumpIfOffScreen();
|
||||
m_hexEditor.scrollToSelection();
|
||||
m_hexEditor.jumpIfOffScreen();
|
||||
});
|
||||
ShortcutManager::addShortcut(this, SHIFT + Keys::PageUp, "hex.builtin.view.hex_editor.shortcut.selection_page_up", [this] {
|
||||
auto selection = getSelection();
|
||||
auto cursor = this->m_hexEditor.getCursorPosition().value_or(selection.getEndAddress());
|
||||
auto cursor = m_hexEditor.getCursorPosition().value_or(selection.getEndAddress());
|
||||
|
||||
if (cursor != selection.getStartAddress()) {
|
||||
auto newCursor = std::max<u64>(cursor, this->m_hexEditor.getBytesPerRow()) - this->m_hexEditor.getBytesPerRow() * this->m_hexEditor.getVisibleRowCount();
|
||||
auto newCursor = std::max<u64>(cursor, m_hexEditor.getBytesPerRow()) - m_hexEditor.getBytesPerRow() * m_hexEditor.getVisibleRowCount();
|
||||
setSelection(selection.getStartAddress(), newCursor);
|
||||
this->m_hexEditor.setCursorPosition(newCursor);
|
||||
m_hexEditor.setCursorPosition(newCursor);
|
||||
} else {
|
||||
auto newCursor = std::max<u64>(cursor, this->m_hexEditor.getBytesPerRow()) - this->m_hexEditor.getBytesPerRow() * this->m_hexEditor.getVisibleRowCount();
|
||||
auto newCursor = std::max<u64>(cursor, m_hexEditor.getBytesPerRow()) - m_hexEditor.getBytesPerRow() * m_hexEditor.getVisibleRowCount();
|
||||
setSelection(newCursor, selection.getEndAddress());
|
||||
this->m_hexEditor.setCursorPosition(newCursor);
|
||||
m_hexEditor.setCursorPosition(newCursor);
|
||||
}
|
||||
|
||||
this->m_hexEditor.scrollToSelection();
|
||||
this->m_hexEditor.jumpIfOffScreen();
|
||||
m_hexEditor.scrollToSelection();
|
||||
m_hexEditor.jumpIfOffScreen();
|
||||
});
|
||||
ShortcutManager::addShortcut(this, SHIFT + Keys::PageDown, "hex.builtin.view.hex_editor.shortcut.selection_page_down", [this] {
|
||||
auto selection = getSelection();
|
||||
auto cursor = this->m_hexEditor.getCursorPosition().value_or(selection.getEndAddress());
|
||||
auto cursor = m_hexEditor.getCursorPosition().value_or(selection.getEndAddress());
|
||||
|
||||
if (cursor != selection.getStartAddress()) {
|
||||
auto newCursor = cursor + (this->m_hexEditor.getBytesPerRow() * this->m_hexEditor.getVisibleRowCount());
|
||||
auto newCursor = cursor + (m_hexEditor.getBytesPerRow() * m_hexEditor.getVisibleRowCount());
|
||||
setSelection(selection.getStartAddress(), newCursor);
|
||||
this->m_hexEditor.setCursorPosition(newCursor);
|
||||
m_hexEditor.setCursorPosition(newCursor);
|
||||
} else {
|
||||
auto newCursor = cursor + (this->m_hexEditor.getBytesPerRow() * this->m_hexEditor.getVisibleRowCount());
|
||||
auto newCursor = cursor + (m_hexEditor.getBytesPerRow() * m_hexEditor.getVisibleRowCount());
|
||||
setSelection(newCursor, selection.getEndAddress());
|
||||
this->m_hexEditor.setCursorPosition(newCursor);
|
||||
m_hexEditor.setCursorPosition(newCursor);
|
||||
}
|
||||
|
||||
this->m_hexEditor.scrollToSelection();
|
||||
this->m_hexEditor.jumpIfOffScreen();
|
||||
m_hexEditor.scrollToSelection();
|
||||
m_hexEditor.jumpIfOffScreen();
|
||||
});
|
||||
|
||||
}
|
||||
@@ -959,8 +959,8 @@ namespace hex::plugin::builtin {
|
||||
auto provider = ImHexApi::Provider::get();
|
||||
|
||||
if (region == Region::Invalid()) {
|
||||
this->m_selectionStart->reset();
|
||||
this->m_selectionEnd->reset();
|
||||
m_selectionStart->reset();
|
||||
m_selectionEnd->reset();
|
||||
EventRegionSelected::post(ImHexApi::HexEditor::ProviderRegion({ Region::Invalid(), nullptr }));
|
||||
|
||||
return;
|
||||
@@ -979,26 +979,26 @@ namespace hex::plugin::builtin {
|
||||
|
||||
EventProviderChanged::subscribe(this, [this](auto *oldProvider, auto *newProvider) {
|
||||
if (oldProvider != nullptr) {
|
||||
auto selection = this->m_hexEditor.getSelection();
|
||||
auto selection = m_hexEditor.getSelection();
|
||||
|
||||
if (selection != Region::Invalid()) {
|
||||
this->m_selectionStart.get(oldProvider) = selection.getStartAddress();
|
||||
this->m_selectionEnd.get(oldProvider) = selection.getEndAddress();
|
||||
this->m_scrollPosition.get(oldProvider) = this->m_hexEditor.getScrollPosition();
|
||||
m_selectionStart.get(oldProvider) = selection.getStartAddress();
|
||||
m_selectionEnd.get(oldProvider) = selection.getEndAddress();
|
||||
m_scrollPosition.get(oldProvider) = m_hexEditor.getScrollPosition();
|
||||
}
|
||||
}
|
||||
|
||||
this->m_hexEditor.setSelectionUnchecked(std::nullopt, std::nullopt);
|
||||
this->m_hexEditor.setScrollPosition(0);
|
||||
m_hexEditor.setSelectionUnchecked(std::nullopt, std::nullopt);
|
||||
m_hexEditor.setScrollPosition(0);
|
||||
|
||||
if (newProvider != nullptr) {
|
||||
this->m_hexEditor.setSelectionUnchecked(this->m_selectionStart.get(newProvider), this->m_selectionEnd.get(newProvider));
|
||||
this->m_hexEditor.setScrollPosition(this->m_scrollPosition.get(newProvider));
|
||||
m_hexEditor.setSelectionUnchecked(m_selectionStart.get(newProvider), m_selectionEnd.get(newProvider));
|
||||
m_hexEditor.setScrollPosition(m_scrollPosition.get(newProvider));
|
||||
} else {
|
||||
ImHexApi::HexEditor::clearSelection();
|
||||
}
|
||||
|
||||
this->m_hexEditor.forceUpdateScrollPosition();
|
||||
m_hexEditor.forceUpdateScrollPosition();
|
||||
if (isSelectionValid()) {
|
||||
EventRegionSelected::post(ImHexApi::HexEditor::ProviderRegion{ this->getSelection(), newProvider });
|
||||
}
|
||||
@@ -1009,8 +1009,8 @@ namespace hex::plugin::builtin {
|
||||
});
|
||||
|
||||
EventHighlightingChanged::subscribe(this, [this]{
|
||||
this->m_foregroundHighlights->clear();
|
||||
this->m_backgroundHighlights->clear();
|
||||
m_foregroundHighlights->clear();
|
||||
m_backgroundHighlights->clear();
|
||||
});
|
||||
|
||||
ProjectFile::registerPerProviderHandler({
|
||||
@@ -1022,12 +1022,12 @@ namespace hex::plugin::builtin {
|
||||
|
||||
auto content = tar.readString(basePath);
|
||||
if (!content.empty())
|
||||
this->m_hexEditor.setCustomEncoding(EncodingFile(hex::EncodingFile::Type::Thingy, content));
|
||||
m_hexEditor.setCustomEncoding(EncodingFile(hex::EncodingFile::Type::Thingy, content));
|
||||
|
||||
return true;
|
||||
},
|
||||
.store = [this](prv::Provider *, const std::fs::path &basePath, Tar &tar) {
|
||||
if (const auto &encoding = this->m_hexEditor.getCustomEncoding(); encoding.has_value()) {
|
||||
if (const auto &encoding = m_hexEditor.getCustomEncoding(); encoding.has_value()) {
|
||||
auto content = encoding->getTableContent();
|
||||
|
||||
if (!content.empty())
|
||||
@@ -1086,7 +1086,7 @@ namespace hex::plugin::builtin {
|
||||
ImHexApi::Provider::markDirty();
|
||||
|
||||
TaskManager::doLater([this, encoding = std::move(encoding)] mutable {
|
||||
this->m_hexEditor.setCustomEncoding(std::move(encoding));
|
||||
m_hexEditor.setCustomEncoding(std::move(encoding));
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1161,12 +1161,12 @@ namespace hex::plugin::builtin {
|
||||
Shortcut::None,
|
||||
[this] {
|
||||
auto selection = ImHexApi::HexEditor::getSelection();
|
||||
auto customEncoding = this->m_hexEditor.getCustomEncoding();
|
||||
auto customEncoding = m_hexEditor.getCustomEncoding();
|
||||
if (customEncoding.has_value() && selection.has_value() && selection != Region::Invalid())
|
||||
copyCustomEncoding(*customEncoding, *selection);
|
||||
},
|
||||
[this] {
|
||||
return ImHexApi::HexEditor::isSelectionValid() && this->m_hexEditor.getCustomEncoding().has_value();
|
||||
return ImHexApi::HexEditor::isSelectionValid() && m_hexEditor.getCustomEncoding().has_value();
|
||||
});
|
||||
|
||||
ContentRegistry::Interface::addMenuItemSeparator({ "hex.builtin.menu.edit", "hex.builtin.view.hex_editor.menu.edit.copy_as" }, 1350);
|
||||
|
||||
@@ -118,7 +118,7 @@ namespace hex::plugin::builtin {
|
||||
.load = [this](prv::Provider *provider, const std::fs::path &basePath, Tar &tar) -> bool {
|
||||
const auto json = nlohmann::json::parse(tar.readString(basePath));
|
||||
|
||||
auto &rules = this->m_rules.get(provider);
|
||||
auto &rules = m_rules.get(provider);
|
||||
rules.clear();
|
||||
|
||||
for (const auto &entry : json) {
|
||||
@@ -140,7 +140,7 @@ namespace hex::plugin::builtin {
|
||||
},
|
||||
.store = [this](prv::Provider *provider, const std::fs::path &basePath, Tar &tar) -> bool {
|
||||
nlohmann::json result = nlohmann::json::array();
|
||||
for (const auto &rule : this->m_rules.get(provider)) {
|
||||
for (const auto &rule : m_rules.get(provider)) {
|
||||
nlohmann::json content;
|
||||
|
||||
content["name"] = rule.name;
|
||||
@@ -163,9 +163,9 @@ namespace hex::plugin::builtin {
|
||||
});
|
||||
|
||||
// Initialize the selected rule iterators to point to the end of the rules lists
|
||||
this->m_selectedRule = this->m_rules->end();
|
||||
m_selectedRule = m_rules->end();
|
||||
EventProviderCreated::subscribe([this](prv::Provider *provider) {
|
||||
this->m_selectedRule.get(provider) = this->m_rules.get(provider).end();
|
||||
m_selectedRule.get(provider) = m_rules.get(provider).end();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -175,7 +175,7 @@ namespace hex::plugin::builtin {
|
||||
ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthStretch, 1);
|
||||
ImGui::TableSetupColumn("Enabled", ImGuiTableColumnFlags_WidthFixed, 10_scaled);
|
||||
|
||||
for (auto it = this->m_rules->begin(); it != this->m_rules->end(); ++it) {
|
||||
for (auto it = m_rules->begin(); it != m_rules->end(); ++it) {
|
||||
auto &rule = *it;
|
||||
|
||||
ImGui::TableNextRow();
|
||||
@@ -184,8 +184,8 @@ namespace hex::plugin::builtin {
|
||||
// Add a selectable for each rule to be able to switch between them
|
||||
ImGui::PushID(&rule);
|
||||
ImGui::BeginDisabled(!rule.enabled);
|
||||
if (ImGui::Selectable(rule.name.c_str(), this->m_selectedRule == it, ImGuiSelectableFlags_SpanAvailWidth)) {
|
||||
this->m_selectedRule = it;
|
||||
if (ImGui::Selectable(rule.name.c_str(), m_selectedRule == it, ImGuiSelectableFlags_SpanAvailWidth)) {
|
||||
m_selectedRule = it;
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
|
||||
@@ -205,21 +205,21 @@ namespace hex::plugin::builtin {
|
||||
|
||||
// Draw button to add a new rule
|
||||
if (ImGuiExt::DimmedIconButton(ICON_VS_ADD, ImGui::GetStyleColorVec4(ImGuiCol_Text))) {
|
||||
this->m_rules->emplace_back("hex.builtin.view.highlight_rules.new_rule"_lang);
|
||||
m_rules->emplace_back("hex.builtin.view.highlight_rules.new_rule"_lang);
|
||||
|
||||
if (this->m_selectedRule == this->m_rules->end())
|
||||
this->m_selectedRule = this->m_rules->begin();
|
||||
if (m_selectedRule == m_rules->end())
|
||||
m_selectedRule = m_rules->begin();
|
||||
}
|
||||
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
// Draw button to remove the selected rule
|
||||
ImGui::BeginDisabled(this->m_selectedRule == this->m_rules->end());
|
||||
ImGui::BeginDisabled(m_selectedRule == m_rules->end());
|
||||
if (ImGuiExt::DimmedIconButton(ICON_VS_REMOVE, ImGui::GetStyleColorVec4(ImGuiCol_Text))) {
|
||||
auto next = std::next(*this->m_selectedRule);
|
||||
this->m_rules->erase(*this->m_selectedRule);
|
||||
this->m_selectedRule = next;
|
||||
auto next = std::next(*m_selectedRule);
|
||||
m_rules->erase(*m_selectedRule);
|
||||
m_selectedRule = next;
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
}
|
||||
@@ -228,14 +228,14 @@ namespace hex::plugin::builtin {
|
||||
void ViewHighlightRules::drawRulesConfig() {
|
||||
ImGuiExt::BeginSubWindow("hex.builtin.view.highlight_rules.config"_lang, ImGui::GetContentRegionAvail());
|
||||
{
|
||||
if (this->m_selectedRule != this->m_rules->end()) {
|
||||
if (m_selectedRule != m_rules->end()) {
|
||||
|
||||
// Draw text input field for the rule name
|
||||
ImGui::PushItemWidth(-1);
|
||||
ImGui::InputTextWithHint("##name", "Name", this->m_selectedRule.get()->name);
|
||||
ImGui::InputTextWithHint("##name", "Name", m_selectedRule.get()->name);
|
||||
ImGui::PopItemWidth();
|
||||
|
||||
auto &rule = *this->m_selectedRule;
|
||||
auto &rule = *m_selectedRule;
|
||||
|
||||
// Draw a table containing all the expressions for the selected rule
|
||||
ImGui::PushID(&rule);
|
||||
@@ -282,7 +282,7 @@ namespace hex::plugin::builtin {
|
||||
|
||||
// Draw button to add a new expression
|
||||
if (ImGuiExt::DimmedIconButton(ICON_VS_ADD, ImGui::GetStyleColorVec4(ImGuiCol_Text))) {
|
||||
this->m_selectedRule.get()->addExpression(Rule::Expression("", {}));
|
||||
m_selectedRule.get()->addExpression(Rule::Expression("", {}));
|
||||
ImHexApi::Provider::markDirty();
|
||||
}
|
||||
|
||||
|
||||
@@ -22,27 +22,27 @@ namespace hex::plugin::builtin {
|
||||
|
||||
ViewInformation::ViewInformation() : View::Window("hex.builtin.view.information.name") {
|
||||
EventDataChanged::subscribe(this, [this] {
|
||||
this->m_dataValid = false;
|
||||
this->m_plainTextCharacterPercentage = -1.0;
|
||||
this->m_averageEntropy = -1.0;
|
||||
this->m_highestBlockEntropy = -1.0;
|
||||
this->m_blockSize = 0;
|
||||
this->m_dataMimeType.clear();
|
||||
this->m_dataDescription.clear();
|
||||
this->m_analyzedRegion = { 0, 0 };
|
||||
m_dataValid = false;
|
||||
m_plainTextCharacterPercentage = -1.0;
|
||||
m_averageEntropy = -1.0;
|
||||
m_highestBlockEntropy = -1.0;
|
||||
m_blockSize = 0;
|
||||
m_dataMimeType.clear();
|
||||
m_dataDescription.clear();
|
||||
m_analyzedRegion = { 0, 0 };
|
||||
});
|
||||
|
||||
EventRegionSelected::subscribe(this, [this](Region region) {
|
||||
// Set the position of the diagram relative to the place where
|
||||
// the user clicked inside the hex editor view
|
||||
if (this->m_blockSize != 0) {
|
||||
this->m_byteTypesDistribution.setHandlePosition(region.getStartAddress());
|
||||
this->m_chunkBasedEntropy.setHandlePosition(region.getStartAddress());
|
||||
if (m_blockSize != 0) {
|
||||
m_byteTypesDistribution.setHandlePosition(region.getStartAddress());
|
||||
m_chunkBasedEntropy.setHandlePosition(region.getStartAddress());
|
||||
}
|
||||
});
|
||||
|
||||
EventProviderDeleted::subscribe(this, [this](const auto*) {
|
||||
this->m_dataValid = false;
|
||||
m_dataValid = false;
|
||||
});
|
||||
|
||||
ContentRegistry::FileHandler::add({ ".mgc" }, [](const auto &path) {
|
||||
@@ -66,72 +66,72 @@ namespace hex::plugin::builtin {
|
||||
void ViewInformation::analyze() {
|
||||
AchievementManager::unlockAchievement("hex.builtin.achievement.misc", "hex.builtin.achievement.misc.analyze_file.name");
|
||||
|
||||
this->m_analyzerTask = TaskManager::createTask("hex.builtin.view.information.analyzing", 0, [this](auto &task) {
|
||||
m_analyzerTask = TaskManager::createTask("hex.builtin.view.information.analyzing", 0, [this](auto &task) {
|
||||
auto provider = ImHexApi::Provider::get();
|
||||
|
||||
if ((this->m_analyzedRegion.getStartAddress() >= this->m_analyzedRegion.getEndAddress()) || (this->m_analyzedRegion.getEndAddress() > provider->getActualSize())) {
|
||||
this->m_analyzedRegion = { provider->getBaseAddress(), provider->getActualSize() };
|
||||
if ((m_analyzedRegion.getStartAddress() >= m_analyzedRegion.getEndAddress()) || (m_analyzedRegion.getEndAddress() > provider->getActualSize())) {
|
||||
m_analyzedRegion = { provider->getBaseAddress(), provider->getActualSize() };
|
||||
}
|
||||
|
||||
if (this->m_inputChunkSize == 0) {
|
||||
this->m_inputChunkSize = 256;
|
||||
if (m_inputChunkSize == 0) {
|
||||
m_inputChunkSize = 256;
|
||||
}
|
||||
|
||||
task.setMaxValue(this->m_analyzedRegion.getSize());
|
||||
task.setMaxValue(m_analyzedRegion.getSize());
|
||||
|
||||
{
|
||||
magic::compile();
|
||||
|
||||
this->m_dataDescription = magic::getDescription(provider);
|
||||
this->m_dataMimeType = magic::getMIMEType(provider);
|
||||
m_dataDescription = magic::getDescription(provider);
|
||||
m_dataMimeType = magic::getMIMEType(provider);
|
||||
}
|
||||
|
||||
{
|
||||
this->m_blockSize = std::max<u32>(std::ceil(provider->getActualSize() / 2048.0F), 256);
|
||||
m_blockSize = std::max<u32>(std::ceil(provider->getActualSize() / 2048.0F), 256);
|
||||
|
||||
this->m_averageEntropy = -1.0;
|
||||
this->m_highestBlockEntropy = -1.0;
|
||||
this->m_plainTextCharacterPercentage = -1.0;
|
||||
m_averageEntropy = -1.0;
|
||||
m_highestBlockEntropy = -1.0;
|
||||
m_plainTextCharacterPercentage = -1.0;
|
||||
|
||||
// Setup / start each analysis
|
||||
|
||||
this->m_byteDistribution.reset();
|
||||
this->m_digram.reset(this->m_analysisRegion.getSize());
|
||||
this->m_layeredDistribution.reset(this->m_analysisRegion.getSize());
|
||||
this->m_byteTypesDistribution.reset(this->m_analysisRegion.getStartAddress(), this->m_analysisRegion.getEndAddress(), provider->getBaseAddress(), provider->getActualSize());
|
||||
this->m_chunkBasedEntropy.reset(this->m_inputChunkSize, this->m_analysisRegion.getStartAddress(), this->m_analysisRegion.getEndAddress(),
|
||||
m_byteDistribution.reset();
|
||||
m_digram.reset(m_analysisRegion.getSize());
|
||||
m_layeredDistribution.reset(m_analysisRegion.getSize());
|
||||
m_byteTypesDistribution.reset(m_analysisRegion.getStartAddress(), m_analysisRegion.getEndAddress(), provider->getBaseAddress(), provider->getActualSize());
|
||||
m_chunkBasedEntropy.reset(m_inputChunkSize, m_analysisRegion.getStartAddress(), m_analysisRegion.getEndAddress(),
|
||||
provider->getBaseAddress(), provider->getActualSize());
|
||||
|
||||
// Create a handle to the file
|
||||
auto reader = prv::ProviderReader(provider);
|
||||
reader.seek(this->m_analysisRegion.getStartAddress());
|
||||
reader.setEndAddress(this->m_analysisRegion.getEndAddress());
|
||||
reader.seek(m_analysisRegion.getStartAddress());
|
||||
reader.setEndAddress(m_analysisRegion.getEndAddress());
|
||||
|
||||
this->m_analyzedRegion = this->m_analysisRegion;
|
||||
m_analyzedRegion = m_analysisRegion;
|
||||
|
||||
u64 count = 0;
|
||||
|
||||
// Loop over each byte of the selection and update each analysis
|
||||
// one byte at a time to process the file only once
|
||||
for (u8 byte : reader) {
|
||||
this->m_byteDistribution.update(byte);
|
||||
this->m_byteTypesDistribution.update(byte);
|
||||
this->m_chunkBasedEntropy.update(byte);
|
||||
this->m_layeredDistribution.update(byte);
|
||||
this->m_digram.update(byte);
|
||||
m_byteDistribution.update(byte);
|
||||
m_byteTypesDistribution.update(byte);
|
||||
m_chunkBasedEntropy.update(byte);
|
||||
m_layeredDistribution.update(byte);
|
||||
m_digram.update(byte);
|
||||
++count;
|
||||
task.update(count);
|
||||
}
|
||||
|
||||
this->m_averageEntropy = this->m_chunkBasedEntropy.calculateEntropy(this->m_byteDistribution.get(), this->m_analyzedRegion.getSize());
|
||||
this->m_highestBlockEntropy = this->m_chunkBasedEntropy.getHighestEntropyBlockValue();
|
||||
this->m_highestBlockEntropyAddress = this->m_chunkBasedEntropy.getHighestEntropyBlockAddress();
|
||||
this->m_lowestBlockEntropy = this->m_chunkBasedEntropy.getLowestEntropyBlockValue();
|
||||
this->m_lowestBlockEntropyAddress = this->m_chunkBasedEntropy.getLowestEntropyBlockAddress();
|
||||
this->m_plainTextCharacterPercentage = this->m_byteTypesDistribution.getPlainTextCharacterPercentage();
|
||||
m_averageEntropy = m_chunkBasedEntropy.calculateEntropy(m_byteDistribution.get(), m_analyzedRegion.getSize());
|
||||
m_highestBlockEntropy = m_chunkBasedEntropy.getHighestEntropyBlockValue();
|
||||
m_highestBlockEntropyAddress = m_chunkBasedEntropy.getHighestEntropyBlockAddress();
|
||||
m_lowestBlockEntropy = m_chunkBasedEntropy.getLowestEntropyBlockValue();
|
||||
m_lowestBlockEntropyAddress = m_chunkBasedEntropy.getLowestEntropyBlockAddress();
|
||||
m_plainTextCharacterPercentage = m_byteTypesDistribution.getPlainTextCharacterPercentage();
|
||||
}
|
||||
|
||||
this->m_dataValid = true;
|
||||
m_dataValid = true;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -140,7 +140,7 @@ namespace hex::plugin::builtin {
|
||||
|
||||
auto provider = ImHexApi::Provider::get();
|
||||
if (ImHexApi::Provider::isValid() && provider->isReadable()) {
|
||||
ImGui::BeginDisabled(this->m_analyzerTask.isRunning());
|
||||
ImGui::BeginDisabled(m_analyzerTask.isRunning());
|
||||
ImGuiExt::BeginSubWindow("hex.builtin.common.settings"_lang);
|
||||
{
|
||||
if (ImGui::BeginTable("SettingsTable", 2, ImGuiTableFlags_BordersInner | ImGuiTableFlags_SizingFixedSame, ImVec2(ImGui::GetContentRegionAvail().x, 0))) {
|
||||
@@ -148,10 +148,10 @@ namespace hex::plugin::builtin {
|
||||
ImGui::TableSetupColumn("Right", ImGuiTableColumnFlags_WidthStretch, 0.5F);
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ui::regionSelectionPicker(&this->m_analysisRegion, provider, &this->m_selectionType, false);
|
||||
ui::regionSelectionPicker(&m_analysisRegion, provider, &m_selectionType, false);
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
ImGuiExt::InputHexadecimal("hex.builtin.view.information.block_size"_lang, &this->m_inputChunkSize);
|
||||
ImGuiExt::InputHexadecimal("hex.builtin.view.information.block_size"_lang, &m_inputChunkSize);
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
@@ -164,13 +164,13 @@ namespace hex::plugin::builtin {
|
||||
ImGuiExt::EndSubWindow();
|
||||
ImGui::EndDisabled();
|
||||
|
||||
if (this->m_analyzerTask.isRunning()) {
|
||||
if (m_analyzerTask.isRunning()) {
|
||||
ImGuiExt::TextSpinner("hex.builtin.view.information.analyzing"_lang);
|
||||
} else {
|
||||
ImGui::NewLine();
|
||||
}
|
||||
|
||||
if (!this->m_analyzerTask.isRunning() && this->m_dataValid) {
|
||||
if (!m_analyzerTask.isRunning() && m_dataValid) {
|
||||
|
||||
// Provider information
|
||||
ImGuiExt::Header("hex.builtin.view.information.provider_information"_lang, true);
|
||||
@@ -191,13 +191,13 @@ namespace hex::plugin::builtin {
|
||||
ImGui::TableNextColumn();
|
||||
ImGuiExt::TextFormatted("{}", "hex.builtin.view.information.region"_lang);
|
||||
ImGui::TableNextColumn();
|
||||
ImGuiExt::TextFormatted("0x{:X} - 0x{:X}", this->m_analyzedRegion.getStartAddress(), this->m_analyzedRegion.getEndAddress());
|
||||
ImGuiExt::TextFormatted("0x{:X} - 0x{:X}", m_analyzedRegion.getStartAddress(), m_analyzedRegion.getEndAddress());
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
|
||||
// Magic information
|
||||
if (!(this->m_dataDescription.empty() && this->m_dataMimeType.empty())) {
|
||||
if (!(m_dataDescription.empty() && m_dataMimeType.empty())) {
|
||||
ImGuiExt::Header("hex.builtin.view.information.magic"_lang);
|
||||
|
||||
if (ImGui::BeginTable("magic", 2, ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_RowBg)) {
|
||||
@@ -206,31 +206,31 @@ namespace hex::plugin::builtin {
|
||||
|
||||
ImGui::TableNextRow();
|
||||
|
||||
if (!this->m_dataDescription.empty()) {
|
||||
if (!m_dataDescription.empty()) {
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::TextUnformatted("hex.builtin.view.information.description"_lang);
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
if (this->m_dataDescription == "data") {
|
||||
ImGuiExt::TextFormattedColored(ImVec4(0.92F, 0.25F, 0.2F, 1.0F), "{} ({})", "hex.builtin.view.information.octet_stream_text"_lang, this->m_dataDescription);
|
||||
if (m_dataDescription == "data") {
|
||||
ImGuiExt::TextFormattedColored(ImVec4(0.92F, 0.25F, 0.2F, 1.0F), "{} ({})", "hex.builtin.view.information.octet_stream_text"_lang, m_dataDescription);
|
||||
} else {
|
||||
ImGuiExt::TextFormattedWrapped("{}", this->m_dataDescription);
|
||||
ImGuiExt::TextFormattedWrapped("{}", m_dataDescription);
|
||||
}
|
||||
}
|
||||
|
||||
if (!this->m_dataMimeType.empty()) {
|
||||
if (!m_dataMimeType.empty()) {
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::TextUnformatted("hex.builtin.view.information.mime"_lang);
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
if (this->m_dataMimeType == "application/octet-stream") {
|
||||
ImGuiExt::TextFormattedColored(ImVec4(0.92F, 0.25F, 0.2F, 1.0F), "{} ({})", "hex.builtin.view.information.octet_stream_text"_lang, this->m_dataMimeType);
|
||||
if (m_dataMimeType == "application/octet-stream") {
|
||||
ImGuiExt::TextFormattedColored(ImVec4(0.92F, 0.25F, 0.2F, 1.0F), "{} ({})", "hex.builtin.view.information.octet_stream_text"_lang, m_dataMimeType);
|
||||
ImGui::SameLine();
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
|
||||
ImGuiExt::HelpHover("hex.builtin.view.information.octet_stream_warning"_lang);
|
||||
ImGui::PopStyleVar();
|
||||
} else {
|
||||
ImGuiExt::TextFormatted("{}", this->m_dataMimeType);
|
||||
ImGuiExt::TextFormatted("{}", m_dataMimeType);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -241,7 +241,7 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
// Information analysis
|
||||
if (this->m_analyzedRegion.getSize() > 0) {
|
||||
if (m_analyzedRegion.getSize() > 0) {
|
||||
|
||||
ImGuiExt::Header("hex.builtin.view.information.info_analysis"_lang);
|
||||
|
||||
@@ -250,14 +250,14 @@ namespace hex::plugin::builtin {
|
||||
|
||||
// Display byte distribution analysis
|
||||
ImGui::TextUnformatted("hex.builtin.view.information.distribution"_lang);
|
||||
this->m_byteDistribution.draw(
|
||||
m_byteDistribution.draw(
|
||||
ImVec2(-1, 0),
|
||||
ImPlotFlags_NoLegend | ImPlotFlags_NoMenus | ImPlotFlags_NoBoxSelect
|
||||
);
|
||||
|
||||
// Display byte types distribution analysis
|
||||
ImGui::TextUnformatted("hex.builtin.view.information.byte_types"_lang);
|
||||
this->m_byteTypesDistribution.draw(
|
||||
m_byteTypesDistribution.draw(
|
||||
ImVec2(-1, 0),
|
||||
ImPlotFlags_NoMenus | ImPlotFlags_NoBoxSelect,
|
||||
true
|
||||
@@ -265,7 +265,7 @@ namespace hex::plugin::builtin {
|
||||
|
||||
// Display chunk-based entropy analysis
|
||||
ImGui::TextUnformatted("hex.builtin.view.information.entropy"_lang);
|
||||
this->m_chunkBasedEntropy.draw(
|
||||
m_chunkBasedEntropy.draw(
|
||||
ImVec2(-1, 0),
|
||||
ImPlotFlags_NoLegend | ImPlotFlags_NoMenus | ImPlotFlags_NoBoxSelect,
|
||||
true
|
||||
@@ -287,15 +287,15 @@ namespace hex::plugin::builtin {
|
||||
ImGui::TableNextColumn();
|
||||
ImGuiExt::TextFormatted("{}", "hex.builtin.view.information.block_size"_lang);
|
||||
ImGui::TableNextColumn();
|
||||
ImGuiExt::TextFormatted("hex.builtin.view.information.block_size.desc"_lang, this->m_chunkBasedEntropy.getSize(), this->m_chunkBasedEntropy.getChunkSize());
|
||||
ImGuiExt::TextFormatted("hex.builtin.view.information.block_size.desc"_lang, m_chunkBasedEntropy.getSize(), m_chunkBasedEntropy.getChunkSize());
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
ImGuiExt::TextFormatted("{}", "hex.builtin.view.information.file_entropy"_lang);
|
||||
ImGui::TableNextColumn();
|
||||
if (this->m_averageEntropy < 0)
|
||||
if (m_averageEntropy < 0)
|
||||
ImGui::TextUnformatted("???");
|
||||
else {
|
||||
auto entropy = std::abs(this->m_averageEntropy);
|
||||
auto entropy = std::abs(m_averageEntropy);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.1F);
|
||||
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImGui::GetColorU32(ImGuiCol_TableRowBgAlt));
|
||||
ImGui::PushStyleColor(ImGuiCol_PlotHistogram, ImColor::HSV(0.3F - (0.3F * entropy), 0.6F, 0.8F, 1.0F).Value);
|
||||
@@ -307,12 +307,12 @@ namespace hex::plugin::builtin {
|
||||
ImGui::TableNextColumn();
|
||||
ImGuiExt::TextFormatted("{}", "hex.builtin.view.information.highest_entropy"_lang);
|
||||
ImGui::TableNextColumn();
|
||||
ImGuiExt::TextFormatted("{:.5f} @", this->m_highestBlockEntropy);
|
||||
ImGuiExt::TextFormatted("{:.5f} @", m_highestBlockEntropy);
|
||||
ImGui::SameLine();
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0));
|
||||
if (ImGui::Button(hex::format("0x{:06X}", this->m_highestBlockEntropyAddress).c_str())) {
|
||||
ImHexApi::HexEditor::setSelection(this->m_highestBlockEntropyAddress, this->m_inputChunkSize);
|
||||
if (ImGui::Button(hex::format("0x{:06X}", m_highestBlockEntropyAddress).c_str())) {
|
||||
ImHexApi::HexEditor::setSelection(m_highestBlockEntropyAddress, m_inputChunkSize);
|
||||
}
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::PopStyleVar();
|
||||
@@ -320,12 +320,12 @@ namespace hex::plugin::builtin {
|
||||
ImGui::TableNextColumn();
|
||||
ImGuiExt::TextFormatted("{}", "hex.builtin.view.information.lowest_entropy"_lang);
|
||||
ImGui::TableNextColumn();
|
||||
ImGuiExt::TextFormatted("{:.5f} @", this->m_lowestBlockEntropy);
|
||||
ImGuiExt::TextFormatted("{:.5f} @", m_lowestBlockEntropy);
|
||||
ImGui::SameLine();
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0));
|
||||
if (ImGui::Button(hex::format("0x{:06X}", this->m_lowestBlockEntropyAddress).c_str())) {
|
||||
ImHexApi::HexEditor::setSelection(this->m_lowestBlockEntropyAddress, this->m_inputChunkSize);
|
||||
if (ImGui::Button(hex::format("0x{:06X}", m_lowestBlockEntropyAddress).c_str())) {
|
||||
ImHexApi::HexEditor::setSelection(m_lowestBlockEntropyAddress, m_inputChunkSize);
|
||||
}
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::PopStyleVar();
|
||||
@@ -333,13 +333,13 @@ namespace hex::plugin::builtin {
|
||||
ImGui::TableNextColumn();
|
||||
ImGuiExt::TextFormatted("{}", "hex.builtin.view.information.plain_text_percentage"_lang);
|
||||
ImGui::TableNextColumn();
|
||||
if (this->m_plainTextCharacterPercentage < 0)
|
||||
if (m_plainTextCharacterPercentage < 0)
|
||||
ImGui::TextUnformatted("???");
|
||||
else {
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.1F);
|
||||
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImGui::GetColorU32(ImGuiCol_TableRowBgAlt));
|
||||
ImGui::PushStyleColor(ImGuiCol_PlotHistogram, ImColor::HSV(0.3F * (this->m_plainTextCharacterPercentage / 100.0F), 0.8F, 0.6F, 1.0F).Value);
|
||||
ImGui::ProgressBar(this->m_plainTextCharacterPercentage / 100.0F, ImVec2(200_scaled, ImGui::GetTextLineHeight()));
|
||||
ImGui::PushStyleColor(ImGuiCol_PlotHistogram, ImColor::HSV(0.3F * (m_plainTextCharacterPercentage / 100.0F), 0.8F, 0.6F, 1.0F).Value);
|
||||
ImGui::ProgressBar(m_plainTextCharacterPercentage / 100.0F, ImVec2(200_scaled, ImGui::GetTextLineHeight()));
|
||||
ImGui::PopStyleColor(2);
|
||||
ImGui::PopStyleVar();
|
||||
}
|
||||
@@ -354,12 +354,12 @@ namespace hex::plugin::builtin {
|
||||
ImGui::TableSetupColumn("value", ImGuiTableColumnFlags_WidthStretch);
|
||||
ImGui::TableNextRow();
|
||||
|
||||
if (this->m_averageEntropy > 0.83 && this->m_highestBlockEntropy > 0.9) {
|
||||
if (m_averageEntropy > 0.83 && m_highestBlockEntropy > 0.9) {
|
||||
ImGui::TableNextColumn();
|
||||
ImGuiExt::TextFormattedColored(ImVec4(0.92F, 0.25F, 0.2F, 1.0F), "{}", "hex.builtin.view.information.encrypted"_lang);
|
||||
}
|
||||
|
||||
if (this->m_plainTextCharacterPercentage > 95) {
|
||||
if (m_plainTextCharacterPercentage > 95) {
|
||||
ImGui::TableNextColumn();
|
||||
ImGuiExt::TextFormattedColored(ImVec4(0.92F, 0.25F, 0.2F, 1.0F), "{}", "hex.builtin.view.information.plain_text"_lang);
|
||||
}
|
||||
@@ -370,7 +370,7 @@ namespace hex::plugin::builtin {
|
||||
ImGui::BeginGroup();
|
||||
{
|
||||
ImGui::TextUnformatted("hex.builtin.view.information.digram"_lang);
|
||||
this->m_digram.draw(scaled(ImVec2(300, 300)));
|
||||
m_digram.draw(scaled(ImVec2(300, 300)));
|
||||
}
|
||||
ImGui::EndGroup();
|
||||
|
||||
@@ -379,7 +379,7 @@ namespace hex::plugin::builtin {
|
||||
ImGui::BeginGroup();
|
||||
{
|
||||
ImGui::TextUnformatted("hex.builtin.view.information.layered_distribution"_lang);
|
||||
this->m_layeredDistribution.draw(scaled(ImVec2(300, 300)));
|
||||
m_layeredDistribution.draw(scaled(ImVec2(300, 300)));
|
||||
}
|
||||
ImGui::EndGroup();
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
void ViewLogs::drawContent() {
|
||||
ImGui::Combo("hex.builtin.view.logs.log_level"_lang, &this->m_logLevel, "DEBUG\0INFO\0WARNING\0ERROR\0FATAL\0");
|
||||
ImGui::Combo("hex.builtin.view.logs.log_level"_lang, &m_logLevel, "DEBUG\0INFO\0WARNING\0ERROR\0FATAL\0");
|
||||
|
||||
if (ImGui::BeginTable("##logs", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_ScrollY)) {
|
||||
ImGui::TableSetupColumn("hex.builtin.view.logs.component"_lang, ImGuiTableColumnFlags_WidthFixed, 100_scaled);
|
||||
@@ -58,7 +58,7 @@ namespace hex::plugin::builtin {
|
||||
for (size_t i = clipper.DisplayStart; i < std::min<size_t>(clipper.DisplayEnd + end, logs.size()); i++) {
|
||||
const auto &log = logs[logs.size() - 1 - i];
|
||||
|
||||
if (!shouldDisplay(log.level, this->m_logLevel)) {
|
||||
if (!shouldDisplay(log.level, m_logLevel)) {
|
||||
end++;
|
||||
clipper.ItemsCount--;
|
||||
continue;
|
||||
|
||||
@@ -151,7 +151,7 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
if (ImGui::IsMouseReleased(1) && ImGui::IsItemHovered()) {
|
||||
ImGui::OpenPopup("PatchContextMenu");
|
||||
this->m_selectedPatch = address;
|
||||
m_selectedPatch = address;
|
||||
}
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
@@ -175,8 +175,8 @@ namespace hex::plugin::builtin {
|
||||
void ViewPatches::drawAlwaysVisibleContent() {
|
||||
if (auto provider = ImHexApi::Provider::get(); provider != nullptr) {
|
||||
const auto &operations = provider->getUndoStack().getAppliedOperations();
|
||||
if (this->m_numOperations.get(provider) != operations.size()) {
|
||||
this->m_numOperations.get(provider) = operations.size();
|
||||
if (m_numOperations.get(provider) != operations.size()) {
|
||||
m_numOperations.get(provider) = operations.size();
|
||||
EventHighlightingChanged::post();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,32 +9,32 @@
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
ViewPatternData::ViewPatternData() : View::Window("hex.builtin.view.pattern_data.name") {
|
||||
this->m_patternDrawer = std::make_unique<ui::PatternDrawer>();
|
||||
m_patternDrawer = std::make_unique<ui::PatternDrawer>();
|
||||
|
||||
// Handle tree style setting changes
|
||||
EventSettingsChanged::subscribe(this, [this] {
|
||||
auto patternStyle = ContentRegistry::Settings::read("hex.builtin.setting.interface", "hex.builtin.setting.interface.pattern_tree_style", 0);
|
||||
this->m_patternDrawer->setTreeStyle(patternStyle);
|
||||
m_patternDrawer->setTreeStyle(patternStyle);
|
||||
|
||||
auto rowColoring = ContentRegistry::Settings::read("hex.builtin.setting.interface", "hex.builtin.setting.interface.pattern_data_row_bg", false);
|
||||
this->m_patternDrawer->enableRowColoring(rowColoring);
|
||||
m_patternDrawer->enableRowColoring(rowColoring);
|
||||
});
|
||||
|
||||
// Reset the pattern drawer when the provider changes
|
||||
EventProviderChanged::subscribe(this, [this](auto, auto) {
|
||||
this->m_patternDrawer->reset();
|
||||
m_patternDrawer->reset();
|
||||
});
|
||||
|
||||
EventPatternEvaluating::subscribe(this, [this]{
|
||||
this->m_patternDrawer->reset();
|
||||
m_patternDrawer->reset();
|
||||
});
|
||||
|
||||
EventPatternExecuted::subscribe(this, [this](auto){
|
||||
this->m_patternDrawer->reset();
|
||||
m_patternDrawer->reset();
|
||||
});
|
||||
|
||||
// Handle jumping to a pattern's location when it is clicked
|
||||
this->m_patternDrawer->setSelectionCallback([](Region region){ ImHexApi::HexEditor::setSelection(region); });
|
||||
m_patternDrawer->setSelectionCallback([](Region region){ ImHexApi::HexEditor::setSelection(region); });
|
||||
}
|
||||
|
||||
ViewPatternData::~ViewPatternData() {
|
||||
@@ -52,11 +52,11 @@ namespace hex::plugin::builtin {
|
||||
|
||||
const auto height = std::max(ImGui::GetContentRegionAvail().y - ImGui::GetTextLineHeightWithSpacing() - ImGui::GetStyle().FramePadding.y * 2, ImGui::GetTextLineHeightWithSpacing() * 5);
|
||||
if (!runtime.arePatternsValid()) {
|
||||
this->m_patternDrawer->draw({ }, nullptr, height);
|
||||
m_patternDrawer->draw({ }, nullptr, height);
|
||||
} else {
|
||||
// If the runtime has finished evaluating, draw the patterns
|
||||
if (TRY_LOCK(ContentRegistry::PatternLanguage::getRuntimeLock())) {
|
||||
this->m_patternDrawer->draw(runtime.getPatterns(), &runtime, height);
|
||||
m_patternDrawer->draw(runtime.getPatterns(), &runtime, height);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,17 +126,17 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
ViewPatternEditor::ViewPatternEditor() : View::Window("hex.builtin.view.pattern_editor.name") {
|
||||
this->m_parserRuntime = std::make_unique<pl::PatternLanguage>();
|
||||
ContentRegistry::PatternLanguage::configureRuntime(*this->m_parserRuntime, nullptr);
|
||||
m_parserRuntime = std::make_unique<pl::PatternLanguage>();
|
||||
ContentRegistry::PatternLanguage::configureRuntime(*m_parserRuntime, nullptr);
|
||||
|
||||
this->m_textEditor.SetLanguageDefinition(PatternLanguage());
|
||||
this->m_textEditor.SetShowWhitespaces(false);
|
||||
m_textEditor.SetLanguageDefinition(PatternLanguage());
|
||||
m_textEditor.SetShowWhitespaces(false);
|
||||
|
||||
this->m_consoleEditor.SetLanguageDefinition(ConsoleLog());
|
||||
this->m_consoleEditor.SetShowWhitespaces(false);
|
||||
this->m_consoleEditor.SetReadOnly(true);
|
||||
this->m_consoleEditor.SetShowCursor(false);
|
||||
this->m_consoleEditor.SetShowLineNumbers(false);
|
||||
m_consoleEditor.SetLanguageDefinition(ConsoleLog());
|
||||
m_consoleEditor.SetShowWhitespaces(false);
|
||||
m_consoleEditor.SetReadOnly(true);
|
||||
m_consoleEditor.SetShowCursor(false);
|
||||
m_consoleEditor.SetShowLineNumbers(false);
|
||||
|
||||
this->registerEvents();
|
||||
this->registerMenuItems();
|
||||
@@ -167,31 +167,31 @@ namespace hex::plugin::builtin {
|
||||
if (availableSize.y > 1)
|
||||
textEditorSize.y = std::clamp(textEditorSize.y, 1.0F, std::max(1.0F, availableSize.y - ImGui::GetTextLineHeightWithSpacing() * 3));
|
||||
|
||||
this->m_textEditor.Render("hex.builtin.view.pattern_editor.name"_lang, textEditorSize, true);
|
||||
m_textEditor.Render("hex.builtin.view.pattern_editor.name"_lang, textEditorSize, true);
|
||||
|
||||
if (ImGui::IsItemClicked(ImGuiMouseButton_Right)) {
|
||||
ImGui::OpenPopup("##pattern_editor_context_menu");
|
||||
}
|
||||
|
||||
if (ImGui::BeginPopup("##pattern_editor_context_menu")) {
|
||||
bool hasSelection = this->m_textEditor.HasSelection();
|
||||
bool hasSelection = m_textEditor.HasSelection();
|
||||
if (ImGui::MenuItem("hex.builtin.view.hex_editor.menu.edit.cut"_lang, Shortcut(CTRLCMD + Keys::X).toString().c_str(), false, hasSelection)) {
|
||||
this->m_textEditor.Cut();
|
||||
m_textEditor.Cut();
|
||||
}
|
||||
if (ImGui::MenuItem("hex.builtin.view.hex_editor.menu.edit.copy"_lang, Shortcut(CTRLCMD + Keys::C).toString().c_str(), false, hasSelection)) {
|
||||
this->m_textEditor.Copy();
|
||||
m_textEditor.Copy();
|
||||
}
|
||||
if (ImGui::MenuItem("hex.builtin.view.hex_editor.menu.edit.paste"_lang, Shortcut(CTRLCMD + Keys::V).toString().c_str())) {
|
||||
this->m_textEditor.Paste();
|
||||
m_textEditor.Paste();
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
if (ImGui::MenuItem("hex.builtin.menu.edit.undo"_lang, Shortcut(CTRLCMD + Keys::Z).toString().c_str(), false, this->m_textEditor.CanUndo())) {
|
||||
this->m_textEditor.Undo();
|
||||
if (ImGui::MenuItem("hex.builtin.menu.edit.undo"_lang, Shortcut(CTRLCMD + Keys::Z).toString().c_str(), false, m_textEditor.CanUndo())) {
|
||||
m_textEditor.Undo();
|
||||
}
|
||||
if (ImGui::MenuItem("hex.builtin.menu.edit.redo"_lang, Shortcut(CTRLCMD + Keys::Y).toString().c_str(), false, this->m_textEditor.CanRedo())) {
|
||||
this->m_textEditor.Redo();
|
||||
if (ImGui::MenuItem("hex.builtin.menu.edit.redo"_lang, Shortcut(CTRLCMD + Keys::Y).toString().c_str(), false, m_textEditor.CanRedo())) {
|
||||
m_textEditor.Redo();
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
@@ -222,15 +222,15 @@ namespace hex::plugin::builtin {
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
if (ImGui::BeginTabItem("hex.builtin.view.pattern_editor.env_vars"_lang)) {
|
||||
this->drawEnvVars(settingsSize, *this->m_envVarEntries);
|
||||
this->drawEnvVars(settingsSize, *m_envVarEntries);
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
if (ImGui::BeginTabItem("hex.builtin.view.pattern_editor.settings"_lang)) {
|
||||
this->drawVariableSettings(settingsSize, *this->m_patternVariables);
|
||||
this->drawVariableSettings(settingsSize, *m_patternVariables);
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
if (ImGui::BeginTabItem("hex.builtin.view.pattern_editor.sections"_lang)) {
|
||||
this->drawSectionSelector(settingsSize, *this->m_sections);
|
||||
this->drawSectionSelector(settingsSize, *m_sections);
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
if (ImGui::BeginTabItem("hex.builtin.view.pattern_editor.debugger"_lang)) {
|
||||
@@ -246,22 +246,22 @@ namespace hex::plugin::builtin {
|
||||
{
|
||||
auto &runtime = ContentRegistry::PatternLanguage::getRuntime();
|
||||
if (runtime.isRunning()) {
|
||||
if (this->m_breakpointHit) {
|
||||
if (m_breakpointHit) {
|
||||
if (ImGuiExt::IconButton(ICON_VS_DEBUG_CONTINUE, ImGuiExt::GetCustomColorVec4(ImGuiCustomCol_ToolbarYellow)))
|
||||
this->m_breakpointHit = false;
|
||||
m_breakpointHit = false;
|
||||
ImGui::SameLine();
|
||||
if (ImGuiExt::IconButton(ICON_VS_DEBUG_STEP_INTO, ImGuiExt::GetCustomColorVec4(ImGuiCustomCol_ToolbarYellow))) {
|
||||
runtime.getInternals().evaluator->pauseNextLine();
|
||||
this->m_breakpointHit = false;
|
||||
m_breakpointHit = false;
|
||||
}
|
||||
} else {
|
||||
if (ImGuiExt::IconButton(ICON_VS_DEBUG_STOP, ImGuiExt::GetCustomColorVec4(ImGuiCustomCol_ToolbarRed)))
|
||||
runtime.abort();
|
||||
}
|
||||
} else {
|
||||
if (ImGuiExt::IconButton(ICON_VS_DEBUG_START, ImGuiExt::GetCustomColorVec4(ImGuiCustomCol_ToolbarGreen)) || this->m_triggerEvaluation) {
|
||||
this->m_triggerEvaluation = false;
|
||||
this->evaluatePattern(this->m_textEditor.GetText(), provider);
|
||||
if (ImGuiExt::IconButton(ICON_VS_DEBUG_START, ImGuiExt::GetCustomColorVec4(ImGuiCustomCol_ToolbarGreen)) || m_triggerEvaluation) {
|
||||
m_triggerEvaluation = false;
|
||||
this->evaluatePattern(m_textEditor.GetText(), provider);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -269,8 +269,8 @@ namespace hex::plugin::builtin {
|
||||
ImGui::PopStyleVar();
|
||||
|
||||
ImGui::SameLine();
|
||||
if (this->m_runningEvaluators > 0) {
|
||||
if (this->m_breakpointHit) {
|
||||
if (m_runningEvaluators > 0) {
|
||||
if (m_breakpointHit) {
|
||||
ImGuiExt::TextFormatted("hex.builtin.view.pattern_editor.breakpoint_hit"_lang, runtime.getInternals().evaluator->getPauseLine().value_or(0));
|
||||
} else {
|
||||
ImGuiExt::TextSpinner("hex.builtin.view.pattern_editor.evaluating"_lang);
|
||||
@@ -294,8 +294,8 @@ namespace hex::plugin::builtin {
|
||||
const auto insertPos = [&, this](u64 address, u32 color) {
|
||||
const auto progress = (address - dataBaseAddress) / float(dataSize);
|
||||
|
||||
this->m_accessHistory[this->m_accessHistoryIndex] = { progress, color };
|
||||
this->m_accessHistoryIndex = (this->m_accessHistoryIndex + 1) % this->m_accessHistory.size();
|
||||
m_accessHistory[m_accessHistoryIndex] = { progress, color };
|
||||
m_accessHistoryIndex = (m_accessHistoryIndex + 1) % m_accessHistory.size();
|
||||
};
|
||||
|
||||
insertPos(runtime.getLastReadAddress(), ImGuiExt::GetCustomColorU32(ImGuiCustomCol_ToolbarBlue));
|
||||
@@ -303,7 +303,7 @@ namespace hex::plugin::builtin {
|
||||
insertPos(runtime.getLastPatternPlaceAddress(), ImGuiExt::GetCustomColorU32(ImGuiCustomCol_ToolbarGreen));
|
||||
|
||||
auto drawList = ImGui::GetWindowDrawList();
|
||||
for (const auto &[progress, color] : this->m_accessHistory) {
|
||||
for (const auto &[progress, color] : m_accessHistory) {
|
||||
if (progress <= 0) continue;
|
||||
|
||||
const auto linePos = startPos + ImVec2(size.x * progress, 0);
|
||||
@@ -315,9 +315,9 @@ namespace hex::plugin::builtin {
|
||||
ImGui::PopStyleVar(2);
|
||||
|
||||
} else {
|
||||
if (ImGui::Checkbox("hex.builtin.view.pattern_editor.auto"_lang, &this->m_runAutomatically)) {
|
||||
if (this->m_runAutomatically)
|
||||
this->m_hasUnevaluatedChanges = true;
|
||||
if (ImGui::Checkbox("hex.builtin.view.pattern_editor.auto"_lang, &m_runAutomatically)) {
|
||||
if (m_runAutomatically)
|
||||
m_hasUnevaluatedChanges = true;
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
@@ -334,68 +334,68 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
}
|
||||
|
||||
if (this->m_textEditor.IsTextChanged()) {
|
||||
this->m_hasUnevaluatedChanges = true;
|
||||
if (m_textEditor.IsTextChanged()) {
|
||||
m_hasUnevaluatedChanges = true;
|
||||
ImHexApi::Provider::markDirty();
|
||||
this->m_sourceCode = this->m_textEditor.GetText();
|
||||
m_sourceCode = m_textEditor.GetText();
|
||||
}
|
||||
|
||||
if (this->m_hasUnevaluatedChanges && this->m_runningEvaluators == 0 && this->m_runningParsers == 0) {
|
||||
this->m_hasUnevaluatedChanges = false;
|
||||
if (m_hasUnevaluatedChanges && m_runningEvaluators == 0 && m_runningParsers == 0) {
|
||||
m_hasUnevaluatedChanges = false;
|
||||
|
||||
auto code = this->m_textEditor.GetText();
|
||||
auto code = m_textEditor.GetText();
|
||||
EventPatternEditorChanged::post(code);
|
||||
|
||||
TaskManager::createBackgroundTask("Pattern Parsing", [this, code, provider](auto &){
|
||||
this->parsePattern(code, provider);
|
||||
|
||||
if (this->m_runAutomatically)
|
||||
this->m_triggerAutoEvaluate = true;
|
||||
if (m_runAutomatically)
|
||||
m_triggerAutoEvaluate = true;
|
||||
});
|
||||
}
|
||||
|
||||
if (this->m_triggerAutoEvaluate.exchange(false)) {
|
||||
this->evaluatePattern(this->m_textEditor.GetText(), provider);
|
||||
if (m_triggerAutoEvaluate.exchange(false)) {
|
||||
this->evaluatePattern(m_textEditor.GetText(), provider);
|
||||
}
|
||||
}
|
||||
|
||||
if (this->m_dangerousFunctionCalled && !ImGui::IsPopupOpen(ImGuiID(0), ImGuiPopupFlags_AnyPopup)) {
|
||||
if (m_dangerousFunctionCalled && !ImGui::IsPopupOpen(ImGuiID(0), ImGuiPopupFlags_AnyPopup)) {
|
||||
PopupQuestion::open("hex.builtin.view.pattern_editor.dangerous_function.desc"_lang,
|
||||
[this] {
|
||||
this->m_dangerousFunctionsAllowed = DangerousFunctionPerms::Allow;
|
||||
m_dangerousFunctionsAllowed = DangerousFunctionPerms::Allow;
|
||||
}, [this] {
|
||||
this->m_dangerousFunctionsAllowed = DangerousFunctionPerms::Deny;
|
||||
m_dangerousFunctionsAllowed = DangerousFunctionPerms::Deny;
|
||||
}
|
||||
);
|
||||
|
||||
this->m_dangerousFunctionCalled = false;
|
||||
m_dangerousFunctionCalled = false;
|
||||
}
|
||||
|
||||
View::discardNavigationRequests();
|
||||
}
|
||||
|
||||
void ViewPatternEditor::drawConsole(ImVec2 size) {
|
||||
if (this->m_consoleNeedsUpdate) {
|
||||
std::scoped_lock lock(this->m_logMutex);
|
||||
if (m_consoleNeedsUpdate) {
|
||||
std::scoped_lock lock(m_logMutex);
|
||||
|
||||
auto lineCount = this->m_consoleEditor.GetTextLines().size() - 1;
|
||||
if (this->m_console->size() < lineCount) {
|
||||
this->m_consoleEditor.SetText("");
|
||||
auto lineCount = m_consoleEditor.GetTextLines().size() - 1;
|
||||
if (m_console->size() < lineCount) {
|
||||
m_consoleEditor.SetText("");
|
||||
lineCount = 0;
|
||||
}
|
||||
|
||||
this->m_consoleEditor.SetCursorPosition({ int(lineCount + 1), 0 });
|
||||
m_consoleEditor.SetCursorPosition({ int(lineCount + 1), 0 });
|
||||
|
||||
auto linesToAdd = this->m_console->size() - lineCount;
|
||||
auto linesToAdd = m_console->size() - lineCount;
|
||||
for (size_t i = 0; i < linesToAdd; i += 1) {
|
||||
this->m_consoleEditor.InsertText(this->m_console->at(lineCount + i));
|
||||
this->m_consoleEditor.InsertText("\n");
|
||||
m_consoleEditor.InsertText(m_console->at(lineCount + i));
|
||||
m_consoleEditor.InsertText("\n");
|
||||
}
|
||||
|
||||
this->m_consoleNeedsUpdate = false;
|
||||
m_consoleNeedsUpdate = false;
|
||||
}
|
||||
|
||||
this->m_consoleEditor.Render("##console", size, true);
|
||||
m_consoleEditor.Render("##console", size, true);
|
||||
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + ImGui::GetStyle().FramePadding.y + 1_scaled);
|
||||
}
|
||||
|
||||
@@ -593,10 +593,10 @@ namespace hex::plugin::builtin {
|
||||
dataProvider->writeRaw(0x00, section.data.data(), section.data.size());
|
||||
dataProvider->setReadOnly(true);
|
||||
|
||||
auto hexEditor = auto(this->m_sectionHexEditor);
|
||||
auto hexEditor = auto(m_sectionHexEditor);
|
||||
|
||||
hexEditor.setBackgroundHighlightCallback([this, id, &runtime](u64 address, const u8 *, size_t) -> std::optional<color_t> {
|
||||
if (this->m_runningEvaluators != 0)
|
||||
if (m_runningEvaluators != 0)
|
||||
return std::nullopt;
|
||||
if (!ImHexApi::Provider::isValid())
|
||||
return std::nullopt;
|
||||
@@ -618,7 +618,7 @@ namespace hex::plugin::builtin {
|
||||
auto patternProvider = ImHexApi::Provider::get();
|
||||
|
||||
|
||||
this->m_sectionWindowDrawer[patternProvider] = [this, id, patternProvider, dataProvider, hexEditor, patternDrawer = std::make_shared<ui::PatternDrawer>(), &runtime] mutable {
|
||||
m_sectionWindowDrawer[patternProvider] = [this, id, patternProvider, dataProvider, hexEditor, patternDrawer = std::make_shared<ui::PatternDrawer>(), &runtime] mutable {
|
||||
hexEditor.setProvider(dataProvider.get());
|
||||
hexEditor.draw(480_scaled);
|
||||
patternDrawer->setSelectionCallback([&](const auto ®ion) {
|
||||
@@ -626,7 +626,7 @@ namespace hex::plugin::builtin {
|
||||
});
|
||||
|
||||
const auto &patterns = [&, this] -> const auto& {
|
||||
if (patternProvider->isReadable() && *this->m_executionDone)
|
||||
if (patternProvider->isReadable() && *m_executionDone)
|
||||
return runtime.getPatterns(id);
|
||||
else {
|
||||
static const std::vector<std::shared_ptr<pl::ptrn::Pattern>> empty;
|
||||
@@ -634,7 +634,7 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
}();
|
||||
|
||||
if (*this->m_executionDone)
|
||||
if (*m_executionDone)
|
||||
patternDrawer->draw(patterns, &runtime, 150_scaled);
|
||||
};
|
||||
}
|
||||
@@ -653,25 +653,25 @@ namespace hex::plugin::builtin {
|
||||
|
||||
if (ImGui::BeginChild("##debugger", size, true)) {
|
||||
const auto &breakpoints = evaluator->getBreakpoints();
|
||||
auto line = this->m_textEditor.GetCursorPosition().mLine + 1;
|
||||
auto line = m_textEditor.GetCursorPosition().mLine + 1;
|
||||
|
||||
if (!breakpoints.contains(line)) {
|
||||
if (ImGuiExt::IconButton(ICON_VS_DEBUG_BREAKPOINT, ImGuiExt::GetCustomColorVec4(ImGuiCustomCol_ToolbarRed))) {
|
||||
evaluator->addBreakpoint(line);
|
||||
this->m_textEditor.SetBreakpoints(breakpoints);
|
||||
m_textEditor.SetBreakpoints(breakpoints);
|
||||
}
|
||||
ImGuiExt::InfoTooltip("hex.builtin.view.pattern_editor.debugger.add_tooltip"_lang);
|
||||
} else {
|
||||
if (ImGuiExt::IconButton(ICON_VS_DEBUG_BREAKPOINT_UNVERIFIED, ImGuiExt::GetCustomColorVec4(ImGuiCustomCol_ToolbarRed))) {
|
||||
evaluator->removeBreakpoint(line);
|
||||
this->m_textEditor.SetBreakpoints(breakpoints);
|
||||
m_textEditor.SetBreakpoints(breakpoints);
|
||||
}
|
||||
ImGuiExt::InfoTooltip("hex.builtin.view.pattern_editor.debugger.remove_tooltip"_lang);
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
if (*this->m_breakpointHit) {
|
||||
if (*m_breakpointHit) {
|
||||
auto displayValue = [&](const auto &parent, size_t index) {
|
||||
return hex::format("{0} {1} [{2}]",
|
||||
"hex.builtin.view.pattern_editor.debugger.scope"_lang,
|
||||
@@ -684,14 +684,14 @@ namespace hex::plugin::builtin {
|
||||
|
||||
if (evaluator->getScopeCount() > 0) {
|
||||
ImGui::SetNextItemWidth(-1);
|
||||
auto &currScope = evaluator->getScope(-this->m_debuggerScopeIndex);
|
||||
if (ImGui::BeginCombo("##scope", displayValue(currScope.parent, this->m_debuggerScopeIndex).c_str())) {
|
||||
auto &currScope = evaluator->getScope(-m_debuggerScopeIndex);
|
||||
if (ImGui::BeginCombo("##scope", displayValue(currScope.parent, m_debuggerScopeIndex).c_str())) {
|
||||
for (size_t i = 0; i < evaluator->getScopeCount(); i++) {
|
||||
auto &scope = evaluator->getScope(-i);
|
||||
|
||||
if (ImGui::Selectable(displayValue(scope.parent, i).c_str(), i == size_t(this->m_debuggerScopeIndex))) {
|
||||
this->m_debuggerScopeIndex = i;
|
||||
this->m_resetDebuggerVariables = true;
|
||||
if (ImGui::Selectable(displayValue(scope.parent, i).c_str(), i == size_t(m_debuggerScopeIndex))) {
|
||||
m_debuggerScopeIndex = i;
|
||||
m_resetDebuggerVariables = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -699,19 +699,19 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
}
|
||||
|
||||
if (this->m_resetDebuggerVariables) {
|
||||
if (m_resetDebuggerVariables) {
|
||||
auto pauseLine = evaluator->getPauseLine();
|
||||
|
||||
(*this->m_debuggerDrawer)->reset();
|
||||
this->m_resetDebuggerVariables = false;
|
||||
this->m_textEditor.SetCursorPosition(TextEditor::Coordinates(pauseLine.value_or(0) - 1, 0));
|
||||
(*m_debuggerDrawer)->reset();
|
||||
m_resetDebuggerVariables = false;
|
||||
m_textEditor.SetCursorPosition(TextEditor::Coordinates(pauseLine.value_or(0) - 1, 0));
|
||||
|
||||
if (pauseLine.has_value())
|
||||
this->m_textEditor.SetCursorPosition({ int(pauseLine.value() - 1), 0 });
|
||||
m_textEditor.SetCursorPosition({ int(pauseLine.value() - 1), 0 });
|
||||
}
|
||||
|
||||
auto &currScope = evaluator->getScope(-this->m_debuggerScopeIndex);
|
||||
(*this->m_debuggerDrawer)->draw(*currScope.scope, &runtime, size.y - ImGui::GetTextLineHeightWithSpacing() * 4);
|
||||
auto &currScope = evaluator->getScope(-m_debuggerScopeIndex);
|
||||
(*m_debuggerDrawer)->draw(*currScope.scope, &runtime, size.y - ImGui::GetTextLineHeightWithSpacing() * 4);
|
||||
}
|
||||
}
|
||||
ImGui::EndChild();
|
||||
@@ -720,51 +720,51 @@ namespace hex::plugin::builtin {
|
||||
void ViewPatternEditor::drawAlwaysVisibleContent() {
|
||||
auto provider = ImHexApi::Provider::get();
|
||||
|
||||
auto open = this->m_sectionWindowDrawer.contains(provider);
|
||||
auto open = m_sectionWindowDrawer.contains(provider);
|
||||
if (open) {
|
||||
ImGui::SetNextWindowSize(scaled(ImVec2(600, 700)), ImGuiCond_Appearing);
|
||||
if (ImGui::Begin("hex.builtin.view.pattern_editor.section_popup"_lang, &open, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoDocking | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse)) {
|
||||
this->m_sectionWindowDrawer[provider]();
|
||||
m_sectionWindowDrawer[provider]();
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
if (!open && this->m_sectionWindowDrawer.contains(provider)) {
|
||||
if (!open && m_sectionWindowDrawer.contains(provider)) {
|
||||
ImHexApi::HexEditor::setSelection(Region::Invalid());
|
||||
this->m_sectionWindowDrawer.erase(provider);
|
||||
m_sectionWindowDrawer.erase(provider);
|
||||
}
|
||||
|
||||
if (!this->m_lastEvaluationProcessed) {
|
||||
if (!this->m_lastEvaluationResult) {
|
||||
if (this->m_lastEvaluationError->has_value()) {
|
||||
if (!m_lastEvaluationProcessed) {
|
||||
if (!m_lastEvaluationResult) {
|
||||
if (m_lastEvaluationError->has_value()) {
|
||||
TextEditor::ErrorMarkers errorMarkers = {
|
||||
{ (*this->m_lastEvaluationError)->line, (*this->m_lastEvaluationError)->message }
|
||||
{ (*m_lastEvaluationError)->line, (*m_lastEvaluationError)->message }
|
||||
};
|
||||
this->m_textEditor.SetErrorMarkers(errorMarkers);
|
||||
m_textEditor.SetErrorMarkers(errorMarkers);
|
||||
}
|
||||
} else {
|
||||
for (auto &[name, variable] : *this->m_patternVariables) {
|
||||
if (variable.outVariable && this->m_lastEvaluationOutVars->contains(name))
|
||||
variable.value = this->m_lastEvaluationOutVars->at(name);
|
||||
for (auto &[name, variable] : *m_patternVariables) {
|
||||
if (variable.outVariable && m_lastEvaluationOutVars->contains(name))
|
||||
variable.value = m_lastEvaluationOutVars->at(name);
|
||||
}
|
||||
|
||||
EventHighlightingChanged::post();
|
||||
}
|
||||
|
||||
this->m_lastEvaluationProcessed = true;
|
||||
*this->m_executionDone = true;
|
||||
m_lastEvaluationProcessed = true;
|
||||
*m_executionDone = true;
|
||||
}
|
||||
|
||||
if (this->m_shouldAnalyze) {
|
||||
this->m_shouldAnalyze = false;
|
||||
if (m_shouldAnalyze) {
|
||||
m_shouldAnalyze = false;
|
||||
|
||||
TaskManager::createBackgroundTask("Analyzing file content", [this, provider](auto &) {
|
||||
if (!this->m_autoLoadPatterns)
|
||||
if (!m_autoLoadPatterns)
|
||||
return;
|
||||
|
||||
// Copy over current pattern source code to the new provider
|
||||
if (!this->m_syncPatternSourceCode) {
|
||||
*this->m_sourceCode = this->m_textEditor.GetText();
|
||||
if (!m_syncPatternSourceCode) {
|
||||
*m_sourceCode = m_textEditor.GetText();
|
||||
}
|
||||
|
||||
pl::PatternLanguage runtime;
|
||||
@@ -844,7 +844,7 @@ namespace hex::plugin::builtin {
|
||||
return true;
|
||||
});
|
||||
|
||||
this->m_possiblePatternFiles.get(provider).clear();
|
||||
m_possiblePatternFiles.get(provider).clear();
|
||||
|
||||
std::error_code errorCode;
|
||||
for (const auto &dir : fs::getDefaultPaths(fs::ImHexPath::Patterns)) {
|
||||
@@ -868,13 +868,13 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
if (foundCorrectType)
|
||||
this->m_possiblePatternFiles.get(provider).push_back(entry.path());
|
||||
m_possiblePatternFiles.get(provider).push_back(entry.path());
|
||||
|
||||
runtime.reset();
|
||||
}
|
||||
}
|
||||
|
||||
if (!this->m_possiblePatternFiles.get(provider).empty()) {
|
||||
if (!m_possiblePatternFiles.get(provider).empty()) {
|
||||
PopupAcceptPattern::open(this);
|
||||
}
|
||||
});
|
||||
@@ -949,20 +949,20 @@ namespace hex::plugin::builtin {
|
||||
auto code = file.readString();
|
||||
|
||||
this->evaluatePattern(code, provider);
|
||||
this->m_textEditor.SetText(code);
|
||||
this->m_sourceCode = code;
|
||||
m_textEditor.SetText(code);
|
||||
m_sourceCode = code;
|
||||
|
||||
TaskManager::createBackgroundTask("Parse pattern", [this, code, provider](auto&) { this->parsePattern(code, provider); });
|
||||
}
|
||||
}
|
||||
|
||||
void ViewPatternEditor::parsePattern(const std::string &code, prv::Provider *provider) {
|
||||
this->m_runningParsers += 1;
|
||||
m_runningParsers += 1;
|
||||
|
||||
ContentRegistry::PatternLanguage::configureRuntime(*this->m_parserRuntime, nullptr);
|
||||
auto ast = this->m_parserRuntime->parseString(code);
|
||||
ContentRegistry::PatternLanguage::configureRuntime(*m_parserRuntime, nullptr);
|
||||
auto ast = m_parserRuntime->parseString(code);
|
||||
|
||||
auto &patternVariables = this->m_patternVariables.get(provider);
|
||||
auto &patternVariables = m_patternVariables.get(provider);
|
||||
|
||||
patternVariables.clear();
|
||||
|
||||
@@ -991,7 +991,7 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
}
|
||||
|
||||
this->m_runningParsers -= 1;
|
||||
m_runningParsers -= 1;
|
||||
}
|
||||
|
||||
void ViewPatternEditor::evaluatePattern(const std::string &code, prv::Provider *provider) {
|
||||
@@ -999,19 +999,19 @@ namespace hex::plugin::builtin {
|
||||
|
||||
auto lock = std::scoped_lock(ContentRegistry::PatternLanguage::getRuntimeLock());
|
||||
|
||||
this->m_runningEvaluators += 1;
|
||||
*this->m_executionDone = false;
|
||||
m_runningEvaluators += 1;
|
||||
*m_executionDone = false;
|
||||
|
||||
|
||||
this->m_textEditor.SetErrorMarkers({});
|
||||
this->m_console->clear();
|
||||
this->m_consoleNeedsUpdate = true;
|
||||
m_textEditor.SetErrorMarkers({});
|
||||
m_console->clear();
|
||||
m_consoleNeedsUpdate = true;
|
||||
|
||||
this->m_sectionWindowDrawer.clear();
|
||||
this->m_consoleEditor.SetText("");
|
||||
m_sectionWindowDrawer.clear();
|
||||
m_consoleEditor.SetText("");
|
||||
|
||||
this->m_accessHistory = {};
|
||||
this->m_accessHistoryIndex = 0;
|
||||
m_accessHistory = {};
|
||||
m_accessHistoryIndex = 0;
|
||||
|
||||
EventHighlightingChanged::post();
|
||||
|
||||
@@ -1021,41 +1021,41 @@ namespace hex::plugin::builtin {
|
||||
auto &runtime = ContentRegistry::PatternLanguage::getRuntime();
|
||||
ContentRegistry::PatternLanguage::configureRuntime(runtime, provider);
|
||||
runtime.getInternals().evaluator->setBreakpointHitCallback([this]{
|
||||
this->m_debuggerScopeIndex = 0;
|
||||
*this->m_breakpointHit = true;
|
||||
this->m_resetDebuggerVariables = true;
|
||||
while (*this->m_breakpointHit) {
|
||||
m_debuggerScopeIndex = 0;
|
||||
*m_breakpointHit = true;
|
||||
m_resetDebuggerVariables = true;
|
||||
while (*m_breakpointHit) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
}
|
||||
});
|
||||
|
||||
task.setInterruptCallback([this, &runtime] {
|
||||
this->m_breakpointHit = false;
|
||||
m_breakpointHit = false;
|
||||
runtime.abort();
|
||||
});
|
||||
|
||||
std::map<std::string, pl::core::Token::Literal> envVars;
|
||||
for (const auto &[id, name, value, type] : *this->m_envVarEntries)
|
||||
for (const auto &[id, name, value, type] : *m_envVarEntries)
|
||||
envVars.insert({ name, value });
|
||||
|
||||
std::map<std::string, pl::core::Token::Literal> inVariables;
|
||||
for (auto &[name, variable] : *this->m_patternVariables) {
|
||||
for (auto &[name, variable] : *m_patternVariables) {
|
||||
if (variable.inVariable)
|
||||
inVariables[name] = variable.value;
|
||||
}
|
||||
|
||||
runtime.setDangerousFunctionCallHandler([this]{
|
||||
this->m_dangerousFunctionCalled = true;
|
||||
m_dangerousFunctionCalled = true;
|
||||
|
||||
while (this->m_dangerousFunctionsAllowed == DangerousFunctionPerms::Ask) {
|
||||
while (m_dangerousFunctionsAllowed == DangerousFunctionPerms::Ask) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
}
|
||||
|
||||
return this->m_dangerousFunctionsAllowed == DangerousFunctionPerms::Allow;
|
||||
return m_dangerousFunctionsAllowed == DangerousFunctionPerms::Allow;
|
||||
});
|
||||
|
||||
runtime.setLogCallback([this](auto level, auto message) {
|
||||
std::scoped_lock lock(this->m_logMutex);
|
||||
std::scoped_lock lock(m_logMutex);
|
||||
|
||||
for (auto line : wolv::util::splitString(message, "\n")) {
|
||||
switch (level) {
|
||||
@@ -1067,30 +1067,30 @@ namespace hex::plugin::builtin {
|
||||
case Error: line = hex::format("E: {}", line); break;
|
||||
}
|
||||
|
||||
this->m_console->emplace_back(line);
|
||||
this->m_consoleNeedsUpdate = true;
|
||||
m_console->emplace_back(line);
|
||||
m_consoleNeedsUpdate = true;
|
||||
}
|
||||
});
|
||||
|
||||
ON_SCOPE_EXIT {
|
||||
*this->m_lastEvaluationOutVars = runtime.getOutVariables();
|
||||
*this->m_sections = runtime.getSections();
|
||||
*m_lastEvaluationOutVars = runtime.getOutVariables();
|
||||
*m_sections = runtime.getSections();
|
||||
|
||||
this->m_runningEvaluators -= 1;
|
||||
m_runningEvaluators -= 1;
|
||||
|
||||
this->m_lastEvaluationProcessed = false;
|
||||
m_lastEvaluationProcessed = false;
|
||||
|
||||
std::scoped_lock lock(this->m_logMutex);
|
||||
this->m_console->emplace_back(
|
||||
std::scoped_lock lock(m_logMutex);
|
||||
m_console->emplace_back(
|
||||
hex::format("I: Evaluation took {}", std::chrono::duration<double>(runtime.getLastRunningTime()))
|
||||
);
|
||||
this->m_consoleNeedsUpdate = true;
|
||||
m_consoleNeedsUpdate = true;
|
||||
};
|
||||
|
||||
|
||||
this->m_lastEvaluationResult = runtime.executeString(code, envVars, inVariables);
|
||||
if (!this->m_lastEvaluationResult) {
|
||||
*this->m_lastEvaluationError = runtime.getError();
|
||||
m_lastEvaluationResult = runtime.executeString(code, envVars, inVariables);
|
||||
if (!m_lastEvaluationResult) {
|
||||
*m_lastEvaluationError = runtime.getError();
|
||||
}
|
||||
|
||||
TaskManager::doLater([code] {
|
||||
@@ -1105,52 +1105,52 @@ namespace hex::plugin::builtin {
|
||||
});
|
||||
|
||||
RequestRunPatternCode::subscribe(this, [this] {
|
||||
this->m_triggerAutoEvaluate = true;
|
||||
m_triggerAutoEvaluate = true;
|
||||
});
|
||||
|
||||
RequestSavePatternLanguageFile::subscribe(this, [this](const std::fs::path &path) {
|
||||
wolv::io::File file(path, wolv::io::File::Mode::Create);
|
||||
file.writeString(wolv::util::trim(this->m_textEditor.GetText()));
|
||||
file.writeString(wolv::util::trim(m_textEditor.GetText()));
|
||||
});
|
||||
|
||||
RequestSetPatternLanguageCode::subscribe(this, [this](const std::string &code) {
|
||||
this->m_textEditor.SetText(code);
|
||||
this->m_sourceCode = code;
|
||||
this->m_hasUnevaluatedChanges = true;
|
||||
m_textEditor.SetText(code);
|
||||
m_sourceCode = code;
|
||||
m_hasUnevaluatedChanges = true;
|
||||
});
|
||||
|
||||
EventSettingsChanged::subscribe(this, [this] {
|
||||
this->m_syncPatternSourceCode = ContentRegistry::Settings::read("hex.builtin.setting.general", "hex.builtin.setting.general.sync_pattern_source", false);
|
||||
this->m_autoLoadPatterns = ContentRegistry::Settings::read("hex.builtin.setting.general", "hex.builtin.setting.general.auto_load_patterns", true);
|
||||
m_syncPatternSourceCode = ContentRegistry::Settings::read("hex.builtin.setting.general", "hex.builtin.setting.general.sync_pattern_source", false);
|
||||
m_autoLoadPatterns = ContentRegistry::Settings::read("hex.builtin.setting.general", "hex.builtin.setting.general.auto_load_patterns", true);
|
||||
});
|
||||
|
||||
EventProviderOpened::subscribe(this, [this](prv::Provider *provider) {
|
||||
this->m_shouldAnalyze.get(provider) = true;
|
||||
this->m_envVarEntries->push_back({ 0, "", 0, EnvVarType::Integer });
|
||||
m_shouldAnalyze.get(provider) = true;
|
||||
m_envVarEntries->push_back({ 0, "", 0, EnvVarType::Integer });
|
||||
|
||||
this->m_debuggerDrawer.get(provider) = std::make_unique<ui::PatternDrawer>();
|
||||
m_debuggerDrawer.get(provider) = std::make_unique<ui::PatternDrawer>();
|
||||
});
|
||||
|
||||
EventProviderChanged::subscribe(this, [this](prv::Provider *oldProvider, prv::Provider *newProvider) {
|
||||
if (!this->m_syncPatternSourceCode) {
|
||||
if (!m_syncPatternSourceCode) {
|
||||
if (oldProvider != nullptr)
|
||||
this->m_sourceCode.get(oldProvider) = this->m_textEditor.GetText();
|
||||
m_sourceCode.get(oldProvider) = m_textEditor.GetText();
|
||||
|
||||
if (newProvider != nullptr) {
|
||||
this->m_consoleEditor.SetTextLines(this->m_console.get(newProvider));
|
||||
this->m_textEditor.SetText(wolv::util::trim(this->m_sourceCode.get(newProvider)));
|
||||
m_consoleEditor.SetTextLines(m_console.get(newProvider));
|
||||
m_textEditor.SetText(wolv::util::trim(m_sourceCode.get(newProvider)));
|
||||
}
|
||||
else
|
||||
this->m_textEditor.SetText("");
|
||||
m_textEditor.SetText("");
|
||||
} else {
|
||||
this->m_hasUnevaluatedChanges = true;
|
||||
m_hasUnevaluatedChanges = true;
|
||||
}
|
||||
});
|
||||
|
||||
EventProviderClosed::subscribe(this, [this](prv::Provider *) {
|
||||
if (this->m_syncPatternSourceCode && ImHexApi::Provider::getProviders().empty()) {
|
||||
this->m_textEditor.SetText("");
|
||||
this->m_sourceCode = "";
|
||||
if (m_syncPatternSourceCode && ImHexApi::Provider::getProviders().empty()) {
|
||||
m_textEditor.SetText("");
|
||||
m_sourceCode = "";
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1171,9 +1171,9 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
void ViewPatternEditor::appendEditorText(const std::string &text) {
|
||||
this->m_textEditor.SetCursorPosition(TextEditor::Coordinates { this->m_textEditor.GetTotalLines(), 0 });
|
||||
this->m_textEditor.InsertText(hex::format("\n{0}", text));
|
||||
this->m_triggerEvaluation = true;
|
||||
m_textEditor.SetCursorPosition(TextEditor::Coordinates { m_textEditor.GetTotalLines(), 0 });
|
||||
m_textEditor.InsertText(hex::format("\n{0}", text));
|
||||
m_triggerEvaluation = true;
|
||||
}
|
||||
|
||||
void ViewPatternEditor::appendVariable(const std::string &type) {
|
||||
@@ -1222,10 +1222,10 @@ namespace hex::plugin::builtin {
|
||||
[this](const auto &path) {
|
||||
wolv::io::File file(path, wolv::io::File::Mode::Create);
|
||||
|
||||
file.writeString(wolv::util::trim(this->m_textEditor.GetText()));
|
||||
file.writeString(wolv::util::trim(m_textEditor.GetText()));
|
||||
});
|
||||
}, [this] {
|
||||
return !wolv::util::trim(this->m_textEditor.GetText()).empty() && ImHexApi::Provider::isValid();
|
||||
return !wolv::util::trim(m_textEditor.GetText()).empty() && ImHexApi::Provider::isValid();
|
||||
}
|
||||
);
|
||||
|
||||
@@ -1257,7 +1257,7 @@ namespace hex::plugin::builtin {
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
const auto &types = this->m_parserRuntime->getInternals().parser->getTypes();
|
||||
const auto &types = m_parserRuntime->getInternals().parser->getTypes();
|
||||
bool hasPlaceableTypes = std::any_of(types.begin(), types.end(), [](const auto &type) { return !type.second->isTemplateType(); });
|
||||
|
||||
if (ImGui::BeginMenu("hex.builtin.view.pattern_editor.menu.edit.place_pattern.custom"_lang, hasPlaceableTypes)) {
|
||||
@@ -1280,7 +1280,7 @@ namespace hex::plugin::builtin {
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
}, [this] {
|
||||
return ImHexApi::Provider::isValid() && ImHexApi::HexEditor::isSelectionValid() && this->m_runningParsers == 0;
|
||||
return ImHexApi::Provider::isValid() && ImHexApi::HexEditor::isSelectionValid() && m_runningParsers == 0;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1299,7 +1299,7 @@ namespace hex::plugin::builtin {
|
||||
ImHexApi::HexEditor::addBackgroundHighlightingProvider([this](u64 address, const u8 *data, size_t size, bool) -> std::optional<color_t> {
|
||||
hex::unused(data, size);
|
||||
|
||||
if (this->m_runningEvaluators != 0)
|
||||
if (m_runningEvaluators != 0)
|
||||
return std::nullopt;
|
||||
|
||||
auto &runtime = ContentRegistry::PatternLanguage::getRuntime();
|
||||
@@ -1358,11 +1358,11 @@ namespace hex::plugin::builtin {
|
||||
.load = [this](prv::Provider *provider, const std::fs::path &basePath, Tar &tar) {
|
||||
std::string sourceCode = tar.readString(basePath);
|
||||
|
||||
if (!this->m_syncPatternSourceCode)
|
||||
this->m_sourceCode.get(provider) = sourceCode;
|
||||
if (!m_syncPatternSourceCode)
|
||||
m_sourceCode.get(provider) = sourceCode;
|
||||
|
||||
if (provider == ImHexApi::Provider::get())
|
||||
this->m_textEditor.SetText(sourceCode);
|
||||
m_textEditor.SetText(sourceCode);
|
||||
|
||||
return true;
|
||||
},
|
||||
@@ -1370,12 +1370,12 @@ namespace hex::plugin::builtin {
|
||||
std::string sourceCode;
|
||||
|
||||
if (provider == ImHexApi::Provider::get())
|
||||
this->m_sourceCode.get(provider) = this->m_textEditor.GetText();
|
||||
m_sourceCode.get(provider) = m_textEditor.GetText();
|
||||
|
||||
if (this->m_syncPatternSourceCode)
|
||||
sourceCode = this->m_textEditor.GetText();
|
||||
if (m_syncPatternSourceCode)
|
||||
sourceCode = m_textEditor.GetText();
|
||||
else
|
||||
sourceCode = this->m_sourceCode.get(provider);
|
||||
sourceCode = m_sourceCode.get(provider);
|
||||
|
||||
tar.writeString(basePath, wolv::util::trim(sourceCode));
|
||||
return true;
|
||||
@@ -1383,7 +1383,7 @@ namespace hex::plugin::builtin {
|
||||
});
|
||||
|
||||
ShortcutManager::addShortcut(this, Keys::F8 + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.add_breakpoint", [this] {
|
||||
auto line = this->m_textEditor.GetCursorPosition().mLine + 1;
|
||||
auto line = m_textEditor.GetCursorPosition().mLine + 1;
|
||||
auto &runtime = ContentRegistry::PatternLanguage::getRuntime();
|
||||
|
||||
auto &evaluator = runtime.getInternals().evaluator;
|
||||
@@ -1395,19 +1395,19 @@ namespace hex::plugin::builtin {
|
||||
evaluator->addBreakpoint(line);
|
||||
}
|
||||
|
||||
this->m_textEditor.SetBreakpoints(breakpoints);
|
||||
m_textEditor.SetBreakpoints(breakpoints);
|
||||
});
|
||||
|
||||
/* Trigger evaluation */
|
||||
ShortcutManager::addGlobalShortcut(Keys::F5 + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.run_pattern", [this] {
|
||||
this->m_triggerAutoEvaluate = true;
|
||||
m_triggerAutoEvaluate = true;
|
||||
});
|
||||
|
||||
/* Continue debugger */
|
||||
ShortcutManager::addGlobalShortcut(SHIFT + Keys::F9 + AllowWhileTyping, "hex.builtin.view.pattern_editor.shortcut.continue_debugger", [this] {
|
||||
auto &runtime = ContentRegistry::PatternLanguage::getRuntime();
|
||||
if (runtime.isRunning())
|
||||
this->m_breakpointHit = false;
|
||||
m_breakpointHit = false;
|
||||
});
|
||||
|
||||
/* Step debugger */
|
||||
@@ -1415,13 +1415,13 @@ namespace hex::plugin::builtin {
|
||||
auto &runtime = ContentRegistry::PatternLanguage::getRuntime();
|
||||
if (runtime.isRunning()) {
|
||||
runtime.getInternals().evaluator->pauseNextLine();
|
||||
this->m_breakpointHit = false;
|
||||
m_breakpointHit = false;
|
||||
}
|
||||
});
|
||||
|
||||
// Generate pattern code report
|
||||
ContentRegistry::Reports::addReportProvider([this](prv::Provider *provider) -> std::string {
|
||||
auto patternCode = this->m_sourceCode.get(provider);
|
||||
auto patternCode = m_sourceCode.get(provider);
|
||||
|
||||
if (wolv::util::trim(patternCode).empty())
|
||||
return "";
|
||||
|
||||
@@ -88,8 +88,8 @@ namespace hex::plugin::builtin {
|
||||
|
||||
// Request a restart if the setting requires it
|
||||
if (widget->doesRequireRestart()) {
|
||||
this->m_restartRequested = true;
|
||||
this->m_triggerPopup = true;
|
||||
m_restartRequested = true;
|
||||
m_triggerPopup = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -109,12 +109,12 @@ namespace hex::plugin::builtin {
|
||||
|
||||
void ViewSettings::drawAlwaysVisibleContent() {
|
||||
// If a restart is required, ask the user if they want to restart
|
||||
if (!this->getWindowOpenState() && this->m_triggerPopup) {
|
||||
this->m_triggerPopup = false;
|
||||
if (!this->getWindowOpenState() && m_triggerPopup) {
|
||||
m_triggerPopup = false;
|
||||
PopupQuestion::open("hex.builtin.view.settings.restart_question"_lang,
|
||||
ImHexApi::System::restartImHex,
|
||||
[this]{
|
||||
this->m_restartRequested = false;
|
||||
m_restartRequested = false;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -29,13 +29,13 @@ namespace hex::plugin::builtin {
|
||||
|
||||
ViewStore::ViewStore() : View::Floating("hex.builtin.view.store.name") {
|
||||
ContentRegistry::Interface::addMenuItem({ "hex.builtin.menu.extras", "hex.builtin.view.store.name" }, 1000, Shortcut::None, [&, this] {
|
||||
if (this->m_requestStatus == RequestStatus::NotAttempted)
|
||||
if (m_requestStatus == RequestStatus::NotAttempted)
|
||||
this->refresh();
|
||||
|
||||
this->getWindowOpenState() = true;
|
||||
});
|
||||
|
||||
this->m_httpRequest.setTimeout(30'0000);
|
||||
m_httpRequest.setTimeout(30'0000);
|
||||
|
||||
addCategory("hex.builtin.view.store.tab.patterns", "patterns", fs::ImHexPath::Patterns);
|
||||
addCategory("hex.builtin.view.store.tab.includes", "includes", fs::ImHexPath::PatternsInclude);
|
||||
@@ -46,7 +46,7 @@ namespace hex::plugin::builtin {
|
||||
addCategory("hex.builtin.view.store.tab.encodings", "encodings", fs::ImHexPath::Encodings);
|
||||
addCategory("hex.builtin.view.store.tab.constants", "constants", fs::ImHexPath::Constants);
|
||||
addCategory("hex.builtin.view.store.tab.themes", "themes", fs::ImHexPath::Themes, [this]{
|
||||
auto themeFile = wolv::io::File(this->m_downloadPath, wolv::io::File::Mode::Read);
|
||||
auto themeFile = wolv::io::File(m_downloadPath, wolv::io::File::Mode::Read);
|
||||
|
||||
ThemeManager::addTheme(themeFile.readString());
|
||||
});
|
||||
@@ -114,12 +114,12 @@ namespace hex::plugin::builtin {
|
||||
const auto buttonSize = ImVec2(100_scaled, ImGui::GetTextLineHeightWithSpacing());
|
||||
|
||||
ImGui::PushID(id);
|
||||
ImGui::BeginDisabled(this->m_updateAllTask.isRunning() || (this->m_download.valid() && this->m_download.wait_for(0s) != std::future_status::ready));
|
||||
ImGui::BeginDisabled(m_updateAllTask.isRunning() || (m_download.valid() && m_download.wait_for(0s) != std::future_status::ready));
|
||||
{
|
||||
if (entry.downloading) {
|
||||
ImGui::ProgressBar(this->m_httpRequest.getProgress(), buttonSize, "");
|
||||
ImGui::ProgressBar(m_httpRequest.getProgress(), buttonSize, "");
|
||||
|
||||
if (this->m_download.valid() && this->m_download.wait_for(0s) == std::future_status::ready) {
|
||||
if (m_download.valid() && m_download.wait_for(0s) == std::future_status::ready) {
|
||||
this->handleDownloadFinished(category, entry);
|
||||
}
|
||||
|
||||
@@ -169,8 +169,8 @@ namespace hex::plugin::builtin {
|
||||
ImGuiExt::Header("hex.builtin.view.store.desc"_lang, true);
|
||||
|
||||
bool reloading = false;
|
||||
if (this->m_apiRequest.valid()) {
|
||||
if (this->m_apiRequest.wait_for(0s) != std::future_status::ready)
|
||||
if (m_apiRequest.valid()) {
|
||||
if (m_apiRequest.wait_for(0s) != std::future_status::ready)
|
||||
reloading = true;
|
||||
else
|
||||
this->parseResponse();
|
||||
@@ -189,15 +189,15 @@ namespace hex::plugin::builtin {
|
||||
|
||||
// Align the button to the right
|
||||
ImGui::SameLine(ImGui::GetWindowWidth() - ImGui::GetCursorPosX() - 25_scaled);
|
||||
ImGui::BeginDisabled(this->m_updateAllTask.isRunning() || this->m_updateCount == 0);
|
||||
ImGui::BeginDisabled(m_updateAllTask.isRunning() || m_updateCount == 0);
|
||||
if (ImGuiExt::IconButton(ICON_VS_CLOUD_DOWNLOAD, ImGui::GetStyleColorVec4(ImGuiCol_Text))) {
|
||||
this->m_updateAllTask = TaskManager::createTask("Update All...", this->m_updateCount, [this](auto &task) {
|
||||
m_updateAllTask = TaskManager::createTask("Update All...", m_updateCount, [this](auto &task) {
|
||||
u32 progress = 0;
|
||||
for (auto &category : this->m_categories) {
|
||||
for (auto &category : m_categories) {
|
||||
for (auto &entry : category.entries) {
|
||||
if (entry.hasUpdate) {
|
||||
entry.downloading = this->download(category.path, entry.fileName, entry.link, true);
|
||||
this->m_download.wait();
|
||||
m_download.wait();
|
||||
this->handleDownloadFinished(category, entry);
|
||||
task.update(progress);
|
||||
}
|
||||
@@ -205,12 +205,12 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
});
|
||||
}
|
||||
ImGuiExt::InfoTooltip(hex::format("hex.builtin.view.store.update_count"_lang, this->m_updateCount.load()).c_str());
|
||||
ImGuiExt::InfoTooltip(hex::format("hex.builtin.view.store.update_count"_lang, m_updateCount.load()).c_str());
|
||||
|
||||
ImGui::EndDisabled();
|
||||
|
||||
if (ImGui::BeginTabBar("storeTabs")) {
|
||||
for (auto &category : this->m_categories) {
|
||||
for (auto &category : m_categories) {
|
||||
this->drawTab(category);
|
||||
}
|
||||
|
||||
@@ -221,22 +221,22 @@ namespace hex::plugin::builtin {
|
||||
|
||||
void ViewStore::refresh() {
|
||||
// Do not refresh if a refresh is already in progress
|
||||
if (this->m_requestStatus == RequestStatus::InProgress)
|
||||
if (m_requestStatus == RequestStatus::InProgress)
|
||||
return;
|
||||
this->m_requestStatus = RequestStatus::InProgress;
|
||||
m_requestStatus = RequestStatus::InProgress;
|
||||
|
||||
for (auto &category : this->m_categories) {
|
||||
for (auto &category : m_categories) {
|
||||
category.entries.clear();
|
||||
}
|
||||
|
||||
this->m_httpRequest.setUrl(ImHexApiURL + "/store"s);
|
||||
this->m_apiRequest = this->m_httpRequest.execute();
|
||||
m_httpRequest.setUrl(ImHexApiURL + "/store"s);
|
||||
m_apiRequest = m_httpRequest.execute();
|
||||
}
|
||||
|
||||
void ViewStore::parseResponse() {
|
||||
auto response = this->m_apiRequest.get();
|
||||
this->m_requestStatus = response.isSuccess() ? RequestStatus::Succeeded : RequestStatus::Failed;
|
||||
if (this->m_requestStatus == RequestStatus::Succeeded) {
|
||||
auto response = m_apiRequest.get();
|
||||
m_requestStatus = response.isSuccess() ? RequestStatus::Succeeded : RequestStatus::Failed;
|
||||
if (m_requestStatus == RequestStatus::Succeeded) {
|
||||
auto json = nlohmann::json::parse(response.getData());
|
||||
|
||||
auto parseStoreEntries = [](auto storeJson, StoreCategory &category) {
|
||||
@@ -262,23 +262,23 @@ namespace hex::plugin::builtin {
|
||||
});
|
||||
};
|
||||
|
||||
for (auto &category : this->m_categories) {
|
||||
for (auto &category : m_categories) {
|
||||
parseStoreEntries(json, category);
|
||||
}
|
||||
|
||||
this->m_updateCount = 0;
|
||||
for (auto &category : this->m_categories) {
|
||||
m_updateCount = 0;
|
||||
for (auto &category : m_categories) {
|
||||
for (auto &entry : category.entries) {
|
||||
if (entry.hasUpdate)
|
||||
this->m_updateCount += 1;
|
||||
m_updateCount += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
this->m_apiRequest = {};
|
||||
m_apiRequest = {};
|
||||
}
|
||||
|
||||
void ViewStore::drawContent() {
|
||||
if (this->m_requestStatus == RequestStatus::Failed)
|
||||
if (m_requestStatus == RequestStatus::Failed)
|
||||
ImGuiExt::TextFormattedColored(ImGuiExt::GetCustomColorVec4(ImGuiCustomCol_ToolbarRed), "hex.builtin.view.store.netfailed"_lang);
|
||||
|
||||
this->drawStore();
|
||||
@@ -301,10 +301,10 @@ namespace hex::plugin::builtin {
|
||||
|
||||
if (!update || wolv::io::fs::exists(fullPath)) {
|
||||
downloading = true;
|
||||
this->m_downloadPath = fullPath;
|
||||
m_downloadPath = fullPath;
|
||||
|
||||
this->m_httpRequest.setUrl(url);
|
||||
this->m_download = this->m_httpRequest.downloadFile(fullPath);
|
||||
m_httpRequest.setUrl(url);
|
||||
m_download = m_httpRequest.downloadFile(fullPath);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -334,27 +334,27 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
void ViewStore::addCategory(const UnlocalizedString &unlocalizedName, const std::string &requestName, fs::ImHexPath path, std::function<void()> downloadCallback) {
|
||||
this->m_categories.push_back({ unlocalizedName, requestName, path, { }, std::move(downloadCallback) });
|
||||
m_categories.push_back({ unlocalizedName, requestName, path, { }, std::move(downloadCallback) });
|
||||
}
|
||||
|
||||
void ViewStore::handleDownloadFinished(const StoreCategory &category, StoreEntry &entry) {
|
||||
entry.downloading = false;
|
||||
|
||||
auto response = this->m_download.get();
|
||||
auto response = m_download.get();
|
||||
if (response.isSuccess()) {
|
||||
if (entry.hasUpdate)
|
||||
this->m_updateCount -= 1;
|
||||
m_updateCount -= 1;
|
||||
|
||||
entry.installed = true;
|
||||
entry.hasUpdate = false;
|
||||
entry.system = false;
|
||||
|
||||
if (entry.isFolder) {
|
||||
Tar tar(this->m_downloadPath, Tar::Mode::Read);
|
||||
tar.extractAll(this->m_downloadPath.parent_path() / this->m_downloadPath.stem());
|
||||
EventStoreContentDownloaded::post(this->m_downloadPath.parent_path() / this->m_downloadPath.stem());
|
||||
Tar tar(m_downloadPath, Tar::Mode::Read);
|
||||
tar.extractAll(m_downloadPath.parent_path() / m_downloadPath.stem());
|
||||
EventStoreContentDownloaded::post(m_downloadPath.parent_path() / m_downloadPath.stem());
|
||||
} else {
|
||||
EventStoreContentDownloaded::post(this->m_downloadPath);
|
||||
EventStoreContentDownloaded::post(m_downloadPath);
|
||||
}
|
||||
|
||||
category.downloadCallback();
|
||||
@@ -362,7 +362,7 @@ namespace hex::plugin::builtin {
|
||||
log::error("Download failed! HTTP Code {}", response.getStatusCode());
|
||||
|
||||
|
||||
this->m_download = {};
|
||||
m_download = {};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -28,9 +28,9 @@ namespace hex::plugin::builtin {
|
||||
|
||||
// Loop over all the individual theme settings
|
||||
for (auto &[colorName, colorId] : handler.colorMap) {
|
||||
if (this->m_startingColor.has_value()) {
|
||||
if (this->m_hoveredColorId == colorId && this->m_hoveredHandlerName == name) {
|
||||
handler.setFunction(colorId, this->m_startingColor.value());
|
||||
if (m_startingColor.has_value()) {
|
||||
if (m_hoveredColorId == colorId && m_hoveredHandlerName == name) {
|
||||
handler.setFunction(colorId, m_startingColor.value());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,17 +47,17 @@ namespace hex::plugin::builtin {
|
||||
if (ImGui::IsItemHovered()) {
|
||||
anyColorHovered = true;
|
||||
|
||||
if (!this->m_hoveredColorId.has_value()) {
|
||||
this->m_hoveredColorId = colorId;
|
||||
this->m_startingColor = color;
|
||||
this->m_hoveredHandlerName = name;
|
||||
if (!m_hoveredColorId.has_value()) {
|
||||
m_hoveredColorId = colorId;
|
||||
m_startingColor = color;
|
||||
m_hoveredHandlerName = name;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this->m_hoveredHandlerName == name && this->m_startingColor.has_value() && this->m_hoveredColorId.has_value()) {
|
||||
auto flashingColor = this->m_startingColor.value();
|
||||
if (m_hoveredHandlerName == name && m_startingColor.has_value() && m_hoveredColorId.has_value()) {
|
||||
auto flashingColor = m_startingColor.value();
|
||||
|
||||
const float flashProgress = std::min(1.0F, (1.0F + sinf(ImGui::GetTime() * 6)) / 2.0F);
|
||||
flashingColor.Value.x = std::lerp(flashingColor.Value.x / 2, 1.0F, flashProgress);
|
||||
@@ -65,12 +65,12 @@ namespace hex::plugin::builtin {
|
||||
flashingColor.Value.z = flashingColor.Value.z / 2;
|
||||
flashingColor.Value.w = 1.0F;
|
||||
|
||||
handler.setFunction(*this->m_hoveredColorId, flashingColor);
|
||||
handler.setFunction(*m_hoveredColorId, flashingColor);
|
||||
|
||||
if (!anyColorHovered) {
|
||||
handler.setFunction(this->m_hoveredColorId.value(), this->m_startingColor.value());
|
||||
this->m_startingColor.reset();
|
||||
this->m_hoveredColorId.reset();
|
||||
handler.setFunction(m_hoveredColorId.value(), m_startingColor.value());
|
||||
m_startingColor.reset();
|
||||
m_hoveredColorId.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -110,13 +110,13 @@ namespace hex::plugin::builtin {
|
||||
|
||||
// Draw export settings
|
||||
ImGuiExt::Header("hex.builtin.view.theme_manager.export"_lang);
|
||||
ImGuiExt::InputTextIcon("hex.builtin.view.theme_manager.export.name"_lang, ICON_VS_SYMBOL_KEY, this->m_themeName);
|
||||
ImGuiExt::InputTextIcon("hex.builtin.view.theme_manager.export.name"_lang, ICON_VS_SYMBOL_KEY, m_themeName);
|
||||
|
||||
// Draw the export buttons
|
||||
if (ImGui::Button("hex.builtin.view.theme_manager.save_theme"_lang, ImVec2(ImGui::GetContentRegionAvail().x, 0))) {
|
||||
fs::openFileBrowser(fs::DialogMode::Save, { { "ImHex Theme", "json" } }, [this](const std::fs::path &path){
|
||||
// Export the current theme as json
|
||||
auto json = ThemeManager::exportCurrentTheme(this->m_themeName);
|
||||
auto json = ThemeManager::exportCurrentTheme(m_themeName);
|
||||
|
||||
// Write the json to the file
|
||||
wolv::io::File outputFile(path, wolv::io::File::Mode::Create);
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
ViewTools::ViewTools() : View::Window("hex.builtin.view.tools.name") {
|
||||
this->m_dragStartIterator = ContentRegistry::Tools::impl::getEntries().end();
|
||||
m_dragStartIterator = ContentRegistry::Tools::impl::getEntries().end();
|
||||
}
|
||||
|
||||
void ViewTools::drawContent() {
|
||||
@@ -27,15 +27,15 @@ namespace hex::plugin::builtin {
|
||||
// Handle dragging the tool out of the main window
|
||||
|
||||
// If the user clicks on the header, start dragging the tool remember the iterator
|
||||
if (ImGui::IsMouseClicked(0) && ImGui::IsItemActivated() && this->m_dragStartIterator == tools.end())
|
||||
this->m_dragStartIterator = iter;
|
||||
if (ImGui::IsMouseClicked(0) && ImGui::IsItemActivated() && m_dragStartIterator == tools.end())
|
||||
m_dragStartIterator = iter;
|
||||
|
||||
// If the user released the mouse button, stop dragging the tool
|
||||
if (!ImGui::IsMouseDown(0))
|
||||
this->m_dragStartIterator = tools.end();
|
||||
m_dragStartIterator = tools.end();
|
||||
|
||||
// Detach the tool if the user dragged it out of the main window
|
||||
if (!ImGui::IsItemHovered() && this->m_dragStartIterator == iter) {
|
||||
if (!ImGui::IsItemHovered() && m_dragStartIterator == iter) {
|
||||
detached = true;
|
||||
}
|
||||
|
||||
@@ -62,8 +62,8 @@ namespace hex::plugin::builtin {
|
||||
function();
|
||||
|
||||
// Handle the first frame after the tool has been detached
|
||||
if (ImGui::IsWindowAppearing() && this->m_dragStartIterator == iter) {
|
||||
this->m_dragStartIterator = tools.end();
|
||||
if (ImGui::IsWindowAppearing() && m_dragStartIterator == iter) {
|
||||
m_dragStartIterator = tools.end();
|
||||
|
||||
// Attach the newly created window to the cursor, so it gets dragged around
|
||||
GImGui->MovingWindow = ImGui::GetCurrentWindowRead();
|
||||
|
||||
@@ -27,14 +27,14 @@ namespace hex::plugin::builtin {
|
||||
|
||||
if (ImGui::BeginTable("Tutorials", 1, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg, ImGui::GetContentRegionAvail())) {
|
||||
for (const auto &tutorial : tutorials | std::views::values) {
|
||||
if (this->m_selectedTutorial == nullptr)
|
||||
this->m_selectedTutorial = &tutorial;
|
||||
if (m_selectedTutorial == nullptr)
|
||||
m_selectedTutorial = &tutorial;
|
||||
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
if (ImGui::Selectable(Lang(tutorial.getUnlocalizedName()), this->m_selectedTutorial == &tutorial, ImGuiSelectableFlags_SpanAllColumns)) {
|
||||
this->m_selectedTutorial = &tutorial;
|
||||
if (ImGui::Selectable(Lang(tutorial.getUnlocalizedName()), m_selectedTutorial == &tutorial, ImGuiSelectableFlags_SpanAllColumns)) {
|
||||
m_selectedTutorial = &tutorial;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,16 +43,16 @@ namespace hex::plugin::builtin {
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
if (this->m_selectedTutorial != nullptr) {
|
||||
if (m_selectedTutorial != nullptr) {
|
||||
ImGuiExt::BeginSubWindow("hex.builtin.view.tutorials.description"_lang, ImGui::GetContentRegionAvail() - ImVec2(0, ImGui::GetTextLineHeightWithSpacing() + ImGui::GetStyle().ItemSpacing.y * 2));
|
||||
{
|
||||
ImGuiExt::TextFormattedWrapped(Lang(this->m_selectedTutorial->getUnlocalizedDescription()));
|
||||
ImGuiExt::TextFormattedWrapped(Lang(m_selectedTutorial->getUnlocalizedDescription()));
|
||||
}
|
||||
ImGuiExt::EndSubWindow();
|
||||
|
||||
ImGui::BeginDisabled(currTutorial != tutorials.end());
|
||||
if (ImGuiExt::DimmedButton("hex.builtin.view.tutorials.start"_lang, ImVec2(ImGui::GetContentRegionAvail().x, 0))) {
|
||||
TutorialManager::startTutorial(this->m_selectedTutorial->getUnlocalizedName());
|
||||
TutorialManager::startTutorial(m_selectedTutorial->getUnlocalizedName());
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ namespace hex::plugin::builtin {
|
||||
if (!rules.is_array())
|
||||
return false;
|
||||
|
||||
this->m_matches.get(provider).clear();
|
||||
m_matches.get(provider).clear();
|
||||
|
||||
for (auto &rule : rules) {
|
||||
if (!rule.contains("name") || !rule.contains("path"))
|
||||
@@ -70,7 +70,7 @@ namespace hex::plugin::builtin {
|
||||
if (!name.is_string() || !path.is_string())
|
||||
return false;
|
||||
|
||||
this->m_rules.get(provider).emplace_back(std::fs::path(name.get<std::string>()), std::fs::path(path.get<std::string>()));
|
||||
m_rules.get(provider).emplace_back(std::fs::path(name.get<std::string>()), std::fs::path(path.get<std::string>()));
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -80,7 +80,7 @@ namespace hex::plugin::builtin {
|
||||
|
||||
data["rules"] = nlohmann::json::array();
|
||||
|
||||
for (auto &[name, path] : this->m_rules.get(provider)) {
|
||||
for (auto &[name, path] : m_rules.get(provider)) {
|
||||
data["rules"].push_back({
|
||||
{ "name", wolv::util::toUTF8String(name) },
|
||||
{ "path", wolv::util::toUTF8String(path) }
|
||||
@@ -102,10 +102,10 @@ namespace hex::plugin::builtin {
|
||||
ImGuiExt::Header("hex.builtin.view.yara.header.rules"_lang, true);
|
||||
|
||||
if (ImGui::BeginListBox("##rules", ImVec2(-FLT_MIN, ImGui::GetTextLineHeightWithSpacing() * 5))) {
|
||||
for (u32 i = 0; i < this->m_rules->size(); i++) {
|
||||
const bool selected = (this->m_selectedRule == i);
|
||||
if (ImGui::Selectable(wolv::util::toUTF8String((*this->m_rules)[i].first).c_str(), selected)) {
|
||||
this->m_selectedRule = i;
|
||||
for (u32 i = 0; i < m_rules->size(); i++) {
|
||||
const bool selected = (m_selectedRule == i);
|
||||
if (ImGui::Selectable(wolv::util::toUTF8String((*m_rules)[i].first).c_str(), selected)) {
|
||||
m_selectedRule = i;
|
||||
}
|
||||
}
|
||||
ImGui::EndListBox();
|
||||
@@ -126,15 +126,15 @@ namespace hex::plugin::builtin {
|
||||
|
||||
PopupFileChooser::open(basePaths, paths, std::vector<hex::fs::ItemFilter>{ { "Yara File", "yara" }, { "Yara File", "yar" } }, true,
|
||||
[&](const auto &path) {
|
||||
this->m_rules->push_back({ path.filename(), path });
|
||||
m_rules->push_back({ path.filename(), path });
|
||||
});
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
if (ImGuiExt::IconButton(ICON_VS_REMOVE, ImGui::GetStyleColorVec4(ImGuiCol_Text))) {
|
||||
if (this->m_selectedRule < this->m_rules->size()) {
|
||||
this->m_rules->erase(this->m_rules->begin() + this->m_selectedRule);
|
||||
this->m_selectedRule = std::min(this->m_selectedRule, u32(this->m_rules->size() - 1));
|
||||
if (m_selectedRule < m_rules->size()) {
|
||||
m_rules->erase(m_rules->begin() + m_selectedRule);
|
||||
m_selectedRule = std::min(m_selectedRule, u32(m_rules->size() - 1));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,7 +142,7 @@ namespace hex::plugin::builtin {
|
||||
if (ImGui::Button("hex.builtin.view.yara.match"_lang)) this->applyRules();
|
||||
ImGui::SameLine();
|
||||
|
||||
if (this->m_matcherTask.isRunning()) {
|
||||
if (m_matcherTask.isRunning()) {
|
||||
ImGui::SameLine();
|
||||
ImGuiExt::TextSpinner("hex.builtin.view.yara.matching"_lang);
|
||||
}
|
||||
@@ -163,13 +163,13 @@ namespace hex::plugin::builtin {
|
||||
ImGui::TableHeadersRow();
|
||||
|
||||
auto sortSpecs = ImGui::TableGetSortSpecs();
|
||||
if (!this->m_matches->empty() && (sortSpecs->SpecsDirty || this->m_sortedMatches->empty())) {
|
||||
this->m_sortedMatches->clear();
|
||||
std::transform(this->m_matches->begin(), this->m_matches->end(), std::back_inserter(*this->m_sortedMatches), [](auto &match) {
|
||||
if (!m_matches->empty() && (sortSpecs->SpecsDirty || m_sortedMatches->empty())) {
|
||||
m_sortedMatches->clear();
|
||||
std::transform(m_matches->begin(), m_matches->end(), std::back_inserter(*m_sortedMatches), [](auto &match) {
|
||||
return &match;
|
||||
});
|
||||
|
||||
std::sort(this->m_sortedMatches->begin(), this->m_sortedMatches->end(), [&sortSpecs](const YaraMatch *left, const YaraMatch *right) -> bool {
|
||||
std::sort(m_sortedMatches->begin(), m_sortedMatches->end(), [&sortSpecs](const YaraMatch *left, const YaraMatch *right) -> bool {
|
||||
if (sortSpecs->Specs->ColumnUserID == ImGui::GetID("identifier"))
|
||||
return left->identifier < right->identifier;
|
||||
else if (sortSpecs->Specs->ColumnUserID == ImGui::GetID("variable"))
|
||||
@@ -183,18 +183,18 @@ namespace hex::plugin::builtin {
|
||||
});
|
||||
|
||||
if (sortSpecs->Specs->SortDirection == ImGuiSortDirection_Descending)
|
||||
std::reverse(this->m_sortedMatches->begin(), this->m_sortedMatches->end());
|
||||
std::reverse(m_sortedMatches->begin(), m_sortedMatches->end());
|
||||
|
||||
sortSpecs->SpecsDirty = false;
|
||||
}
|
||||
|
||||
if (!this->m_matcherTask.isRunning()) {
|
||||
if (!m_matcherTask.isRunning()) {
|
||||
ImGuiListClipper clipper;
|
||||
clipper.Begin(this->m_sortedMatches->size());
|
||||
clipper.Begin(m_sortedMatches->size());
|
||||
|
||||
while (clipper.Step()) {
|
||||
for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) {
|
||||
auto &[identifier, variableName, address, size, wholeDataMatch, highlightId, tooltipId] = *(*this->m_sortedMatches)[i];
|
||||
auto &[identifier, variableName, address, size, wholeDataMatch, highlightId, tooltipId] = *(*m_sortedMatches)[i];
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::PushID(i);
|
||||
@@ -232,10 +232,10 @@ namespace hex::plugin::builtin {
|
||||
if (ImGui::BeginChild("##console", consoleSize, true, ImGuiWindowFlags_AlwaysVerticalScrollbar | ImGuiWindowFlags_HorizontalScrollbar)) {
|
||||
ImGuiListClipper clipper;
|
||||
|
||||
clipper.Begin(this->m_consoleMessages.size());
|
||||
clipper.Begin(m_consoleMessages.size());
|
||||
while (clipper.Step())
|
||||
for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) {
|
||||
const auto &message = this->m_consoleMessages[i];
|
||||
const auto &message = m_consoleMessages[i];
|
||||
|
||||
if (ImGui::Selectable(message.c_str()))
|
||||
ImGui::SetClipboardText(message.c_str());
|
||||
@@ -245,19 +245,19 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
void ViewYara::clearResult() {
|
||||
for (const auto &match : *this->m_matches) {
|
||||
for (const auto &match : *m_matches) {
|
||||
ImHexApi::HexEditor::removeBackgroundHighlight(match.highlightId);
|
||||
ImHexApi::HexEditor::removeTooltip(match.tooltipId);
|
||||
}
|
||||
|
||||
this->m_matches->clear();
|
||||
this->m_consoleMessages.clear();
|
||||
m_matches->clear();
|
||||
m_consoleMessages.clear();
|
||||
}
|
||||
|
||||
void ViewYara::applyRules() {
|
||||
this->clearResult();
|
||||
|
||||
this->m_matcherTask = TaskManager::createTask("hex.builtin.view.yara.matching", 0, [this](auto &task) {
|
||||
m_matcherTask = TaskManager::createTask("hex.builtin.view.yara.matching", 0, [this](auto &task) {
|
||||
if (!ImHexApi::Provider::isValid()) return;
|
||||
|
||||
struct ResultContext {
|
||||
@@ -269,7 +269,7 @@ namespace hex::plugin::builtin {
|
||||
ResultContext resultContext;
|
||||
resultContext.task = &task;
|
||||
|
||||
for (const auto &[fileName, filePath] : *this->m_rules) {
|
||||
for (const auto &[fileName, filePath] : *m_rules) {
|
||||
YR_COMPILER *compiler = nullptr;
|
||||
yr_compiler_create(&compiler);
|
||||
ON_SCOPE_EXIT {
|
||||
@@ -300,7 +300,7 @@ namespace hex::plugin::builtin {
|
||||
currFilePath.data()
|
||||
);
|
||||
|
||||
wolv::io::File file((*this->m_rules)[this->m_selectedRule].second, wolv::io::File::Mode::Read);
|
||||
wolv::io::File file((*m_rules)[m_selectedRule].second, wolv::io::File::Mode::Read);
|
||||
if (!file.isValid()) return;
|
||||
|
||||
if (yr_compiler_add_file(compiler, file.getHandle(), nullptr, nullptr) != 0) {
|
||||
@@ -310,7 +310,7 @@ namespace hex::plugin::builtin {
|
||||
TaskManager::doLater([this, errorMessage = wolv::util::trim(errorMessage)] {
|
||||
this->clearResult();
|
||||
|
||||
this->m_consoleMessages.push_back(hex::format("hex.builtin.view.yara.error"_lang, errorMessage));
|
||||
m_consoleMessages.push_back(hex::format("hex.builtin.view.yara.error"_lang, errorMessage));
|
||||
});
|
||||
|
||||
return;
|
||||
@@ -417,22 +417,22 @@ namespace hex::plugin::builtin {
|
||||
|
||||
}
|
||||
TaskManager::doLater([this, resultContext] {
|
||||
for (const auto &match : *this->m_matches) {
|
||||
for (const auto &match : *m_matches) {
|
||||
ImHexApi::HexEditor::removeBackgroundHighlight(match.highlightId);
|
||||
ImHexApi::HexEditor::removeTooltip(match.tooltipId);
|
||||
}
|
||||
|
||||
this->m_consoleMessages = resultContext.consoleMessages;
|
||||
m_consoleMessages = resultContext.consoleMessages;
|
||||
|
||||
std::move(resultContext.newMatches.begin(), resultContext.newMatches.end(), std::back_inserter(*this->m_matches));
|
||||
std::move(resultContext.newMatches.begin(), resultContext.newMatches.end(), std::back_inserter(*m_matches));
|
||||
|
||||
auto uniques = std::set(this->m_matches->begin(), this->m_matches->end(), [](const auto &l, const auto &r) {
|
||||
auto uniques = std::set(m_matches->begin(), m_matches->end(), [](const auto &l, const auto &r) {
|
||||
return std::tie(l.address, l.size, l.wholeDataMatch, l.identifier, l.variable) <
|
||||
std::tie(r.address, r.size, r.wholeDataMatch, r.identifier, r.variable);
|
||||
});
|
||||
|
||||
this->m_matches->clear();
|
||||
std::move(uniques.begin(), uniques.end(), std::back_inserter(*this->m_matches));
|
||||
m_matches->clear();
|
||||
std::move(uniques.begin(), uniques.end(), std::back_inserter(*m_matches));
|
||||
|
||||
constexpr static color_t YaraColor = 0x70B4771F;
|
||||
for (auto &match : uniques) {
|
||||
|
||||
@@ -55,31 +55,31 @@ namespace hex::plugin::builtin {
|
||||
m_restoreCallback(restoreCallback),
|
||||
m_deleteCallback(deleteCallback) {
|
||||
|
||||
this->m_reportError = ContentRegistry::Settings::read("hex.builtin.setting.general", "hex.builtin.setting.general.upload_crash_logs", true);
|
||||
m_reportError = ContentRegistry::Settings::read("hex.builtin.setting.general", "hex.builtin.setting.general.upload_crash_logs", true);
|
||||
}
|
||||
|
||||
void drawContent() override {
|
||||
ImGui::TextUnformatted("hex.builtin.popup.safety_backup.desc"_lang);
|
||||
if (!this->m_logFilePath.empty()) {
|
||||
if (!m_logFilePath.empty()) {
|
||||
ImGui::NewLine();
|
||||
ImGui::TextUnformatted("hex.builtin.popup.safety_backup.log_file"_lang);
|
||||
ImGui::SameLine(0, 2_scaled);
|
||||
if (ImGuiExt::Hyperlink(this->m_logFilePath.filename().string().c_str())) {
|
||||
fs::openFolderWithSelectionExternal(this->m_logFilePath);
|
||||
if (ImGuiExt::Hyperlink(m_logFilePath.filename().string().c_str())) {
|
||||
fs::openFolderWithSelectionExternal(m_logFilePath);
|
||||
}
|
||||
|
||||
ImGui::Checkbox("hex.builtin.popup.safety_backup.report_error"_lang, &this->m_reportError);
|
||||
ImGui::Checkbox("hex.builtin.popup.safety_backup.report_error"_lang, &m_reportError);
|
||||
ImGui::NewLine();
|
||||
}
|
||||
|
||||
auto width = ImGui::GetWindowWidth();
|
||||
ImGui::SetCursorPosX(width / 9);
|
||||
if (ImGui::Button("hex.builtin.popup.safety_backup.restore"_lang, ImVec2(width / 3, 0))) {
|
||||
this->m_restoreCallback();
|
||||
this->m_deleteCallback();
|
||||
m_restoreCallback();
|
||||
m_deleteCallback();
|
||||
|
||||
if (this->m_reportError) {
|
||||
wolv::io::File logFile(this->m_logFilePath, wolv::io::File::Mode::Read);
|
||||
if (m_reportError) {
|
||||
wolv::io::File logFile(m_logFilePath, wolv::io::File::Mode::Read);
|
||||
if (logFile.isValid()) {
|
||||
// Read current log file data
|
||||
auto data = logFile.readString();
|
||||
@@ -94,21 +94,21 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
}
|
||||
|
||||
TaskManager::createBackgroundTask("Upload Crash report", [path = this->m_logFilePath, data](auto&){
|
||||
TaskManager::createBackgroundTask("Upload Crash report", [path = m_logFilePath, data](auto&){
|
||||
HttpRequest request("POST", ImHexApiURL + std::string("/crash_upload"));
|
||||
request.uploadFile(std::vector<u8>(data.begin(), data.end()), "file", path.filename()).wait();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
ContentRegistry::Settings::write("hex.builtin.setting.general", "hex.builtin.setting.general.upload_crash_logs", this->m_reportError);
|
||||
ContentRegistry::Settings::write("hex.builtin.setting.general", "hex.builtin.setting.general.upload_crash_logs", m_reportError);
|
||||
|
||||
this->close();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ImGui::SetCursorPosX(width / 9 * 5);
|
||||
if (ImGui::Button("hex.builtin.popup.safety_backup.delete"_lang, ImVec2(width / 3, 0)) || ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Escape))) {
|
||||
this->m_deleteCallback();
|
||||
m_deleteCallback();
|
||||
|
||||
this->close();
|
||||
}
|
||||
|
||||
@@ -70,14 +70,14 @@ namespace hex::plugin::builtin::ui {
|
||||
/* Hex Editor */
|
||||
|
||||
HexEditor::HexEditor(prv::Provider *provider) : m_provider(provider) {
|
||||
this->m_currDataVisualizer = ContentRegistry::HexEditor::getVisualizerByName("hex.builtin.visualizer.hexadecimal.8bit");
|
||||
this->m_bytesPerRow = ContentRegistry::Settings::read("hex.builtin.setting.hex_editor", "hex.builtin.setting.hex_editor.bytes_per_row", this->m_bytesPerRow);
|
||||
m_currDataVisualizer = ContentRegistry::HexEditor::getVisualizerByName("hex.builtin.visualizer.hexadecimal.8bit");
|
||||
m_bytesPerRow = ContentRegistry::Settings::read("hex.builtin.setting.hex_editor", "hex.builtin.setting.hex_editor.bytes_per_row", m_bytesPerRow);
|
||||
|
||||
EventSettingsChanged::subscribe(this, [this] {
|
||||
this->m_selectionColor = ContentRegistry::Settings::read("hex.builtin.setting.hex_editor", "hex.builtin.setting.hex_editor.highlight_color", 0x60C08080);
|
||||
this->m_syncScrolling = ContentRegistry::Settings::read("hex.builtin.setting.hex_editor", "hex.builtin.setting.hex_editor.sync_scrolling", false);
|
||||
this->m_byteCellPadding = ContentRegistry::Settings::read("hex.builtin.setting.hex_editor", "hex.builtin.setting.hex_editor.byte_padding", false);
|
||||
this->m_characterCellPadding = ContentRegistry::Settings::read("hex.builtin.setting.hex_editor", "hex.builtin.setting.hex_editor.char_padding", false);
|
||||
m_selectionColor = ContentRegistry::Settings::read("hex.builtin.setting.hex_editor", "hex.builtin.setting.hex_editor.highlight_color", 0x60C08080);
|
||||
m_syncScrolling = ContentRegistry::Settings::read("hex.builtin.setting.hex_editor", "hex.builtin.setting.hex_editor.sync_scrolling", false);
|
||||
m_byteCellPadding = ContentRegistry::Settings::read("hex.builtin.setting.hex_editor", "hex.builtin.setting.hex_editor.byte_padding", false);
|
||||
m_characterCellPadding = ContentRegistry::Settings::read("hex.builtin.setting.hex_editor", "hex.builtin.setting.hex_editor.char_padding", false);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -99,14 +99,14 @@ namespace hex::plugin::builtin::ui {
|
||||
|
||||
if (byteAddress >= selection.getStartAddress() && byteAddress <= selection.getEndAddress()) {
|
||||
if (color.has_value())
|
||||
color = (ImAlphaBlendColors(color.value(), this->m_selectionColor)) & 0x00FFFFFF;
|
||||
color = (ImAlphaBlendColors(color.value(), m_selectionColor)) & 0x00FFFFFF;
|
||||
else
|
||||
color = this->m_selectionColor;
|
||||
color = m_selectionColor;
|
||||
}
|
||||
}
|
||||
|
||||
if (color.has_value())
|
||||
color = (*color & 0x00FFFFFF) | (this->m_selectionColor & 0xFF000000);
|
||||
color = (*color & 0x00FFFFFF) | (m_selectionColor & 0xFF000000);
|
||||
|
||||
return color;
|
||||
}
|
||||
@@ -152,7 +152,7 @@ namespace hex::plugin::builtin::ui {
|
||||
void HexEditor::drawTooltip(u64 address, const u8 *data, size_t size) const {
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, scaled(ImVec2(5, 5)));
|
||||
|
||||
this->m_tooltipCallback(address, data, size);
|
||||
m_tooltipCallback(address, data, size);
|
||||
|
||||
ImGui::PopStyleVar();
|
||||
}
|
||||
@@ -160,39 +160,39 @@ namespace hex::plugin::builtin::ui {
|
||||
void HexEditor::drawCell(u64 address, const u8 *data, size_t size, bool hovered, CellType cellType) {
|
||||
static DataVisualizerAscii asciiVisualizer;
|
||||
|
||||
if (this->m_shouldUpdateEditingValue && address == this->m_editingAddress) {
|
||||
this->m_shouldUpdateEditingValue = false;
|
||||
if (m_shouldUpdateEditingValue && address == m_editingAddress) {
|
||||
m_shouldUpdateEditingValue = false;
|
||||
|
||||
if (this->m_editingBytes.size() < size) {
|
||||
this->m_editingBytes.resize(size);
|
||||
if (m_editingBytes.size() < size) {
|
||||
m_editingBytes.resize(size);
|
||||
}
|
||||
|
||||
std::memcpy(this->m_editingBytes.data(), data, size);
|
||||
std::memcpy(m_editingBytes.data(), data, size);
|
||||
}
|
||||
|
||||
if (this->m_editingAddress != address || this->m_editingCellType != cellType) {
|
||||
if (m_editingAddress != address || m_editingCellType != cellType) {
|
||||
if (cellType == CellType::Hex) {
|
||||
std::vector<u8> buffer(size);
|
||||
std::memcpy(buffer.data(), data, size);
|
||||
|
||||
if (this->m_dataVisualizerEndianness != std::endian::native)
|
||||
if (m_dataVisualizerEndianness != std::endian::native)
|
||||
std::reverse(buffer.begin(), buffer.end());
|
||||
|
||||
this->m_currDataVisualizer->draw(address, buffer.data(), buffer.size(), this->m_upperCaseHex);
|
||||
m_currDataVisualizer->draw(address, buffer.data(), buffer.size(), m_upperCaseHex);
|
||||
} else {
|
||||
asciiVisualizer.draw(address, data, size, this->m_upperCaseHex);
|
||||
asciiVisualizer.draw(address, data, size, m_upperCaseHex);
|
||||
}
|
||||
|
||||
if (hovered && this->m_provider->isWritable()) {
|
||||
if (hovered && m_provider->isWritable()) {
|
||||
// Enter editing mode when double-clicking a cell
|
||||
if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) {
|
||||
this->m_editingAddress = address;
|
||||
this->m_shouldModifyValue = false;
|
||||
this->m_enteredEditingMode = true;
|
||||
m_editingAddress = address;
|
||||
m_shouldModifyValue = false;
|
||||
m_enteredEditingMode = true;
|
||||
|
||||
this->m_editingBytes.resize(size);
|
||||
std::memcpy(this->m_editingBytes.data(), data, size);
|
||||
this->m_editingCellType = cellType;
|
||||
m_editingBytes.resize(size);
|
||||
std::memcpy(m_editingBytes.data(), data, size);
|
||||
m_editingCellType = cellType;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -201,64 +201,64 @@ namespace hex::plugin::builtin::ui {
|
||||
ImGui::SetNextFrameWantCaptureKeyboard(true);
|
||||
|
||||
bool shouldExitEditingMode = true;
|
||||
if (cellType == this->m_editingCellType && cellType == CellType::Hex) {
|
||||
std::vector<u8> buffer = this->m_editingBytes;
|
||||
if (cellType == m_editingCellType && cellType == CellType::Hex) {
|
||||
std::vector<u8> buffer = m_editingBytes;
|
||||
|
||||
if (this->m_dataVisualizerEndianness != std::endian::native)
|
||||
if (m_dataVisualizerEndianness != std::endian::native)
|
||||
std::reverse(buffer.begin(), buffer.end());
|
||||
|
||||
shouldExitEditingMode = this->m_currDataVisualizer->drawEditing(*this->m_editingAddress, buffer.data(), buffer.size(), this->m_upperCaseHex, this->m_enteredEditingMode);
|
||||
shouldExitEditingMode = m_currDataVisualizer->drawEditing(*m_editingAddress, buffer.data(), buffer.size(), m_upperCaseHex, m_enteredEditingMode);
|
||||
|
||||
if (this->m_dataVisualizerEndianness != std::endian::native)
|
||||
if (m_dataVisualizerEndianness != std::endian::native)
|
||||
std::reverse(buffer.begin(), buffer.end());
|
||||
|
||||
this->m_editingBytes = buffer;
|
||||
} else if (cellType == this->m_editingCellType && cellType == CellType::ASCII) {
|
||||
shouldExitEditingMode = asciiVisualizer.drawEditing(*this->m_editingAddress, this->m_editingBytes.data(), this->m_editingBytes.size(), this->m_upperCaseHex, this->m_enteredEditingMode);
|
||||
m_editingBytes = buffer;
|
||||
} else if (cellType == m_editingCellType && cellType == CellType::ASCII) {
|
||||
shouldExitEditingMode = asciiVisualizer.drawEditing(*m_editingAddress, m_editingBytes.data(), m_editingBytes.size(), m_upperCaseHex, m_enteredEditingMode);
|
||||
}
|
||||
|
||||
if (shouldExitEditingMode || this->m_shouldModifyValue) {
|
||||
if (shouldExitEditingMode || m_shouldModifyValue) {
|
||||
{
|
||||
std::vector<u8> oldData(this->m_editingBytes.size());
|
||||
this->m_provider->read(*this->m_editingAddress, oldData.data(), oldData.size());
|
||||
std::vector<u8> oldData(m_editingBytes.size());
|
||||
m_provider->read(*m_editingAddress, oldData.data(), oldData.size());
|
||||
|
||||
size_t writtenBytes = 0;
|
||||
for (size_t i = 0; i < this->m_editingBytes.size(); i += 1) {
|
||||
if (this->m_editingBytes[i] != oldData[i]) {
|
||||
this->m_provider->write(*this->m_editingAddress, &this->m_editingBytes[i], 1);
|
||||
for (size_t i = 0; i < m_editingBytes.size(); i += 1) {
|
||||
if (m_editingBytes[i] != oldData[i]) {
|
||||
m_provider->write(*m_editingAddress, &m_editingBytes[i], 1);
|
||||
writtenBytes += 1;
|
||||
}
|
||||
}
|
||||
|
||||
this->m_provider->getUndoStack().groupOperations(writtenBytes, "hex.builtin.undo_operation.modification");
|
||||
m_provider->getUndoStack().groupOperations(writtenBytes, "hex.builtin.undo_operation.modification");
|
||||
}
|
||||
|
||||
|
||||
if (!this->m_selectionChanged && !ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseClicked(ImGuiMouseButton_Left) && !ImGui::IsKeyDown(ImGuiKey_Escape)) {
|
||||
auto nextEditingAddress = *this->m_editingAddress + this->m_currDataVisualizer->getBytesPerCell();
|
||||
if (!m_selectionChanged && !ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseClicked(ImGuiMouseButton_Left) && !ImGui::IsKeyDown(ImGuiKey_Escape)) {
|
||||
auto nextEditingAddress = *m_editingAddress + m_currDataVisualizer->getBytesPerCell();
|
||||
this->setSelection(nextEditingAddress, nextEditingAddress);
|
||||
|
||||
if (nextEditingAddress >= this->m_provider->getBaseAddress() + this->m_provider->getCurrentPageAddress() + this->m_provider->getSize())
|
||||
this->m_editingAddress = std::nullopt;
|
||||
if (nextEditingAddress >= m_provider->getBaseAddress() + m_provider->getCurrentPageAddress() + m_provider->getSize())
|
||||
m_editingAddress = std::nullopt;
|
||||
else
|
||||
this->m_editingAddress = nextEditingAddress;
|
||||
m_editingAddress = nextEditingAddress;
|
||||
} else {
|
||||
this->m_editingAddress = std::nullopt;
|
||||
m_editingAddress = std::nullopt;
|
||||
}
|
||||
|
||||
this->m_shouldModifyValue = false;
|
||||
this->m_shouldUpdateEditingValue = true;
|
||||
m_shouldModifyValue = false;
|
||||
m_shouldUpdateEditingValue = true;
|
||||
}
|
||||
|
||||
if (ImGui::IsMouseClicked(ImGuiMouseButton_Left) && !hovered && !this->m_enteredEditingMode) {
|
||||
this->m_editingAddress = std::nullopt;
|
||||
this->m_shouldModifyValue = false;
|
||||
if (ImGui::IsMouseClicked(ImGuiMouseButton_Left) && !hovered && !m_enteredEditingMode) {
|
||||
m_editingAddress = std::nullopt;
|
||||
m_shouldModifyValue = false;
|
||||
}
|
||||
|
||||
if (!this->m_editingAddress.has_value())
|
||||
this->m_editingCellType = CellType::None;
|
||||
if (!m_editingAddress.has_value())
|
||||
m_editingCellType = CellType::None;
|
||||
|
||||
this->m_enteredEditingMode = false;
|
||||
m_enteredEditingMode = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -280,15 +280,15 @@ namespace hex::plugin::builtin::ui {
|
||||
drawList->AddLine(cellPos, cellPos + ImVec2(0, cellSize.y), ImColor(SelectionFrameColor), 1_scaled);
|
||||
|
||||
// Draw vertical line at the right of the last byte and the end of the line
|
||||
if (x == u16((this->m_bytesPerRow / bytesPerCell) - 1) || (byteAddress + bytesPerCell) > selection.getEndAddress())
|
||||
if (x == u16((m_bytesPerRow / bytesPerCell) - 1) || (byteAddress + bytesPerCell) > selection.getEndAddress())
|
||||
drawList->AddLine(cellPos + ImVec2(cellSize.x, -1), cellPos + cellSize, ImColor(SelectionFrameColor), 1_scaled);
|
||||
|
||||
// Draw horizontal line at the top of the bytes
|
||||
if (y == 0 || (byteAddress - this->m_bytesPerRow) < selection.getStartAddress())
|
||||
if (y == 0 || (byteAddress - m_bytesPerRow) < selection.getStartAddress())
|
||||
drawList->AddLine(cellPos, cellPos + ImVec2(cellSize.x + 1, 0), ImColor(SelectionFrameColor), 1_scaled);
|
||||
|
||||
// Draw horizontal line at the bottom of the bytes
|
||||
if ((byteAddress + this->m_bytesPerRow) > selection.getEndAddress())
|
||||
if ((byteAddress + m_bytesPerRow) > selection.getEndAddress())
|
||||
drawList->AddLine(cellPos + ImVec2(0, cellSize.y), cellPos + cellSize + ImVec2(1, 0), ImColor(SelectionFrameColor), 1_scaled);
|
||||
}
|
||||
|
||||
@@ -296,19 +296,19 @@ namespace hex::plugin::builtin::ui {
|
||||
const float SeparatorColumWidth = 6_scaled;
|
||||
const auto CharacterSize = ImGui::CalcTextSize("0");
|
||||
|
||||
const auto bytesPerCell = this->m_currDataVisualizer->getBytesPerCell();
|
||||
const u16 columnCount = this->m_bytesPerRow / bytesPerCell;
|
||||
const auto bytesPerCell = m_currDataVisualizer->getBytesPerCell();
|
||||
const u16 columnCount = m_bytesPerRow / bytesPerCell;
|
||||
auto byteColumnCount = 2 + columnCount + getByteColumnSeparatorCount(columnCount) + 2 + 2;
|
||||
|
||||
if (byteColumnCount >= IMGUI_TABLE_MAX_COLUMNS) {
|
||||
this->m_bytesPerRow = 64;
|
||||
ContentRegistry::Settings::write("hex.builtin.setting.hex_editor", "hex.builtin.setting.hex_editor.bytes_per_row", this->m_bytesPerRow);
|
||||
m_bytesPerRow = 64;
|
||||
ContentRegistry::Settings::write("hex.builtin.setting.hex_editor", "hex.builtin.setting.hex_editor.bytes_per_row", m_bytesPerRow);
|
||||
return;
|
||||
}
|
||||
|
||||
const auto selection = getSelection();
|
||||
|
||||
if (this->m_provider == nullptr || this->m_provider->getActualSize() == 0) {
|
||||
if (m_provider == nullptr || m_provider->getActualSize() == 0) {
|
||||
ImGuiExt::TextFormattedCentered("{}", "hex.builtin.hex_editor.no_bytes"_lang);
|
||||
}
|
||||
|
||||
@@ -326,14 +326,14 @@ namespace hex::plugin::builtin::ui {
|
||||
if (isColumnSeparatorColumn(i, columnCount))
|
||||
ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, SeparatorColumWidth);
|
||||
|
||||
ImGui::TableSetupColumn(hex::format(this->m_upperCaseHex ? "{:0{}X}" : "{:0{}x}", i * bytesPerCell, this->m_currDataVisualizer->getMaxCharsPerCell()).c_str(), ImGuiTableColumnFlags_WidthFixed, CharacterSize.x * this->m_currDataVisualizer->getMaxCharsPerCell() + (6 + this->m_byteCellPadding) * 1_scaled);
|
||||
ImGui::TableSetupColumn(hex::format(m_upperCaseHex ? "{:0{}X}" : "{:0{}x}", i * bytesPerCell, m_currDataVisualizer->getMaxCharsPerCell()).c_str(), ImGuiTableColumnFlags_WidthFixed, CharacterSize.x * m_currDataVisualizer->getMaxCharsPerCell() + (6 + m_byteCellPadding) * 1_scaled);
|
||||
}
|
||||
|
||||
// ASCII column
|
||||
ImGui::TableSetupColumn("");
|
||||
|
||||
if (this->m_showAscii) {
|
||||
ImGui::TableSetupColumn("hex.builtin.common.encoding.ascii"_lang, ImGuiTableColumnFlags_WidthFixed, (CharacterSize.x + this->m_characterCellPadding * 1_scaled) * this->m_bytesPerRow);
|
||||
if (m_showAscii) {
|
||||
ImGui::TableSetupColumn("hex.builtin.common.encoding.ascii"_lang, ImGuiTableColumnFlags_WidthFixed, (CharacterSize.x + m_characterCellPadding * 1_scaled) * m_bytesPerRow);
|
||||
}
|
||||
else
|
||||
ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, 0);
|
||||
@@ -341,8 +341,8 @@ namespace hex::plugin::builtin::ui {
|
||||
ImGui::TableSetupColumn("");
|
||||
// Custom encoding column
|
||||
{
|
||||
if (this->m_currCustomEncoding.has_value() && this->m_showCustomEncoding) {
|
||||
ImGui::TableSetupColumn(this->m_currCustomEncoding->getName().c_str(), ImGuiTableColumnFlags_WidthStretch);
|
||||
if (m_currCustomEncoding.has_value() && m_showCustomEncoding) {
|
||||
ImGui::TableSetupColumn(m_currCustomEncoding->getName().c_str(), ImGuiTableColumnFlags_WidthStretch);
|
||||
} else {
|
||||
ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, 0);
|
||||
}
|
||||
@@ -358,11 +358,11 @@ namespace hex::plugin::builtin::ui {
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
if (this->m_provider != nullptr && this->m_provider->isReadable()) {
|
||||
if (m_provider != nullptr && m_provider->isReadable()) {
|
||||
const auto isCurrRegionValid = [this](u64 address) {
|
||||
auto &[currRegion, currRegionValid] = this->m_currValidRegion;
|
||||
auto &[currRegion, currRegionValid] = m_currValidRegion;
|
||||
if (!Region{ address, 1 }.isWithin(currRegion)) {
|
||||
this->m_currValidRegion = this->m_provider->getRegionValidity(address);
|
||||
m_currValidRegion = m_provider->getRegionValidity(address);
|
||||
}
|
||||
|
||||
return currRegionValid;
|
||||
@@ -370,7 +370,7 @@ namespace hex::plugin::builtin::ui {
|
||||
|
||||
ImGuiListClipper clipper;
|
||||
|
||||
u64 numRows = std::ceil(this->m_provider->getSize() / static_cast<long double>(this->m_bytesPerRow));
|
||||
u64 numRows = std::ceil(m_provider->getSize() / static_cast<long double>(m_bytesPerRow));
|
||||
if (numRows == 0) {
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
@@ -379,34 +379,34 @@ namespace hex::plugin::builtin::ui {
|
||||
|
||||
clipper.Begin(numRows + size.y / CharacterSize.y - 3, CharacterSize.y);
|
||||
while (clipper.Step()) {
|
||||
this->m_visibleRowCount = clipper.DisplayEnd - clipper.DisplayStart;
|
||||
m_visibleRowCount = clipper.DisplayEnd - clipper.DisplayStart;
|
||||
|
||||
// Loop over rows
|
||||
for (u64 y = u64(clipper.DisplayStart); y < std::min(numRows, u64(clipper.DisplayEnd)); y++) {
|
||||
// Draw address column
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGuiExt::TextFormatted(this->m_upperCaseHex ? "{:08X}: " : "{:08x}: ", y * this->m_bytesPerRow + this->m_provider->getBaseAddress() + this->m_provider->getCurrentPageAddress());
|
||||
ImGuiExt::TextFormatted(m_upperCaseHex ? "{:08X}: " : "{:08x}: ", y * m_bytesPerRow + m_provider->getBaseAddress() + m_provider->getCurrentPageAddress());
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
const u8 validBytes = std::min<u64>(this->m_bytesPerRow, this->m_provider->getSize() - y * this->m_bytesPerRow);
|
||||
const u8 validBytes = std::min<u64>(m_bytesPerRow, m_provider->getSize() - y * m_bytesPerRow);
|
||||
|
||||
std::vector<u8> bytes(this->m_bytesPerRow, 0x00);
|
||||
this->m_provider->read(y * this->m_bytesPerRow + this->m_provider->getBaseAddress() + this->m_provider->getCurrentPageAddress(), bytes.data(), validBytes);
|
||||
std::vector<u8> bytes(m_bytesPerRow, 0x00);
|
||||
m_provider->read(y * m_bytesPerRow + m_provider->getBaseAddress() + m_provider->getCurrentPageAddress(), bytes.data(), validBytes);
|
||||
|
||||
std::vector<std::tuple<std::optional<color_t>, std::optional<color_t>>> cellColors;
|
||||
{
|
||||
for (u64 x = 0; x < std::ceil(float(validBytes) / bytesPerCell); x++) {
|
||||
const u64 byteAddress = y * this->m_bytesPerRow + x * bytesPerCell + this->m_provider->getBaseAddress() + this->m_provider->getCurrentPageAddress();
|
||||
const u64 byteAddress = y * m_bytesPerRow + x * bytesPerCell + m_provider->getBaseAddress() + m_provider->getCurrentPageAddress();
|
||||
|
||||
const auto cellBytes = std::min<u64>(validBytes, bytesPerCell);
|
||||
|
||||
// Query cell colors
|
||||
if (x < std::ceil(float(validBytes) / bytesPerCell)) {
|
||||
auto foregroundColor = this->m_foregroundColorCallback(byteAddress, &bytes[x * cellBytes], cellBytes);
|
||||
auto backgroundColor = this->m_backgroundColorCallback(byteAddress, &bytes[x * cellBytes], cellBytes);
|
||||
auto foregroundColor = m_foregroundColorCallback(byteAddress, &bytes[x * cellBytes], cellBytes);
|
||||
auto backgroundColor = m_backgroundColorCallback(byteAddress, &bytes[x * cellBytes], cellBytes);
|
||||
|
||||
if (this->m_grayOutZero && !foregroundColor.has_value()) {
|
||||
if (m_grayOutZero && !foregroundColor.has_value()) {
|
||||
bool allZero = true;
|
||||
for (u64 i = 0; i < cellBytes && (x * cellBytes + i) < bytes.size(); i++) {
|
||||
if (bytes[x * cellBytes + i] != 0x00) {
|
||||
@@ -436,7 +436,7 @@ namespace hex::plugin::builtin::ui {
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, scaled(ImVec2(2.75F, 0.0F)));
|
||||
|
||||
for (u64 x = 0; x < columnCount; x++) {
|
||||
const u64 byteAddress = y * this->m_bytesPerRow + x * bytesPerCell + this->m_provider->getBaseAddress() + this->m_provider->getCurrentPageAddress();
|
||||
const u64 byteAddress = y * m_bytesPerRow + x * bytesPerCell + m_provider->getBaseAddress() + m_provider->getCurrentPageAddress();
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
if (isColumnSeparatorColumn(x, columnCount))
|
||||
@@ -444,8 +444,8 @@ namespace hex::plugin::builtin::ui {
|
||||
|
||||
if (x < std::ceil(float(validBytes) / bytesPerCell)) {
|
||||
auto cellStartPos = getCellPosition();
|
||||
auto cellSize = (CharacterSize * ImVec2(this->m_currDataVisualizer->getMaxCharsPerCell(), 1)) + (ImVec2(2, 2) * ImGui::GetStyle().CellPadding) + scaled(ImVec2(1 + this->m_byteCellPadding, 0));
|
||||
auto maxCharsPerCell = this->m_currDataVisualizer->getMaxCharsPerCell();
|
||||
auto cellSize = (CharacterSize * ImVec2(m_currDataVisualizer->getMaxCharsPerCell(), 1)) + (ImVec2(2, 2) * ImGui::GetStyle().CellPadding) + scaled(ImVec2(1 + m_byteCellPadding, 0));
|
||||
auto maxCharsPerCell = m_currDataVisualizer->getMaxCharsPerCell();
|
||||
|
||||
auto [foregroundColor, backgroundColor] = cellColors[x];
|
||||
|
||||
@@ -495,21 +495,21 @@ namespace hex::plugin::builtin::ui {
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
// Draw ASCII column
|
||||
if (this->m_showAscii) {
|
||||
if (m_showAscii) {
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, ImVec2(0, 0));
|
||||
if (ImGui::BeginTable("##ascii_column", this->m_bytesPerRow)) {
|
||||
for (u64 x = 0; x < this->m_bytesPerRow; x++)
|
||||
ImGui::TableSetupColumn(hex::format("##ascii_cell{}", x).c_str(), ImGuiTableColumnFlags_WidthFixed, CharacterSize.x + this->m_characterCellPadding * 1_scaled);
|
||||
if (ImGui::BeginTable("##ascii_column", m_bytesPerRow)) {
|
||||
for (u64 x = 0; x < m_bytesPerRow; x++)
|
||||
ImGui::TableSetupColumn(hex::format("##ascii_cell{}", x).c_str(), ImGuiTableColumnFlags_WidthFixed, CharacterSize.x + m_characterCellPadding * 1_scaled);
|
||||
|
||||
ImGui::TableNextRow();
|
||||
|
||||
for (u64 x = 0; x < this->m_bytesPerRow; x++) {
|
||||
for (u64 x = 0; x < m_bytesPerRow; x++) {
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
const u64 byteAddress = y * this->m_bytesPerRow + x + this->m_provider->getBaseAddress() + this->m_provider->getCurrentPageAddress();
|
||||
const u64 byteAddress = y * m_bytesPerRow + x + m_provider->getBaseAddress() + m_provider->getCurrentPageAddress();
|
||||
|
||||
const auto cellStartPos = getCellPosition();
|
||||
const auto cellSize = CharacterSize + scaled(ImVec2(this->m_characterCellPadding, 0));
|
||||
const auto cellSize = CharacterSize + scaled(ImVec2(m_characterCellPadding, 0));
|
||||
|
||||
const bool cellHovered = ImGui::IsMouseHoveringRect(cellStartPos, cellStartPos + cellSize, true);
|
||||
|
||||
@@ -525,11 +525,11 @@ namespace hex::plugin::builtin::ui {
|
||||
this->drawSelectionFrame(x, y, selection, byteAddress, 1, cellStartPos, cellSize, backgroundColor.value());
|
||||
}
|
||||
|
||||
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + (this->m_characterCellPadding * 1_scaled) / 2);
|
||||
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + (m_characterCellPadding * 1_scaled) / 2);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
|
||||
ImGui::PushItemWidth(CharacterSize.x);
|
||||
if (!isCurrRegionValid(byteAddress))
|
||||
ImGuiExt::TextFormattedDisabled("{}", this->m_unknownDataCharacter);
|
||||
ImGuiExt::TextFormattedDisabled("{}", m_unknownDataCharacter);
|
||||
else
|
||||
this->drawCell(byteAddress, &bytes[x], 1, cellHovered, CellType::ASCII);
|
||||
ImGui::PopItemWidth();
|
||||
@@ -546,29 +546,29 @@ namespace hex::plugin::builtin::ui {
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
// Draw Custom encoding column
|
||||
if (this->m_showCustomEncoding && this->m_currCustomEncoding.has_value()) {
|
||||
if (this->m_encodingLineStartAddresses.empty()) {
|
||||
this->m_encodingLineStartAddresses.push_back(0);
|
||||
if (m_showCustomEncoding && m_currCustomEncoding.has_value()) {
|
||||
if (m_encodingLineStartAddresses.empty()) {
|
||||
m_encodingLineStartAddresses.push_back(0);
|
||||
}
|
||||
|
||||
if (y < this->m_encodingLineStartAddresses.size()) {
|
||||
if (y < m_encodingLineStartAddresses.size()) {
|
||||
std::vector<std::pair<u64, CustomEncodingData>> encodingData;
|
||||
|
||||
if (this->m_encodingLineStartAddresses[y] >= this->m_bytesPerRow) {
|
||||
encodingData.emplace_back(y * this->m_bytesPerRow + this->m_provider->getBaseAddress() + this->m_provider->getCurrentPageAddress(), CustomEncodingData(".", 1, ImGuiExt::GetCustomColorU32(ImGuiCustomCol_AdvancedEncodingUnknown)));
|
||||
this->m_encodingLineStartAddresses.push_back(0);
|
||||
if (m_encodingLineStartAddresses[y] >= m_bytesPerRow) {
|
||||
encodingData.emplace_back(y * m_bytesPerRow + m_provider->getBaseAddress() + m_provider->getCurrentPageAddress(), CustomEncodingData(".", 1, ImGuiExt::GetCustomColorU32(ImGuiCustomCol_AdvancedEncodingUnknown)));
|
||||
m_encodingLineStartAddresses.push_back(0);
|
||||
} else {
|
||||
u32 offset = this->m_encodingLineStartAddresses[y];
|
||||
u32 offset = m_encodingLineStartAddresses[y];
|
||||
do {
|
||||
const u64 address = y * this->m_bytesPerRow + offset + this->m_provider->getBaseAddress() + this->m_provider->getCurrentPageAddress();
|
||||
const u64 address = y * m_bytesPerRow + offset + m_provider->getBaseAddress() + m_provider->getCurrentPageAddress();
|
||||
|
||||
auto result = queryCustomEncodingData(this->m_provider, *this->m_currCustomEncoding, address);
|
||||
auto result = queryCustomEncodingData(m_provider, *m_currCustomEncoding, address);
|
||||
|
||||
offset += result.advance;
|
||||
encodingData.emplace_back(address, result);
|
||||
} while (offset < this->m_bytesPerRow);
|
||||
} while (offset < m_bytesPerRow);
|
||||
|
||||
this->m_encodingLineStartAddresses.push_back(offset - this->m_bytesPerRow);
|
||||
m_encodingLineStartAddresses.push_back(offset - m_bytesPerRow);
|
||||
}
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, ImVec2(0, 0));
|
||||
@@ -580,10 +580,10 @@ namespace hex::plugin::builtin::ui {
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
const auto cellStartPos = getCellPosition();
|
||||
const auto cellSize = ImGui::CalcTextSize(data.displayValue.c_str()) * ImVec2(1, 0) + ImVec2(this->m_characterCellPadding * 1_scaled, CharacterSize.y);
|
||||
const auto cellSize = ImGui::CalcTextSize(data.displayValue.c_str()) * ImVec2(1, 0) + ImVec2(m_characterCellPadding * 1_scaled, CharacterSize.y);
|
||||
const bool cellHovered = ImGui::IsMouseHoveringRect(cellStartPos, cellStartPos + cellSize, true);
|
||||
|
||||
const auto x = address % this->m_bytesPerRow;
|
||||
const auto x = address % m_bytesPerRow;
|
||||
if (x < validBytes && isCurrRegionValid(address)) {
|
||||
auto [foregroundColor, backgroundColor] = cellColors[x / bytesPerCell];
|
||||
|
||||
@@ -600,7 +600,7 @@ namespace hex::plugin::builtin::ui {
|
||||
ImGui::SameLine(0, 0);
|
||||
ImGui::Dummy({ 0, 0 });
|
||||
|
||||
this->handleSelection(address, data.advance, &bytes[address % this->m_bytesPerRow], cellHovered);
|
||||
this->handleSelection(address, data.advance, &bytes[address % m_bytesPerRow], cellHovered);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -612,35 +612,35 @@ namespace hex::plugin::builtin::ui {
|
||||
}
|
||||
|
||||
// Scroll to the cursor if it's either at the top or bottom edge of the screen
|
||||
if (this->m_shouldScrollToSelection && isSelectionValid()) {
|
||||
if (m_shouldScrollToSelection && isSelectionValid()) {
|
||||
// Make sure simply clicking on a byte at the edge of the screen won't cause scrolling
|
||||
if ((ImGui::IsMouseDragging(ImGuiMouseButton_Left) && *this->m_selectionStart != *this->m_selectionEnd)) {
|
||||
auto fractionPerLine = 1.0 / (this->m_visibleRowCount + 1);
|
||||
if ((ImGui::IsMouseDragging(ImGuiMouseButton_Left) && *m_selectionStart != *m_selectionEnd)) {
|
||||
auto fractionPerLine = 1.0 / (m_visibleRowCount + 1);
|
||||
|
||||
if (y == (u64(clipper.DisplayStart) + 3)) {
|
||||
if (i128(this->m_selectionEnd.value() - this->m_provider->getBaseAddress() - this->m_provider->getCurrentPageAddress()) <= (i64(clipper.DisplayStart + 3) * this->m_bytesPerRow)) {
|
||||
this->m_shouldScrollToSelection = false;
|
||||
if (i128(m_selectionEnd.value() - m_provider->getBaseAddress() - m_provider->getCurrentPageAddress()) <= (i64(clipper.DisplayStart + 3) * m_bytesPerRow)) {
|
||||
m_shouldScrollToSelection = false;
|
||||
ImGui::SetScrollHereY(fractionPerLine * 5);
|
||||
}
|
||||
} else if (y == (u64(clipper.DisplayEnd) - 1)) {
|
||||
if (i128(this->m_selectionEnd.value() - this->m_provider->getBaseAddress() - this->m_provider->getCurrentPageAddress()) >= (i64(clipper.DisplayEnd - 2) * this->m_bytesPerRow)) {
|
||||
this->m_shouldScrollToSelection = false;
|
||||
ImGui::SetScrollHereY(fractionPerLine * (this->m_visibleRowCount));
|
||||
if (i128(m_selectionEnd.value() - m_provider->getBaseAddress() - m_provider->getCurrentPageAddress()) >= (i64(clipper.DisplayEnd - 2) * m_bytesPerRow)) {
|
||||
m_shouldScrollToSelection = false;
|
||||
ImGui::SetScrollHereY(fractionPerLine * (m_visibleRowCount));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If the cursor is off-screen, directly jump to the byte
|
||||
if (this->m_shouldJumpWhenOffScreen) {
|
||||
this->m_shouldJumpWhenOffScreen = false;
|
||||
if (m_shouldJumpWhenOffScreen) {
|
||||
m_shouldJumpWhenOffScreen = false;
|
||||
|
||||
const auto pageAddress = this->m_provider->getCurrentPageAddress() + this->m_provider->getBaseAddress();
|
||||
const auto pageAddress = m_provider->getCurrentPageAddress() + m_provider->getBaseAddress();
|
||||
auto newSelection = getSelection();
|
||||
newSelection.address -= pageAddress;
|
||||
|
||||
if ((newSelection.getStartAddress()) < u64(clipper.DisplayStart * this->m_bytesPerRow))
|
||||
if ((newSelection.getStartAddress()) < u64(clipper.DisplayStart * m_bytesPerRow))
|
||||
this->jumpToSelection(false);
|
||||
if ((newSelection.getEndAddress()) > u64(clipper.DisplayEnd * this->m_bytesPerRow))
|
||||
if ((newSelection.getEndAddress()) > u64(clipper.DisplayEnd * m_bytesPerRow))
|
||||
this->jumpToSelection(false);
|
||||
}
|
||||
}
|
||||
@@ -648,31 +648,31 @@ namespace hex::plugin::builtin::ui {
|
||||
}
|
||||
|
||||
// Handle jumping to selection
|
||||
if (this->m_shouldJumpToSelection) {
|
||||
this->m_shouldJumpToSelection = false;
|
||||
if (m_shouldJumpToSelection) {
|
||||
m_shouldJumpToSelection = false;
|
||||
|
||||
auto newSelection = getSelection();
|
||||
this->m_provider->setCurrentPage(this->m_provider->getPageOfAddress(newSelection.address).value_or(0));
|
||||
m_provider->setCurrentPage(m_provider->getPageOfAddress(newSelection.address).value_or(0));
|
||||
|
||||
const auto pageAddress = this->m_provider->getCurrentPageAddress() + this->m_provider->getBaseAddress();
|
||||
auto scrollPos = (static_cast<long double>(newSelection.getStartAddress() - pageAddress) / this->m_bytesPerRow) * CharacterSize.y;
|
||||
const auto pageAddress = m_provider->getCurrentPageAddress() + m_provider->getBaseAddress();
|
||||
auto scrollPos = (static_cast<long double>(newSelection.getStartAddress() - pageAddress) / m_bytesPerRow) * CharacterSize.y;
|
||||
bool scrollUpwards = scrollPos < ImGui::GetScrollY();
|
||||
auto scrollFraction = scrollUpwards ? 0.0F : (1.0F - ((1.0F / this->m_visibleRowCount) * 2));
|
||||
auto scrollFraction = scrollUpwards ? 0.0F : (1.0F - ((1.0F / m_visibleRowCount) * 2));
|
||||
|
||||
if (this->m_centerOnJump) {
|
||||
if (m_centerOnJump) {
|
||||
scrollFraction = 0.5F;
|
||||
this->m_centerOnJump = false;
|
||||
m_centerOnJump = false;
|
||||
}
|
||||
|
||||
ImGui::SetScrollFromPosY(ImGui::GetCursorStartPos().y + scrollPos, scrollFraction);
|
||||
}
|
||||
|
||||
if (!this->m_syncScrolling) {
|
||||
if (this->m_shouldUpdateScrollPosition) {
|
||||
this->m_shouldUpdateScrollPosition = false;
|
||||
ImGui::SetScrollY(this->m_scrollPosition);
|
||||
if (!m_syncScrolling) {
|
||||
if (m_shouldUpdateScrollPosition) {
|
||||
m_shouldUpdateScrollPosition = false;
|
||||
ImGui::SetScrollY(m_scrollPosition);
|
||||
} else {
|
||||
this->m_scrollPosition = ImGui::GetScrollY();
|
||||
m_scrollPosition = ImGui::GetScrollY();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -681,12 +681,12 @@ namespace hex::plugin::builtin::ui {
|
||||
}
|
||||
ImGui::PopStyleVar();
|
||||
|
||||
this->m_shouldScrollToSelection = false;
|
||||
m_shouldScrollToSelection = false;
|
||||
}
|
||||
|
||||
void HexEditor::drawFooter(const ImVec2 &size) {
|
||||
if (this->m_provider != nullptr && this->m_provider->isReadable()) {
|
||||
const auto pageCount = std::max<u32>(1, this->m_provider->getPageCount());
|
||||
if (m_provider != nullptr && m_provider->isReadable()) {
|
||||
const auto pageCount = std::max<u32>(1, m_provider->getPageCount());
|
||||
constexpr static u32 MinPage = 1;
|
||||
|
||||
const auto windowEndPos = ImGui::GetWindowPos() + size - ImGui::GetStyle().WindowPadding;
|
||||
@@ -702,7 +702,7 @@ namespace hex::plugin::builtin::ui {
|
||||
// Page slider
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
u32 page = this->m_provider->getCurrentPage() + 1;
|
||||
u32 page = m_provider->getCurrentPage() + 1;
|
||||
|
||||
ImGuiExt::TextFormatted("{}: ", "hex.builtin.hex_editor.page"_lang);
|
||||
ImGui::SameLine();
|
||||
@@ -711,7 +711,7 @@ namespace hex::plugin::builtin::ui {
|
||||
{
|
||||
ImGui::PushItemWidth(-1);
|
||||
if (ImGui::SliderScalar("##page_selection", ImGuiDataType_U32, &page, &MinPage, &pageCount, hex::format("0x%02llX / 0x{:02X}", pageCount).c_str()))
|
||||
this->m_provider->setCurrentPage(page - 1);
|
||||
m_provider->setCurrentPage(page - 1);
|
||||
ImGui::PopItemWidth();
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
@@ -720,15 +720,15 @@ namespace hex::plugin::builtin::ui {
|
||||
// Collapse button
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
if (ImGuiExt::DimmedIconButton(this->m_footerCollapsed ? ICON_VS_FOLD_UP : ICON_VS_FOLD_DOWN, ImGui::GetStyleColorVec4(ImGuiCol_Text)))
|
||||
this->m_footerCollapsed = !this->m_footerCollapsed;
|
||||
if (ImGuiExt::DimmedIconButton(m_footerCollapsed ? ICON_VS_FOLD_UP : ICON_VS_FOLD_DOWN, ImGui::GetStyleColorVec4(ImGuiCol_Text)))
|
||||
m_footerCollapsed = !m_footerCollapsed;
|
||||
}
|
||||
|
||||
// Page Address
|
||||
ImGui::TableNextColumn();
|
||||
{
|
||||
const auto pageAddress = this->m_provider->getCurrentPageAddress();
|
||||
const auto pageSize = this->m_provider->getSize();
|
||||
const auto pageAddress = m_provider->getCurrentPageAddress();
|
||||
const auto pageSize = m_provider->getSize();
|
||||
ImGuiExt::TextFormatted("{}:", "hex.builtin.hex_editor.region"_lang);
|
||||
ImGui::SameLine();
|
||||
ImGuiExt::TextFormattedSelectable("0x{0:08X} - 0x{1:08X} ({0} - {1})",
|
||||
@@ -737,7 +737,7 @@ namespace hex::plugin::builtin::ui {
|
||||
);
|
||||
}
|
||||
|
||||
if (!this->m_footerCollapsed) {
|
||||
if (!m_footerCollapsed) {
|
||||
ImGui::TableNextRow();
|
||||
|
||||
// Selection
|
||||
@@ -750,7 +750,7 @@ namespace hex::plugin::builtin::ui {
|
||||
selection.getStartAddress(),
|
||||
selection.getEndAddress(),
|
||||
selection.getSize(),
|
||||
this->m_showHumanReadableUnits
|
||||
m_showHumanReadableUnits
|
||||
? hex::toByteString(selection.getSize())
|
||||
: hex::format("{}", selection.getSize())
|
||||
);
|
||||
@@ -771,11 +771,11 @@ namespace hex::plugin::builtin::ui {
|
||||
ImGuiExt::TextFormatted("{}:", "hex.builtin.hex_editor.data_size"_lang);
|
||||
ImGui::SameLine();
|
||||
ImGuiExt::TextFormattedSelectable("0x{0:08X} (0x{1:X} | {2})",
|
||||
this->m_provider->getBaseAddress(),
|
||||
this->m_provider->getBaseAddress() + this->m_provider->getActualSize(),
|
||||
this->m_showHumanReadableUnits
|
||||
? hex::toByteString(this->m_provider->getActualSize())
|
||||
: hex::format("{}", this->m_provider->getActualSize())
|
||||
m_provider->getBaseAddress(),
|
||||
m_provider->getBaseAddress() + m_provider->getActualSize(),
|
||||
m_showHumanReadableUnits
|
||||
? hex::toByteString(m_provider->getActualSize())
|
||||
: hex::format("{}", m_provider->getActualSize())
|
||||
);
|
||||
}
|
||||
|
||||
@@ -785,26 +785,26 @@ namespace hex::plugin::builtin::ui {
|
||||
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 2_scaled);
|
||||
|
||||
// Upper/lower case hex
|
||||
ImGuiExt::DimmedIconToggle(ICON_VS_CASE_SENSITIVE, &this->m_upperCaseHex);
|
||||
ImGuiExt::DimmedIconToggle(ICON_VS_CASE_SENSITIVE, &m_upperCaseHex);
|
||||
ImGuiExt::InfoTooltip("hex.builtin.hex_editor.uppercase_hex"_lang);
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
// Grayed out zeros
|
||||
ImGuiExt::DimmedIconToggle(ICON_VS_LIGHTBULB, &this->m_grayOutZero);
|
||||
ImGuiExt::DimmedIconToggle(ICON_VS_LIGHTBULB, &m_grayOutZero);
|
||||
ImGuiExt::InfoTooltip("hex.builtin.hex_editor.gray_out_zero"_lang);
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
// ASCII view
|
||||
ImGuiExt::DimmedIconToggle(ICON_VS_SYMBOL_KEY, &this->m_showAscii);
|
||||
ImGuiExt::DimmedIconToggle(ICON_VS_SYMBOL_KEY, &m_showAscii);
|
||||
ImGuiExt::InfoTooltip("hex.builtin.hex_editor.ascii_view"_lang);
|
||||
|
||||
ImGui::SameLine(0, 1_scaled);
|
||||
|
||||
// Custom encoding view
|
||||
ImGui::BeginDisabled(!this->m_currCustomEncoding.has_value());
|
||||
ImGuiExt::DimmedIconToggle(ICON_VS_WHITESPACE, &this->m_showCustomEncoding);
|
||||
ImGui::BeginDisabled(!m_currCustomEncoding.has_value());
|
||||
ImGuiExt::DimmedIconToggle(ICON_VS_WHITESPACE, &m_showCustomEncoding);
|
||||
ImGui::EndDisabled();
|
||||
|
||||
ImGuiExt::InfoTooltip("hex.builtin.hex_editor.custom_encoding_view"_lang);
|
||||
@@ -812,7 +812,7 @@ namespace hex::plugin::builtin::ui {
|
||||
ImGui::SameLine();
|
||||
|
||||
// Human-readable units
|
||||
ImGuiExt::DimmedIconToggle(ICON_VS_SYMBOL_NUMERIC, &this->m_showHumanReadableUnits);
|
||||
ImGuiExt::DimmedIconToggle(ICON_VS_SYMBOL_NUMERIC, &m_showHumanReadableUnits);
|
||||
ImGuiExt::InfoTooltip("hex.builtin.hex_editor.human_readable_units_footer"_lang);
|
||||
}
|
||||
|
||||
@@ -828,33 +828,33 @@ namespace hex::plugin::builtin::ui {
|
||||
ImGui::SameLine(0, 0);
|
||||
|
||||
{
|
||||
bool hasEndianess = this->m_currDataVisualizer->getBytesPerCell() > 1;
|
||||
bool hasEndianess = m_currDataVisualizer->getBytesPerCell() > 1;
|
||||
|
||||
if (!hasEndianess)
|
||||
this->m_dataVisualizerEndianness = std::endian::native;
|
||||
m_dataVisualizerEndianness = std::endian::native;
|
||||
|
||||
ImGui::BeginDisabled(!hasEndianess);
|
||||
{
|
||||
int sliderPos = this->m_dataVisualizerEndianness == std::endian::little ? 0 : 1;
|
||||
int sliderPos = m_dataVisualizerEndianness == std::endian::little ? 0 : 1;
|
||||
ImGui::PushItemWidth(60_scaled);
|
||||
ImGui::SliderInt("##visualizer_endianness", &sliderPos, 0, 1, sliderPos == 0 ? "hex.builtin.common.little"_lang : "hex.builtin.common.big"_lang);
|
||||
ImGui::PopItemWidth();
|
||||
this->m_dataVisualizerEndianness = sliderPos == 0 ? std::endian::little : std::endian::big;
|
||||
m_dataVisualizerEndianness = sliderPos == 0 ? std::endian::little : std::endian::big;
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
}
|
||||
|
||||
ImGui::SameLine(0, 2_scaled);
|
||||
ImGui::PushItemWidth((ImGui::GetContentRegionAvail().x / 3) * 2);
|
||||
if (ImGui::BeginCombo("##visualizer", Lang(this->m_currDataVisualizer->getUnlocalizedName()))) {
|
||||
if (ImGui::BeginCombo("##visualizer", Lang(m_currDataVisualizer->getUnlocalizedName()))) {
|
||||
|
||||
for (const auto &visualizer : visualizers) {
|
||||
if (ImGui::Selectable(Lang(visualizer->getUnlocalizedName()))) {
|
||||
this->m_currDataVisualizer = visualizer;
|
||||
this->m_encodingLineStartAddresses.clear();
|
||||
m_currDataVisualizer = visualizer;
|
||||
m_encodingLineStartAddresses.clear();
|
||||
|
||||
if (this->m_bytesPerRow < visualizer->getBytesPerCell())
|
||||
this->m_bytesPerRow = visualizer->getBytesPerCell();
|
||||
if (m_bytesPerRow < visualizer->getBytesPerCell())
|
||||
m_bytesPerRow = visualizer->getBytesPerCell();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -864,12 +864,12 @@ namespace hex::plugin::builtin::ui {
|
||||
|
||||
ImGui::SameLine(0, 2_scaled);
|
||||
ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
int bytesPerRow = this->m_bytesPerRow / this->getBytesPerCell();
|
||||
int bytesPerRow = m_bytesPerRow / this->getBytesPerCell();
|
||||
if (ImGui::SliderInt("##row_size", &bytesPerRow, 1, 32 / this->getBytesPerCell(), hex::format("{}", bytesPerRow * this->getBytesPerCell()).c_str())) {
|
||||
this->m_bytesPerRow = bytesPerRow * this->getBytesPerCell();
|
||||
this->m_encodingLineStartAddresses.clear();
|
||||
m_bytesPerRow = bytesPerRow * this->getBytesPerCell();
|
||||
m_encodingLineStartAddresses.clear();
|
||||
|
||||
ContentRegistry::Settings::write("hex.builtin.setting.hex_editor", "hex.builtin.setting.hex_editor.bytes_per_row", this->m_bytesPerRow);
|
||||
ContentRegistry::Settings::write("hex.builtin.setting.hex_editor", "hex.builtin.setting.hex_editor.bytes_per_row", m_bytesPerRow);
|
||||
}
|
||||
ImGui::PopItemWidth();
|
||||
}
|
||||
@@ -887,7 +887,7 @@ namespace hex::plugin::builtin::ui {
|
||||
drawTooltip(address, data, bytesPerCell);
|
||||
|
||||
auto endAddress = address + bytesPerCell - 1;
|
||||
auto &selectionStart = this->m_selectionStart;
|
||||
auto &selectionStart = m_selectionStart;
|
||||
|
||||
if (ImGui::IsMouseDragging(ImGuiMouseButton_Left)) {
|
||||
this->setSelection(selectionStart.value_or(address), endAddress);
|
||||
@@ -908,7 +908,7 @@ namespace hex::plugin::builtin::ui {
|
||||
const auto width = ImGui::GetContentRegionAvail().x;
|
||||
|
||||
auto footerSize = ImVec2(width, 0);
|
||||
if (!this->m_footerCollapsed)
|
||||
if (!m_footerCollapsed)
|
||||
footerSize.y = ImGui::GetTextLineHeightWithSpacing() * 3.6F;
|
||||
else
|
||||
footerSize.y = ImGui::GetTextLineHeightWithSpacing() * 1.4F;
|
||||
@@ -922,7 +922,7 @@ namespace hex::plugin::builtin::ui {
|
||||
if (tableSize.y > 0)
|
||||
this->drawFooter(footerSize);
|
||||
|
||||
this->m_selectionChanged = false;
|
||||
m_selectionChanged = false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -204,12 +204,12 @@ namespace hex::plugin::builtin::ui {
|
||||
}
|
||||
|
||||
bool PatternDrawer::isEditingPattern(const pl::ptrn::Pattern& pattern) const {
|
||||
return this->m_editingPattern == &pattern && this->m_editingPatternOffset == pattern.getOffset();
|
||||
return m_editingPattern == &pattern && m_editingPatternOffset == pattern.getOffset();
|
||||
}
|
||||
|
||||
void PatternDrawer::resetEditing() {
|
||||
this->m_editingPattern = nullptr;
|
||||
this->m_editingPatternOffset = 0x00;
|
||||
m_editingPattern = nullptr;
|
||||
m_editingPatternOffset = 0x00;
|
||||
}
|
||||
|
||||
bool PatternDrawer::matchesFilter(const std::vector<std::string> &filterPath, const std::vector<std::string> &patternPath, bool fullMatch) const {
|
||||
@@ -232,24 +232,24 @@ namespace hex::plugin::builtin::ui {
|
||||
}
|
||||
|
||||
void PatternDrawer::drawFavoriteColumn(const pl::ptrn::Pattern& pattern) {
|
||||
if (this->m_rowColoring)
|
||||
if (m_rowColoring)
|
||||
ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBg0, (pattern.getColor() & 0x00'FF'FF'FF) | 0x30'00'00'00);
|
||||
|
||||
if (!this->m_showFavoriteStars) {
|
||||
if (!m_showFavoriteStars) {
|
||||
ImGui::TableNextColumn();
|
||||
return;
|
||||
}
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
|
||||
|
||||
if (this->m_favorites.contains(this->m_currPatternPath)) {
|
||||
if (m_favorites.contains(m_currPatternPath)) {
|
||||
if (ImGuiExt::DimmedIconButton(ICON_VS_STAR_DELETE, ImGui::GetStyleColorVec4(ImGuiCol_PlotHistogram))) {
|
||||
this->m_favorites.erase(this->m_currPatternPath);
|
||||
m_favorites.erase(m_currPatternPath);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (ImGuiExt::DimmedIconButton(ICON_VS_STAR_ADD, ImGui::GetStyleColorVec4(ImGuiCol_TextDisabled))) {
|
||||
this->m_favorites.insert({ this->m_currPatternPath, pattern.clone() });
|
||||
m_favorites.insert({ m_currPatternPath, pattern.clone() });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -271,7 +271,7 @@ namespace hex::plugin::builtin::ui {
|
||||
try {
|
||||
visualizer.callback(pattern, iterable, reset, { arguments.begin() + 1, arguments.end() });
|
||||
} catch (std::exception &e) {
|
||||
this->m_lastVisualizerError = e.what();
|
||||
m_lastVisualizerError = e.what();
|
||||
}
|
||||
} else {
|
||||
ImGui::TextUnformatted("hex.builtin.pattern_drawer.visualizer.invalid_parameter_count"_lang);
|
||||
@@ -280,8 +280,8 @@ namespace hex::plugin::builtin::ui {
|
||||
ImGui::TextUnformatted("hex.builtin.pattern_drawer.visualizer.unknown"_lang);
|
||||
}
|
||||
|
||||
if (!this->m_lastVisualizerError.empty())
|
||||
ImGui::TextUnformatted(this->m_lastVisualizerError.c_str());
|
||||
if (!m_lastVisualizerError.empty())
|
||||
ImGui::TextUnformatted(m_lastVisualizerError.c_str());
|
||||
}
|
||||
|
||||
void PatternDrawer::drawValueColumn(pl::ptrn::Pattern& pattern) {
|
||||
@@ -300,12 +300,12 @@ namespace hex::plugin::builtin::ui {
|
||||
|
||||
bool shouldReset = false;
|
||||
if (ImGui::Button(hex::format(" {} {}", ICON_VS_EYE_WATCH, value).c_str(), ImVec2(width, ImGui::GetTextLineHeight()))) {
|
||||
auto previousPattern = this->m_currVisualizedPattern;
|
||||
auto previousPattern = m_currVisualizedPattern;
|
||||
|
||||
this->m_currVisualizedPattern = &pattern;
|
||||
this->m_lastVisualizerError.clear();
|
||||
m_currVisualizedPattern = &pattern;
|
||||
m_lastVisualizerError.clear();
|
||||
|
||||
if (this->m_currVisualizedPattern != previousPattern)
|
||||
if (m_currVisualizedPattern != previousPattern)
|
||||
shouldReset = true;
|
||||
|
||||
ImGui::OpenPopup("Visualizer");
|
||||
@@ -315,9 +315,9 @@ namespace hex::plugin::builtin::ui {
|
||||
ImGui::SameLine();
|
||||
|
||||
if (ImGui::BeginPopup("Visualizer")) {
|
||||
if (this->m_currVisualizedPattern == &pattern) {
|
||||
drawVisualizer(ContentRegistry::PatternLanguage::impl::getVisualizers(), visualizeArgs, pattern, dynamic_cast<pl::ptrn::IIterable&>(pattern), !this->m_visualizedPatterns.contains(&pattern) || shouldReset);
|
||||
this->m_visualizedPatterns.insert(&pattern);
|
||||
if (m_currVisualizedPattern == &pattern) {
|
||||
drawVisualizer(ContentRegistry::PatternLanguage::impl::getVisualizers(), visualizeArgs, pattern, dynamic_cast<pl::ptrn::IIterable&>(pattern), !m_visualizedPatterns.contains(&pattern) || shouldReset);
|
||||
m_visualizedPatterns.insert(&pattern);
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
@@ -334,7 +334,7 @@ namespace hex::plugin::builtin::ui {
|
||||
}
|
||||
|
||||
std::string PatternDrawer::getDisplayName(const pl::ptrn::Pattern& pattern) const {
|
||||
if (this->m_showSpecName && pattern.hasAttribute("hex::spec_name"))
|
||||
if (m_showSpecName && pattern.hasAttribute("hex::spec_name"))
|
||||
return pattern.getAttributeArguments("hex::spec_name")[0].toString(true);
|
||||
else
|
||||
return pattern.getDisplayName();
|
||||
@@ -351,7 +351,7 @@ namespace hex::plugin::builtin::ui {
|
||||
}
|
||||
|
||||
return highlightWhenSelected(pattern, [&]{
|
||||
switch (this->m_treeStyle) {
|
||||
switch (m_treeStyle) {
|
||||
using enum TreeStyle;
|
||||
default:
|
||||
case Default:
|
||||
@@ -369,16 +369,16 @@ namespace hex::plugin::builtin::ui {
|
||||
ImGui::PushID(pattern.getVariableName().c_str());
|
||||
|
||||
if (ImGui::Selectable("##PatternLine", false, ImGuiSelectableFlags_SpanAllColumns | ImGuiSelectableFlags_AllowOverlap)) {
|
||||
this->m_selectionCallback(Region { pattern.getOffset(), pattern.getSize() });
|
||||
m_selectionCallback(Region { pattern.getOffset(), pattern.getSize() });
|
||||
|
||||
if (this->m_editingPattern != &pattern) {
|
||||
if (m_editingPattern != &pattern) {
|
||||
this->resetEditing();
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) {
|
||||
this->m_editingPattern = &pattern;
|
||||
this->m_editingPatternOffset = pattern.getOffset();
|
||||
m_editingPattern = &pattern;
|
||||
m_editingPatternOffset = pattern.getOffset();
|
||||
AchievementManager::unlockAchievement("hex.builtin.achievement.patterns", "hex.builtin.achievement.patterns.modify_data.name");
|
||||
}
|
||||
|
||||
@@ -404,7 +404,7 @@ namespace hex::plugin::builtin::ui {
|
||||
}
|
||||
|
||||
void PatternDrawer::closeTreeNode(bool inlined) const {
|
||||
if (!inlined && this->m_treeStyle != TreeStyle::Flattened)
|
||||
if (!inlined && m_treeStyle != TreeStyle::Flattened)
|
||||
ImGui::TreePop();
|
||||
}
|
||||
|
||||
@@ -478,7 +478,7 @@ namespace hex::plugin::builtin::ui {
|
||||
|
||||
void PatternDrawer::visit(pl::ptrn::PatternBitfield& pattern) {
|
||||
bool open = true;
|
||||
if (!pattern.isInlined() && this->m_treeStyle != TreeStyle::Flattened) {
|
||||
if (!pattern.isInlined() && m_treeStyle != TreeStyle::Flattened) {
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
open = createTreeNode(pattern);
|
||||
@@ -634,7 +634,7 @@ namespace hex::plugin::builtin::ui {
|
||||
void PatternDrawer::visit(pl::ptrn::PatternPointer& pattern) {
|
||||
bool open = true;
|
||||
|
||||
if (!pattern.isInlined() && this->m_treeStyle != TreeStyle::Flattened) {
|
||||
if (!pattern.isInlined() && m_treeStyle != TreeStyle::Flattened) {
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
open = createTreeNode(pattern);
|
||||
@@ -708,7 +708,7 @@ namespace hex::plugin::builtin::ui {
|
||||
void PatternDrawer::visit(pl::ptrn::PatternStruct& pattern) {
|
||||
bool open = true;
|
||||
|
||||
if (!pattern.isInlined() && this->m_treeStyle != TreeStyle::Flattened) {
|
||||
if (!pattern.isInlined() && m_treeStyle != TreeStyle::Flattened) {
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
open = createTreeNode(pattern);
|
||||
@@ -758,7 +758,7 @@ namespace hex::plugin::builtin::ui {
|
||||
void PatternDrawer::visit(pl::ptrn::PatternUnion& pattern) {
|
||||
bool open = true;
|
||||
|
||||
if (!pattern.isInlined() && this->m_treeStyle != TreeStyle::Flattened) {
|
||||
if (!pattern.isInlined() && m_treeStyle != TreeStyle::Flattened) {
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
open = createTreeNode(pattern);
|
||||
@@ -844,18 +844,18 @@ namespace hex::plugin::builtin::ui {
|
||||
if (pattern.getVisibility() == pl::ptrn::Visibility::Hidden)
|
||||
return;
|
||||
|
||||
this->m_currPatternPath.push_back(pattern.getVariableName());
|
||||
ON_SCOPE_EXIT { this->m_currPatternPath.pop_back(); };
|
||||
m_currPatternPath.push_back(pattern.getVariableName());
|
||||
ON_SCOPE_EXIT { m_currPatternPath.pop_back(); };
|
||||
|
||||
if (matchesFilter(this->m_filter.path, this->m_currPatternPath, false)) {
|
||||
if (this->m_filter.value.has_value()) {
|
||||
if (matchesFilter(m_filter.path, m_currPatternPath, false)) {
|
||||
if (m_filter.value.has_value()) {
|
||||
auto patternValue = pattern.getValue();
|
||||
if (patternValue == this->m_filter.value)
|
||||
if (patternValue == m_filter.value)
|
||||
pattern.accept(*this);
|
||||
else if (!matchesFilter(this->m_filter.path, this->m_currPatternPath, true))
|
||||
else if (!matchesFilter(m_filter.path, m_currPatternPath, true))
|
||||
pattern.accept(*this);
|
||||
else if (patternValue.isPattern() && this->m_filter.value->isString()) {
|
||||
if (patternValue.toString(true) == this->m_filter.value->toString(false))
|
||||
else if (patternValue.isPattern() && m_filter.value->isString()) {
|
||||
if (patternValue.toString(true) == m_filter.value->toString(false))
|
||||
pattern.accept(*this);
|
||||
}
|
||||
} else {
|
||||
@@ -869,7 +869,7 @@ namespace hex::plugin::builtin::ui {
|
||||
return;
|
||||
|
||||
bool open = true;
|
||||
if (!isInlined && this->m_treeStyle != TreeStyle::Flattened) {
|
||||
if (!isInlined && m_treeStyle != TreeStyle::Flattened) {
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
open = createTreeNode(pattern);
|
||||
@@ -933,7 +933,7 @@ namespace hex::plugin::builtin::ui {
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
chunkOpen = highlightWhenSelected(startOffset, ((endOffset + endSize) - startOffset) - 1, [&]{
|
||||
return ImGui::TreeNodeEx(hex::format("{0}[{1} ... {2}]", this->m_treeStyle == TreeStyle::Flattened ? this->getDisplayName(pattern).c_str() : "", i, endIndex - 1).c_str(), ImGuiTreeNodeFlags_SpanFullWidth);
|
||||
return ImGui::TreeNodeEx(hex::format("{0}[{1} ... {2}]", m_treeStyle == TreeStyle::Flattened ? this->getDisplayName(pattern).c_str() : "", i, endIndex - 1).c_str(), ImGuiTreeNodeFlags_SpanFullWidth);
|
||||
});
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
@@ -976,12 +976,12 @@ namespace hex::plugin::builtin::ui {
|
||||
}
|
||||
|
||||
u64& PatternDrawer::getDisplayEnd(const pl::ptrn::Pattern& pattern) {
|
||||
auto it = this->m_displayEnd.find(&pattern);
|
||||
if (it != this->m_displayEnd.end()) {
|
||||
auto it = m_displayEnd.find(&pattern);
|
||||
if (it != m_displayEnd.end()) {
|
||||
return it->second;
|
||||
}
|
||||
|
||||
auto [value, success] = this->m_displayEnd.emplace(&pattern, DisplayEndDefault);
|
||||
auto [value, success] = m_displayEnd.emplace(&pattern, DisplayEndDefault);
|
||||
return value->second;
|
||||
}
|
||||
|
||||
@@ -1089,13 +1089,13 @@ namespace hex::plugin::builtin::ui {
|
||||
const auto treeStyleButton = [this](auto icon, TreeStyle style, const char *tooltip) {
|
||||
bool pushed = false;
|
||||
|
||||
if (this->m_treeStyle == style) {
|
||||
if (m_treeStyle == style) {
|
||||
ImGui::PushStyleColor(ImGuiCol_Border, ImGui::GetStyleColorVec4(ImGuiCol_ButtonActive));
|
||||
pushed = true;
|
||||
}
|
||||
|
||||
if (ImGuiExt::DimmedIconButton(icon, ImGui::GetStyleColorVec4(ImGuiCol_Text)))
|
||||
this->m_treeStyle = style;
|
||||
m_treeStyle = style;
|
||||
|
||||
if (pushed)
|
||||
ImGui::PopStyleColor();
|
||||
@@ -1108,14 +1108,14 @@ namespace hex::plugin::builtin::ui {
|
||||
}
|
||||
|
||||
ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x - ImGui::GetTextLineHeightWithSpacing() * 9.5);
|
||||
if (ImGuiExt::InputTextIcon("##Search", ICON_VS_FILTER, this->m_filterText)) {
|
||||
this->m_filter = parseRValueFilter(this->m_filterText).value_or(Filter{ });
|
||||
if (ImGuiExt::InputTextIcon("##Search", ICON_VS_FILTER, m_filterText)) {
|
||||
m_filter = parseRValueFilter(m_filterText).value_or(Filter{ });
|
||||
}
|
||||
ImGui::PopItemWidth();
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGuiExt::DimmedIconToggle(ICON_VS_BOOK, &this->m_showSpecName);
|
||||
ImGuiExt::DimmedIconToggle(ICON_VS_BOOK, &m_showSpecName);
|
||||
ImGuiExt::InfoTooltip("hex.builtin.pattern_drawer.spec_name"_lang);
|
||||
|
||||
ImGui::SameLine();
|
||||
@@ -1140,7 +1140,7 @@ namespace hex::plugin::builtin::ui {
|
||||
|
||||
ImGui::SetNextWindowPos(ImGui::GetWindowPos() + ImVec2(startPos.x, ImGui::GetCursorPosY()));
|
||||
if (ImGui::BeginPopup("ExportPatterns")) {
|
||||
for (const auto &formatter : this->m_formatters) {
|
||||
for (const auto &formatter : m_formatters) {
|
||||
const auto name = [&]{
|
||||
auto name = formatter->getName();
|
||||
std::transform(name.begin(), name.end(), name.begin(), [](char c){ return char(std::toupper(c)); });
|
||||
@@ -1162,37 +1162,37 @@ namespace hex::plugin::builtin::ui {
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
if (!this->m_favoritesUpdated) {
|
||||
this->m_favoritesUpdated = true;
|
||||
if (!m_favoritesUpdated) {
|
||||
m_favoritesUpdated = true;
|
||||
|
||||
if (!patterns.empty() && !this->m_favoritesUpdateTask.isRunning()) {
|
||||
this->m_favoritesUpdateTask = TaskManager::createTask("hex.builtin.pattern_drawer.updating"_lang, TaskManager::NoProgress, [this, patterns](auto &task) {
|
||||
if (!patterns.empty() && !m_favoritesUpdateTask.isRunning()) {
|
||||
m_favoritesUpdateTask = TaskManager::createTask("hex.builtin.pattern_drawer.updating"_lang, TaskManager::NoProgress, [this, patterns](auto &task) {
|
||||
size_t updatedFavorites = 0;
|
||||
|
||||
for (auto &pattern : patterns) {
|
||||
std::vector<std::string> patternPath;
|
||||
traversePatternTree(*pattern, patternPath, [&, this](const pl::ptrn::Pattern &pattern) {
|
||||
if (pattern.hasAttribute("hex::favorite"))
|
||||
this->m_favorites.insert({ patternPath, pattern.clone() });
|
||||
m_favorites.insert({ patternPath, pattern.clone() });
|
||||
|
||||
if (const auto &args = pattern.getAttributeArguments("hex::group"); !args.empty()) {
|
||||
auto groupName = args.front().toString();
|
||||
|
||||
if (!this->m_groups.contains(groupName))
|
||||
this->m_groups.insert({groupName, std::vector<std::unique_ptr<pl::ptrn::Pattern>>()});
|
||||
if (!m_groups.contains(groupName))
|
||||
m_groups.insert({groupName, std::vector<std::unique_ptr<pl::ptrn::Pattern>>()});
|
||||
|
||||
this->m_groups[groupName].push_back(pattern.clone());
|
||||
m_groups[groupName].push_back(pattern.clone());
|
||||
}
|
||||
});
|
||||
|
||||
if (updatedFavorites == this->m_favorites.size())
|
||||
if (updatedFavorites == m_favorites.size())
|
||||
task.interrupt();
|
||||
task.update();
|
||||
|
||||
patternPath.clear();
|
||||
traversePatternTree(*pattern, patternPath, [&, this](const pl::ptrn::Pattern &pattern) {
|
||||
for (auto &[path, favoritePattern] : this->m_favorites) {
|
||||
if (updatedFavorites == this->m_favorites.size())
|
||||
for (auto &[path, favoritePattern] : m_favorites) {
|
||||
if (updatedFavorites == m_favorites.size())
|
||||
task.interrupt();
|
||||
task.update();
|
||||
|
||||
@@ -1206,7 +1206,7 @@ namespace hex::plugin::builtin::ui {
|
||||
});
|
||||
}
|
||||
|
||||
std::erase_if(this->m_favorites, [](const auto &entry) {
|
||||
std::erase_if(m_favorites, [](const auto &entry) {
|
||||
const auto &[path, favoritePattern] = entry;
|
||||
|
||||
return favoritePattern == nullptr;
|
||||
@@ -1216,20 +1216,20 @@ namespace hex::plugin::builtin::ui {
|
||||
|
||||
}
|
||||
|
||||
if (beginPatternTable(patterns, this->m_sortedPatterns, height)) {
|
||||
if (beginPatternTable(patterns, m_sortedPatterns, height)) {
|
||||
ImGui::TableHeadersRow();
|
||||
|
||||
this->m_showFavoriteStars = false;
|
||||
if (!this->m_favoritesUpdateTask.isRunning()) {
|
||||
m_showFavoriteStars = false;
|
||||
if (!m_favoritesUpdateTask.isRunning()) {
|
||||
int id = 1;
|
||||
bool doTableNextRow = false;
|
||||
|
||||
if (!this->m_favorites.empty() && !patterns.empty()) {
|
||||
if (!m_favorites.empty() && !patterns.empty()) {
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::PushID(id);
|
||||
if (ImGui::TreeNodeEx("hex.builtin.pattern_drawer.favorites"_lang, ImGuiTreeNodeFlags_SpanFullWidth)) {
|
||||
for (auto &[path, pattern] : this->m_favorites) {
|
||||
for (auto &[path, pattern] : m_favorites) {
|
||||
if (pattern == nullptr)
|
||||
continue;
|
||||
|
||||
@@ -1246,8 +1246,8 @@ namespace hex::plugin::builtin::ui {
|
||||
doTableNextRow = true;
|
||||
}
|
||||
|
||||
if (!this->m_groups.empty() && !patterns.empty()) {
|
||||
for (auto &[groupName, groupPatterns]: this->m_groups) {
|
||||
if (!m_groups.empty() && !patterns.empty()) {
|
||||
for (auto &[groupName, groupPatterns]: m_groups) {
|
||||
if (doTableNextRow) {
|
||||
ImGui::TableNextRow();
|
||||
}
|
||||
@@ -1276,9 +1276,9 @@ namespace hex::plugin::builtin::ui {
|
||||
}
|
||||
}
|
||||
|
||||
this->m_showFavoriteStars = true;
|
||||
m_showFavoriteStars = true;
|
||||
|
||||
for (auto &pattern : this->m_sortedPatterns) {
|
||||
for (auto &pattern : m_sortedPatterns) {
|
||||
ImGui::PushID(id);
|
||||
this->draw(*pattern);
|
||||
ImGui::PopID();
|
||||
@@ -1290,7 +1290,7 @@ namespace hex::plugin::builtin::ui {
|
||||
ImGui::EndTable();
|
||||
}
|
||||
|
||||
if (this->m_favoritesUpdateTask.isRunning()) {
|
||||
if (m_favoritesUpdateTask.isRunning()) {
|
||||
ImGuiExt::TextOverlay("hex.builtin.pattern_drawer.updating"_lang, ImGui::GetWindowPos() + ImGui::GetWindowSize() / 2);
|
||||
}
|
||||
}
|
||||
@@ -1299,23 +1299,23 @@ namespace hex::plugin::builtin::ui {
|
||||
std::scoped_lock lock(s_resetDrawMutex);
|
||||
|
||||
this->resetEditing();
|
||||
this->m_displayEnd.clear();
|
||||
this->m_visualizedPatterns.clear();
|
||||
this->m_currVisualizedPattern = nullptr;
|
||||
this->m_sortedPatterns.clear();
|
||||
this->m_lastVisualizerError.clear();
|
||||
this->m_currPatternPath.clear();
|
||||
m_displayEnd.clear();
|
||||
m_visualizedPatterns.clear();
|
||||
m_currVisualizedPattern = nullptr;
|
||||
m_sortedPatterns.clear();
|
||||
m_lastVisualizerError.clear();
|
||||
m_currPatternPath.clear();
|
||||
|
||||
this->m_favoritesUpdateTask.interrupt();
|
||||
m_favoritesUpdateTask.interrupt();
|
||||
|
||||
for (auto &[path, pattern] : this->m_favorites)
|
||||
for (auto &[path, pattern] : m_favorites)
|
||||
pattern = nullptr;
|
||||
for (auto &[groupName, patterns]: this->m_groups)
|
||||
for (auto &[groupName, patterns]: m_groups)
|
||||
for (auto &pattern: patterns)
|
||||
pattern = nullptr;
|
||||
|
||||
this->m_groups.clear();
|
||||
m_groups.clear();
|
||||
|
||||
this->m_favoritesUpdated = false;
|
||||
m_favoritesUpdated = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,16 +20,16 @@ namespace hex::script::loader {
|
||||
virtual bool loadAll() = 0;
|
||||
|
||||
void addScript(std::string name, std::function<void()> entryPoint) {
|
||||
this->m_scripts.emplace_back(std::move(name), std::move(entryPoint));
|
||||
m_scripts.emplace_back(std::move(name), std::move(entryPoint));
|
||||
}
|
||||
|
||||
const auto& getScripts() const {
|
||||
return this->m_scripts;
|
||||
return m_scripts;
|
||||
}
|
||||
|
||||
protected:
|
||||
void clearScripts() {
|
||||
this->m_scripts.clear();
|
||||
m_scripts.clear();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -166,7 +166,7 @@ namespace hex::script::loader {
|
||||
|
||||
component_entry_point_fn entryPoint = nullptr;
|
||||
u32 result = loadAssembly(
|
||||
this->m_assemblyLoaderPathString.c_str(),
|
||||
m_assemblyLoaderPathString.c_str(),
|
||||
dotnetType,
|
||||
dotnetTypeMethod,
|
||||
nullptr,
|
||||
@@ -179,7 +179,7 @@ namespace hex::script::loader {
|
||||
continue;
|
||||
}
|
||||
|
||||
this->m_loadAssembly = [entryPoint](const std::fs::path &path) -> bool {
|
||||
m_loadAssembly = [entryPoint](const std::fs::path &path) -> bool {
|
||||
auto string = wolv::util::toUTF8String(path);
|
||||
auto result = entryPoint(string.data(), string.size());
|
||||
|
||||
@@ -212,7 +212,7 @@ namespace hex::script::loader {
|
||||
continue;
|
||||
|
||||
this->addScript(entry.path().stem().string(), [this, scriptPath] {
|
||||
hex::unused(this->m_loadAssembly(scriptPath));
|
||||
hex::unused(m_loadAssembly(scriptPath));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ public:
|
||||
m_message(std::move(message)) { }
|
||||
|
||||
void drawContent() override {
|
||||
ImGuiExt::TextFormattedWrapped("{}", this->m_message.c_str());
|
||||
ImGuiExt::TextFormattedWrapped("{}", m_message.c_str());
|
||||
ImGui::NewLine();
|
||||
ImGui::Separator();
|
||||
|
||||
@@ -65,23 +65,23 @@ public:
|
||||
m_message(std::move(message)), m_maxSize(maxSize) { }
|
||||
|
||||
void drawContent() override {
|
||||
ImGuiExt::TextFormattedWrapped("{}", this->m_message.c_str());
|
||||
ImGuiExt::TextFormattedWrapped("{}", m_message.c_str());
|
||||
ImGui::NewLine();
|
||||
|
||||
ImGui::SetItemDefaultFocus();
|
||||
ImGui::SetNextItemWidth(-1);
|
||||
bool submitted = ImGui::InputText("##input", this->m_input, ImGuiInputTextFlags_EnterReturnsTrue);
|
||||
if (this->m_input.size() > this->m_maxSize)
|
||||
this->m_input.resize(this->m_maxSize);
|
||||
bool submitted = ImGui::InputText("##input", m_input, ImGuiInputTextFlags_EnterReturnsTrue);
|
||||
if (m_input.size() > m_maxSize)
|
||||
m_input.resize(m_maxSize);
|
||||
|
||||
ImGui::NewLine();
|
||||
ImGui::Separator();
|
||||
|
||||
auto width = ImGui::GetWindowWidth();
|
||||
ImGui::SetCursorPosX(width / 9);
|
||||
ImGui::BeginDisabled(this->m_input.empty());
|
||||
ImGui::BeginDisabled(m_input.empty());
|
||||
if (ImGui::Button("hex.builtin.common.okay"_lang, ImVec2(width / 3, 0)) || submitted) {
|
||||
s_inputTextBoxResult = this->m_input;
|
||||
s_inputTextBoxResult = m_input;
|
||||
this->close();
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
|
||||
@@ -12,35 +12,35 @@
|
||||
namespace hex::plugin::windows {
|
||||
|
||||
ViewTTYConsole::ViewTTYConsole() : View::Window("hex.windows.view.tty_console.name") {
|
||||
this->m_comPorts = getAvailablePorts();
|
||||
this->m_transmitDataBuffer.resize(0xFFF, 0x00);
|
||||
this->m_receiveDataBuffer.reserve(0xFFF);
|
||||
this->m_receiveDataBuffer.push_back(0x00);
|
||||
m_comPorts = getAvailablePorts();
|
||||
m_transmitDataBuffer.resize(0xFFF, 0x00);
|
||||
m_receiveDataBuffer.reserve(0xFFF);
|
||||
m_receiveDataBuffer.push_back(0x00);
|
||||
}
|
||||
|
||||
void ViewTTYConsole::drawContent() {
|
||||
ImGuiExt::Header("hex.windows.view.tty_console.config"_lang, true);
|
||||
|
||||
bool connected = this->m_portHandle != INVALID_HANDLE_VALUE;
|
||||
bool connected = m_portHandle != INVALID_HANDLE_VALUE;
|
||||
|
||||
ImGui::PushItemFlag(ImGuiItemFlags_Disabled, connected);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, connected ? 0.5F : 1.0F);
|
||||
|
||||
ImGui::Combo(
|
||||
"hex.windows.view.tty_console.port"_lang, &this->m_selectedPort, [](void *data, int idx) {
|
||||
"hex.windows.view.tty_console.port"_lang, &m_selectedPort, [](void *data, int idx) {
|
||||
auto &ports = *static_cast<std::vector<std::pair<std::string, std::string>> *>(data);
|
||||
|
||||
return ports[idx].first.c_str();
|
||||
},
|
||||
&this->m_comPorts,
|
||||
this->m_comPorts.size());
|
||||
&m_comPorts,
|
||||
m_comPorts.size());
|
||||
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("hex.windows.view.tty_console.reload"_lang))
|
||||
this->m_comPorts = getAvailablePorts();
|
||||
m_comPorts = getAvailablePorts();
|
||||
|
||||
ImGui::Combo(
|
||||
"hex.windows.view.tty_console.baud"_lang, &this->m_selectedBaudRate, [](void *data, int idx) {
|
||||
"hex.windows.view.tty_console.baud"_lang, &m_selectedBaudRate, [](void *data, int idx) {
|
||||
hex::unused(data);
|
||||
|
||||
return ViewTTYConsole::BaudRates[idx];
|
||||
@@ -49,7 +49,7 @@ namespace hex::plugin::windows {
|
||||
ViewTTYConsole::BaudRates.size());
|
||||
|
||||
ImGui::Combo(
|
||||
"hex.windows.view.tty_console.num_bits"_lang, &this->m_selectedNumBits, [](void *data, int idx) {
|
||||
"hex.windows.view.tty_console.num_bits"_lang, &m_selectedNumBits, [](void *data, int idx) {
|
||||
hex::unused(data);
|
||||
|
||||
return ViewTTYConsole::NumBits[idx];
|
||||
@@ -58,7 +58,7 @@ namespace hex::plugin::windows {
|
||||
ViewTTYConsole::NumBits.size());
|
||||
|
||||
ImGui::Combo(
|
||||
"hex.windows.view.tty_console.stop_bits"_lang, &this->m_selectedStopBits, [](void *data, int idx) {
|
||||
"hex.windows.view.tty_console.stop_bits"_lang, &m_selectedStopBits, [](void *data, int idx) {
|
||||
hex::unused(data);
|
||||
|
||||
return ViewTTYConsole::StopBits[idx];
|
||||
@@ -67,7 +67,7 @@ namespace hex::plugin::windows {
|
||||
ViewTTYConsole::StopBits.size());
|
||||
|
||||
ImGui::Combo(
|
||||
"hex.windows.view.tty_console.parity_bits"_lang, &this->m_selectedParityBits, [](void *data, int idx) {
|
||||
"hex.windows.view.tty_console.parity_bits"_lang, &m_selectedParityBits, [](void *data, int idx) {
|
||||
hex::unused(data);
|
||||
|
||||
return ViewTTYConsole::ParityBits[idx];
|
||||
@@ -75,14 +75,14 @@ namespace hex::plugin::windows {
|
||||
nullptr,
|
||||
ViewTTYConsole::ParityBits.size());
|
||||
|
||||
ImGui::Checkbox("hex.windows.view.tty_console.cts"_lang, &this->m_hasCTSFlowControl);
|
||||
ImGui::Checkbox("hex.windows.view.tty_console.cts"_lang, &m_hasCTSFlowControl);
|
||||
|
||||
ImGui::PopStyleVar();
|
||||
ImGui::PopItemFlag();
|
||||
|
||||
ImGui::NewLine();
|
||||
|
||||
if (this->m_portHandle == INVALID_HANDLE_VALUE) {
|
||||
if (m_portHandle == INVALID_HANDLE_VALUE) {
|
||||
if (ImGui::Button("hex.windows.view.tty_console.connect"_lang))
|
||||
if (!this->connect())
|
||||
RequestOpenErrorPopup::post("hex.windows.view.tty_console.connect_error"_lang);
|
||||
@@ -94,15 +94,15 @@ namespace hex::plugin::windows {
|
||||
ImGui::NewLine();
|
||||
|
||||
if (ImGui::Button("hex.windows.view.tty_console.clear"_lang)) {
|
||||
std::scoped_lock lock(this->m_receiveBufferMutex);
|
||||
std::scoped_lock lock(m_receiveBufferMutex);
|
||||
|
||||
this->m_receiveDataBuffer.clear();
|
||||
this->m_wrapPositions.clear();
|
||||
m_receiveDataBuffer.clear();
|
||||
m_wrapPositions.clear();
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::Checkbox("hex.windows.view.tty_console.auto_scroll"_lang, &this->m_shouldAutoScroll);
|
||||
ImGui::Checkbox("hex.windows.view.tty_console.auto_scroll"_lang, &m_shouldAutoScroll);
|
||||
|
||||
ImGuiExt::Header("hex.windows.view.tty_console.console"_lang);
|
||||
|
||||
@@ -110,21 +110,21 @@ namespace hex::plugin::windows {
|
||||
consoleSize.y -= ImGui::GetTextLineHeight() + ImGui::GetStyle().FramePadding.y * 4;
|
||||
if (ImGui::BeginChild("##scrolling", consoleSize, true, ImGuiWindowFlags_HorizontalScrollbar)) {
|
||||
ImGuiListClipper clipper;
|
||||
clipper.Begin(this->m_wrapPositions.size(), ImGui::GetTextLineHeight());
|
||||
clipper.Begin(m_wrapPositions.size(), ImGui::GetTextLineHeight());
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(4, 1));
|
||||
while (clipper.Step()) {
|
||||
std::scoped_lock lock(this->m_receiveBufferMutex);
|
||||
std::scoped_lock lock(m_receiveBufferMutex);
|
||||
|
||||
for (int i = clipper.DisplayStart + 1; i < clipper.DisplayEnd; i++) {
|
||||
ImGui::TextUnformatted(this->m_receiveDataBuffer.data() + this->m_wrapPositions[i - 1], this->m_receiveDataBuffer.data() + this->m_wrapPositions[i]);
|
||||
ImGui::TextUnformatted(m_receiveDataBuffer.data() + m_wrapPositions[i - 1], m_receiveDataBuffer.data() + m_wrapPositions[i]);
|
||||
}
|
||||
|
||||
if (!this->m_receiveDataBuffer.empty() && !this->m_wrapPositions.empty())
|
||||
if (static_cast<size_t>(clipper.DisplayEnd) >= this->m_wrapPositions.size() - 1)
|
||||
ImGui::TextUnformatted(this->m_receiveDataBuffer.data() + this->m_wrapPositions.back());
|
||||
if (!m_receiveDataBuffer.empty() && !m_wrapPositions.empty())
|
||||
if (static_cast<size_t>(clipper.DisplayEnd) >= m_wrapPositions.size() - 1)
|
||||
ImGui::TextUnformatted(m_receiveDataBuffer.data() + m_wrapPositions.back());
|
||||
|
||||
if (this->m_shouldAutoScroll && ImGui::GetScrollY() >= ImGui::GetScrollMaxY()) {
|
||||
if (m_shouldAutoScroll && ImGui::GetScrollY() >= ImGui::GetScrollMaxY()) {
|
||||
ImGui::SetScrollHereY(0.0F);
|
||||
}
|
||||
}
|
||||
@@ -133,18 +133,18 @@ namespace hex::plugin::windows {
|
||||
ImGui::EndChild();
|
||||
|
||||
ImGui::PushItemWidth(-1);
|
||||
if (ImGui::InputText("##transmit", this->m_transmitDataBuffer.data(), this->m_transmitDataBuffer.size() - 2, ImGuiInputTextFlags_EnterReturnsTrue)) {
|
||||
auto size = strlen(this->m_transmitDataBuffer.data());
|
||||
if (ImGui::InputText("##transmit", m_transmitDataBuffer.data(), m_transmitDataBuffer.size() - 2, ImGuiInputTextFlags_EnterReturnsTrue)) {
|
||||
auto size = strlen(m_transmitDataBuffer.data());
|
||||
|
||||
this->m_transmitDataBuffer[size + 0] = '\n';
|
||||
this->m_transmitDataBuffer[size + 1] = 0x00;
|
||||
m_transmitDataBuffer[size + 0] = '\n';
|
||||
m_transmitDataBuffer[size + 1] = 0x00;
|
||||
|
||||
this->transmitData(this->m_transmitDataBuffer);
|
||||
this->transmitData(m_transmitDataBuffer);
|
||||
ImGui::SetKeyboardFocusHere(0);
|
||||
}
|
||||
ImGui::PopItemWidth();
|
||||
|
||||
if (ImGui::IsMouseReleased(ImGuiMouseButton_Right) && ImGui::IsItemHovered() && this->m_portHandle != INVALID_HANDLE_VALUE && !this->m_transmitting)
|
||||
if (ImGui::IsMouseReleased(ImGuiMouseButton_Right) && ImGui::IsItemHovered() && m_portHandle != INVALID_HANDLE_VALUE && !m_transmitting)
|
||||
ImGui::OpenPopup("ConsoleMenu");
|
||||
|
||||
if (ImGui::BeginPopup("ConsoleMenu")) {
|
||||
@@ -183,11 +183,11 @@ namespace hex::plugin::windows {
|
||||
}
|
||||
|
||||
bool ViewTTYConsole::connect() {
|
||||
if (this->m_comPorts.empty() || static_cast<size_t>(this->m_selectedPort) >= this->m_comPorts.size()) {
|
||||
if (m_comPorts.empty() || static_cast<size_t>(m_selectedPort) >= m_comPorts.size()) {
|
||||
RequestOpenErrorPopup::post("hex.windows.view.tty_console.no_available_port"_lang);
|
||||
return true; // If false, connect_error error popup will override this error popup
|
||||
}
|
||||
this->m_portHandle = ::CreateFile((R"(\\.\)" + this->m_comPorts[this->m_selectedPort].first).c_str(),
|
||||
m_portHandle = ::CreateFile((R"(\\.\)" + m_comPorts[m_selectedPort].first).c_str(),
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
0,
|
||||
nullptr,
|
||||
@@ -195,27 +195,27 @@ namespace hex::plugin::windows {
|
||||
FILE_FLAG_OVERLAPPED,
|
||||
nullptr);
|
||||
|
||||
if (this->m_portHandle == INVALID_HANDLE_VALUE)
|
||||
if (m_portHandle == INVALID_HANDLE_VALUE)
|
||||
return false;
|
||||
|
||||
auto closeHandle = SCOPE_GUARD { CloseHandle(this->m_portHandle); };
|
||||
auto closeHandle = SCOPE_GUARD { CloseHandle(m_portHandle); };
|
||||
|
||||
if (!::SetupComm(this->m_portHandle, 10000, 10000))
|
||||
if (!::SetupComm(m_portHandle, 10000, 10000))
|
||||
return false;
|
||||
|
||||
DCB serialParams;
|
||||
serialParams.DCBlength = sizeof(DCB);
|
||||
|
||||
if (!::GetCommState(this->m_portHandle, &serialParams))
|
||||
if (!::GetCommState(m_portHandle, &serialParams))
|
||||
return false;
|
||||
|
||||
serialParams.BaudRate = std::stoi(ViewTTYConsole::BaudRates[this->m_selectedBaudRate]);
|
||||
serialParams.ByteSize = std::stoi(ViewTTYConsole::NumBits[this->m_selectedNumBits]);
|
||||
serialParams.StopBits = this->m_selectedStopBits;
|
||||
serialParams.Parity = this->m_selectedParityBits;
|
||||
serialParams.fOutxCtsFlow = this->m_hasCTSFlowControl;
|
||||
serialParams.BaudRate = std::stoi(ViewTTYConsole::BaudRates[m_selectedBaudRate]);
|
||||
serialParams.ByteSize = std::stoi(ViewTTYConsole::NumBits[m_selectedNumBits]);
|
||||
serialParams.StopBits = m_selectedStopBits;
|
||||
serialParams.Parity = m_selectedParityBits;
|
||||
serialParams.fOutxCtsFlow = m_hasCTSFlowControl;
|
||||
|
||||
if (!::SetCommState(this->m_portHandle, &serialParams))
|
||||
if (!::SetCommState(m_portHandle, &serialParams))
|
||||
return false;
|
||||
|
||||
COMMTIMEOUTS timeouts;
|
||||
@@ -225,12 +225,12 @@ namespace hex::plugin::windows {
|
||||
timeouts.WriteTotalTimeoutConstant = 500;
|
||||
timeouts.WriteTotalTimeoutMultiplier = 100;
|
||||
|
||||
if (!::SetCommTimeouts(this->m_portHandle, &timeouts))
|
||||
if (!::SetCommTimeouts(m_portHandle, &timeouts))
|
||||
return false;
|
||||
|
||||
closeHandle.release();
|
||||
|
||||
this->m_receiveThread = std::jthread([this](const std::stop_token &token) {
|
||||
m_receiveThread = std::jthread([this](const std::stop_token &token) {
|
||||
bool waitingOnRead = false;
|
||||
OVERLAPPED overlapped = { };
|
||||
|
||||
@@ -238,19 +238,19 @@ namespace hex::plugin::windows {
|
||||
ON_SCOPE_EXIT { ::CloseHandle(&overlapped); };
|
||||
|
||||
auto addByte = [this](char byte) {
|
||||
std::scoped_lock lock(this->m_receiveBufferMutex);
|
||||
std::scoped_lock lock(m_receiveBufferMutex);
|
||||
|
||||
if (byte >= 0x20 && byte <= 0x7E) {
|
||||
this->m_receiveDataBuffer.back() = byte;
|
||||
this->m_receiveDataBuffer.push_back(0x00);
|
||||
m_receiveDataBuffer.back() = byte;
|
||||
m_receiveDataBuffer.push_back(0x00);
|
||||
} else if (byte == '\n' || byte == '\r') {
|
||||
if (this->m_receiveDataBuffer.empty())
|
||||
if (m_receiveDataBuffer.empty())
|
||||
return;
|
||||
|
||||
u32 wrapPos = this->m_receiveDataBuffer.size() - 1;
|
||||
u32 wrapPos = m_receiveDataBuffer.size() - 1;
|
||||
|
||||
if (this->m_wrapPositions.empty() || this->m_wrapPositions.back() != wrapPos)
|
||||
this->m_wrapPositions.push_back(wrapPos);
|
||||
if (m_wrapPositions.empty() || m_wrapPositions.back() != wrapPos)
|
||||
m_wrapPositions.push_back(wrapPos);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -259,7 +259,7 @@ namespace hex::plugin::windows {
|
||||
|
||||
char byte = 0;
|
||||
if (!waitingOnRead) {
|
||||
if (::ReadFile(this->m_portHandle, &byte, sizeof(char), &bytesRead, &overlapped)) {
|
||||
if (::ReadFile(m_portHandle, &byte, sizeof(char), &bytesRead, &overlapped)) {
|
||||
addByte(byte);
|
||||
} else if (::GetLastError() == ERROR_IO_PENDING) {
|
||||
waitingOnRead = true;
|
||||
@@ -268,7 +268,7 @@ namespace hex::plugin::windows {
|
||||
byte = 0;
|
||||
switch (::WaitForSingleObject(overlapped.hEvent, 500)) {
|
||||
case WAIT_OBJECT_0:
|
||||
if (::GetOverlappedResult(this->m_portHandle, &overlapped, &bytesRead, false)) {
|
||||
if (::GetOverlappedResult(m_portHandle, &overlapped, &bytesRead, false)) {
|
||||
addByte(byte);
|
||||
waitingOnRead = false;
|
||||
}
|
||||
@@ -283,18 +283,18 @@ namespace hex::plugin::windows {
|
||||
}
|
||||
|
||||
bool ViewTTYConsole::disconnect() {
|
||||
::SetCommMask(this->m_portHandle, EV_TXEMPTY);
|
||||
this->m_receiveThread.request_stop();
|
||||
this->m_receiveThread.join();
|
||||
::SetCommMask(m_portHandle, EV_TXEMPTY);
|
||||
m_receiveThread.request_stop();
|
||||
m_receiveThread.join();
|
||||
|
||||
::CloseHandle(this->m_portHandle);
|
||||
this->m_portHandle = INVALID_HANDLE_VALUE;
|
||||
::CloseHandle(m_portHandle);
|
||||
m_portHandle = INVALID_HANDLE_VALUE;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ViewTTYConsole::transmitData(std::vector<char> &data) {
|
||||
if (this->m_transmitting)
|
||||
if (m_transmitting)
|
||||
return;
|
||||
|
||||
TaskManager::createBackgroundTask("Transmitting data", [&, this](auto&) {
|
||||
@@ -303,19 +303,19 @@ namespace hex::plugin::windows {
|
||||
overlapped.hEvent = ::CreateEvent(nullptr, true, false, nullptr);
|
||||
ON_SCOPE_EXIT { ::CloseHandle(&overlapped); };
|
||||
|
||||
this->m_transmitting = true;
|
||||
m_transmitting = true;
|
||||
|
||||
DWORD bytesWritten = 0;
|
||||
if (!::WriteFile(this->m_portHandle, data.data(), strlen(data.data()), &bytesWritten, &overlapped)) {
|
||||
if (!::WriteFile(m_portHandle, data.data(), strlen(data.data()), &bytesWritten, &overlapped)) {
|
||||
if (::GetLastError() == ERROR_IO_PENDING) {
|
||||
::GetOverlappedResult(this->m_portHandle, &overlapped, &bytesWritten, true);
|
||||
::GetOverlappedResult(m_portHandle, &overlapped, &bytesWritten, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (bytesWritten > 0)
|
||||
data[0] = 0x00;
|
||||
|
||||
this->m_transmitting = false;
|
||||
m_transmitting = false;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user