1
0
mirror of synced 2024-11-15 11:33:23 +01:00
ImHex/source/views/view_strings.cpp

204 lines
8.8 KiB
C++
Raw Normal View History

2020-11-15 01:42:43 +01:00
#include "views/view_strings.hpp"
#include <hex/providers/provider.hpp>
#include <hex/helpers/utils.hpp>
2020-11-15 01:42:43 +01:00
#include <cstring>
2021-02-22 10:16:58 +01:00
#include <thread>
2020-11-15 01:42:43 +01:00
#include <llvm/Demangle/Demangle.h>
2021-02-22 10:16:58 +01:00
#include <imgui_imhex_extensions.h>
using namespace std::literals::string_literals;
2020-11-15 01:42:43 +01:00
namespace hex {
ViewStrings::ViewStrings() : View("hex.view.strings.name"_lang) {
2021-01-21 10:53:12 +01:00
View::subscribeEvent(Events::DataChanged, [this](auto){
this->m_foundStrings.clear();
2020-11-15 01:42:43 +01:00
});
2021-02-17 14:47:25 +01:00
this->m_filter.resize(0xFFFF, 0x00);
2020-11-15 01:42:43 +01:00
}
ViewStrings::~ViewStrings() {
View::unsubscribeEvent(Events::DataChanged);
}
void ViewStrings::createStringContextMenu(const FoundString &foundString) {
if (ImGui::TableGetColumnFlags(2) == ImGuiTableColumnFlags_IsHovered && ImGui::IsMouseReleased(1) && ImGui::IsItemHovered()) {
ImGui::OpenPopup("StringContextMenu");
this->m_selectedString = foundString.string;
}
if (ImGui::BeginPopup("StringContextMenu")) {
if (ImGui::MenuItem("hex.view.strings.copy"_lang)) {
ImGui::SetClipboardText(this->m_selectedString.c_str());
}
ImGui::Separator();
if (ImGui::MenuItem("hex.view.strings.demangle"_lang)) {
this->m_demangledName = llvm::demangle(this->m_selectedString);
if (!this->m_demangledName.empty())
View::doLater([]{ ImGui::OpenPopup("hex.view.strings.demangle.name"_lang); });
}
ImGui::EndPopup();
}
}
2021-02-22 10:16:58 +01:00
void ViewStrings::searchStrings() {
this->m_foundStrings.clear();
this->m_searching = true;
2021-02-22 10:16:58 +01:00
std::thread([this] {
auto provider = SharedData::currentProvider;
2020-11-15 01:42:43 +01:00
std::vector<u8> buffer(1024, 0x00);
u32 foundCharacters = 0;
for (u64 offset = 0; offset < provider->getSize(); offset += buffer.size()) {
size_t readSize = std::min(u64(buffer.size()), provider->getSize() - offset);
provider->read(offset, buffer.data(), readSize);
2020-11-15 01:42:43 +01:00
for (u32 i = 0; i < readSize; i++) {
2020-11-15 01:42:43 +01:00
if (buffer[i] >= 0x20 && buffer[i] <= 0x7E)
foundCharacters++;
else {
if (foundCharacters >= this->m_minimumLength) {
FoundString foundString;
foundString.offset = offset + i - foundCharacters;
foundString.size = foundCharacters;
foundString.string.reserve(foundCharacters);
foundString.string.resize(foundCharacters);
provider->read(foundString.offset, foundString.string.data(), foundCharacters);
2020-11-15 01:42:43 +01:00
this->m_foundStrings.push_back(foundString);
}
foundCharacters = 0;
}
}
}
2021-02-22 10:16:58 +01:00
this->m_searching = false;
}).detach();
2020-11-15 01:42:43 +01:00
2021-02-22 10:16:58 +01:00
}
void ViewStrings::drawContent() {
auto provider = SharedData::currentProvider;
if (ImGui::Begin("hex.view.strings.name"_lang, &this->getWindowOpenState(), ImGuiWindowFlags_NoCollapse)) {
if (provider != nullptr && provider->isReadable()) {
2021-02-22 10:16:58 +01:00
ImGui::Disabled([this]{
if (ImGui::InputInt("hex.view.strings.min_length"_lang, &this->m_minimumLength, 1, 0))
this->m_foundStrings.clear();
ImGui::InputText("hex.view.strings.filter"_lang, this->m_filter.data(), this->m_filter.size());
if (ImGui::Button("hex.view.strings.extract"_lang))
this->searchStrings();
}, this->m_searching);
if (this->m_searching) {
ImGui::SameLine();
ImGui::Text("hex.view.strings.searching"_lang, "|/-\\"[u8(ImGui::GetTime() * 20) % 4]);
}
2020-11-15 03:51:59 +01:00
ImGui::Separator();
ImGui::NewLine();
if (ImGui::BeginTable("##strings", 3,
ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_Sortable |
ImGuiTableFlags_Reorderable | ImGuiTableFlags_RowBg | ImGuiTableFlags_ScrollY)) {
ImGui::TableSetupScrollFreeze(0, 1);
ImGui::TableSetupColumn("hex.view.strings.offset"_lang, 0, -1, ImGui::GetID("offset"));
ImGui::TableSetupColumn("hex.view.strings.size"_lang, 0, -1, ImGui::GetID("size"));
ImGui::TableSetupColumn("hex.view.strings.string"_lang, 0, -1, ImGui::GetID("string"));
2020-11-15 03:51:59 +01:00
auto sortSpecs = ImGui::TableGetSortSpecs();
if (sortSpecs->SpecsDirty) {
std::sort(this->m_foundStrings.begin(), this->m_foundStrings.end(),
[&sortSpecs](FoundString &left, FoundString &right) -> bool {
2021-02-17 14:47:25 +01:00
if (sortSpecs->Specs->ColumnUserID == ImGui::GetID("offset")) {
2020-11-15 03:51:59 +01:00
if (sortSpecs->Specs->SortDirection == ImGuiSortDirection_Ascending)
return left.offset > right.offset;
else
return left.offset < right.offset;
2021-02-17 14:47:25 +01:00
} else if (sortSpecs->Specs->ColumnUserID == ImGui::GetID("size")) {
2020-11-15 03:51:59 +01:00
if (sortSpecs->Specs->SortDirection == ImGuiSortDirection_Ascending)
return left.size > right.size;
else
return left.size < right.size;
2021-02-17 14:47:25 +01:00
} else if (sortSpecs->Specs->ColumnUserID == ImGui::GetID("string")) {
2020-11-15 03:51:59 +01:00
if (sortSpecs->Specs->SortDirection == ImGuiSortDirection_Ascending)
return left.string > right.string;
else
return left.string < right.string;
}
return false;
});
sortSpecs->SpecsDirty = false;
}
2020-11-15 01:42:43 +01:00
2020-11-15 03:51:59 +01:00
ImGui::TableHeadersRow();
ImGuiListClipper clipper;
2020-11-20 11:56:37 +01:00
clipper.Begin(this->m_foundStrings.size());
while (clipper.Step()) {
for (u64 i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) {
auto &foundString = this->m_foundStrings[i];
2021-02-17 14:47:25 +01:00
if (strlen(this->m_filter.data()) != 0 &&
foundString.string.find(this->m_filter.data()) == std::string::npos)
2020-11-20 11:56:37 +01:00
continue;
2020-11-23 13:08:24 +01:00
ImGui::TableNextRow();
2020-11-20 11:56:37 +01:00
ImGui::TableNextColumn();
if (ImGui::Selectable(("##StringLine"s + std::to_string(i)).c_str(), false, ImGuiSelectableFlags_SpanAllColumns)) {
Region selectRegion = { foundString.offset, foundString.size };
2021-01-21 10:53:12 +01:00
View::postEvent(Events::SelectionChangeRequest, selectRegion);
}
ImGui::PushID(i + 1);
createStringContextMenu(foundString);
ImGui::PopID();
ImGui::SameLine();
2020-11-20 11:56:37 +01:00
ImGui::Text("0x%08lx : 0x%08lx", foundString.offset, foundString.offset + foundString.size);
ImGui::TableNextColumn();
ImGui::Text("0x%04lx", foundString.size);
ImGui::TableNextColumn();
ImGui::Text("%s", foundString.string.c_str());
}
2020-11-15 03:51:59 +01:00
}
clipper.End();
2020-11-15 01:42:43 +01:00
2020-11-15 03:51:59 +01:00
ImGui::EndTable();
2020-11-15 01:42:43 +01:00
}
}
}
ImGui::End();
if (ImGui::BeginPopup("hex.view.strings.demangle.title"_lang)) {
if (ImGui::BeginChild("##scrolling", ImVec2(500, 150))) {
2021-02-17 14:47:25 +01:00
ImGui::TextUnformatted("hex.view.strings.demangle.title"_lang);
ImGui::Separator();
ImGui::TextWrapped("%s", this->m_demangledName.c_str());
ImGui::EndChild();
ImGui::NewLine();
if (ImGui::Button("hex.view.strings.demangle.copy"_lang))
ImGui::SetClipboardText(this->m_demangledName.c_str());
}
ImGui::EndPopup();
}
2020-11-15 01:42:43 +01:00
}
void ViewStrings::drawMenu() {
2020-11-15 01:42:43 +01:00
}
}