1
0
mirror of synced 2025-01-18 09:04:52 +01:00

feat: Added primitive replace feature to find view

This commit is contained in:
WerWolv 2023-05-28 11:50:10 +02:00
parent ea756e620e
commit c8c3f5e753
4 changed files with 87 additions and 10 deletions

View File

@ -37,6 +37,9 @@ namespace hex {
void ShortcutManager::process(const std::unique_ptr<View> &currentView, bool ctrl, bool alt, bool shift, bool super, bool focused, u32 keyCode) {
Shortcut pressedShortcut = getShortcut(ctrl, alt, shift, super, focused, keyCode);
if (ImGui::GetIO().WantTextInput)
return;
if (currentView->m_shortcuts.contains(pressedShortcut))
currentView->m_shortcuts[pressedShortcut]();
}

View File

@ -28,6 +28,7 @@ namespace hex::plugin::builtin {
Region region;
enum class DecodeType { ASCII, Binary, UTF16, Unsigned, Signed, Float, Double } decodeType;
std::endian endian = std::endian::native;
bool selected;
};
struct BinaryPattern {
@ -104,6 +105,7 @@ namespace hex::plugin::builtin {
TaskHolder m_searchTask, m_filterTask;
bool m_settingsValid = false;
std::string m_replaceBuffer;
private:
static std::vector<Occurrence> searchStrings(Task &task, prv::Provider *provider, Region searchRegion, const SearchSettings::Strings &settings);
@ -112,6 +114,8 @@ namespace hex::plugin::builtin {
static std::vector<Occurrence> searchBinaryPattern(Task &task, prv::Provider *provider, Region searchRegion, const SearchSettings::BinaryPattern &settings);
static std::vector<Occurrence> searchValue(Task &task, prv::Provider *provider, Region searchRegion, const SearchSettings::Value &settings);
void drawContextMenu(Occurrence &target, const std::string &value);
static std::vector<BinaryPattern> parseBinaryPatternString(std::string string);
static std::tuple<bool, std::variant<u64, i64, float, double>, size_t> parseNumericValueInput(const std::string &input, SearchSettings::Value::Type type);

View File

@ -677,6 +677,9 @@
"hex.builtin.view.find.binary_pattern.alignment": "Alignment",
"hex.builtin.view.find.context.copy": "Copy Value",
"hex.builtin.view.find.context.copy_demangle": "Copy Demangled Value",
"hex.builtin.view.find.context.replace": "Replace",
"hex.builtin.view.find.context.replace.ascii": "ASCII",
"hex.builtin.view.find.context.replace.hex": "Hex",
"hex.builtin.view.find.demangled": "Demangled",
"hex.builtin.view.find.name": "Find",
"hex.builtin.view.find.regex": "Regex",

View File

@ -91,6 +91,16 @@ namespace hex::plugin::builtin {
ImGui::EndTooltip();
});
ShortcutManager::addShortcut(this, CTRLCMD + Keys::A, [this] {
if (this->m_filterTask.isRunning())
return;
if (this->m_searchTask.isRunning())
return;
for (auto &occurrence : *this->m_sortedOccurrences)
occurrence.selected = true;
});
}
template<typename Type, typename StorageType>
@ -223,8 +233,8 @@ namespace hex::plugin::builtin {
countedCharacters++;
if (!validChar || startAddress + countedCharacters == endAddress) {
if (countedCharacters >= size_t(settings.minLength)) {
if (!(settings.nullTermination && byte != 0x00)) {
results.push_back(Occurrence { Region { startAddress, countedCharacters }, decodeType, endian });
if (!settings.nullTermination || byte == 0x00) {
results.push_back(Occurrence { Region { startAddress, countedCharacters }, decodeType, endian, false });
}
}
@ -261,7 +271,7 @@ namespace hex::plugin::builtin {
auto address = occurrence.getAddress();
reader.seek(address + 1);
results.push_back(Occurrence{ Region { address, bytes.size() }, Occurrence::DecodeType::Binary, std::endian::native });
results.push_back(Occurrence{ Region { address, bytes.size() }, Occurrence::DecodeType::Binary, std::endian::native, false });
progress = address - searchRegion.getStartAddress();
}
@ -322,7 +332,7 @@ namespace hex::plugin::builtin {
if (matchedBytes == settings.pattern.getSize()) {
auto occurrenceAddress = it.getAddress() - (patternSize - 1);
results.push_back(Occurrence { Region { occurrenceAddress, patternSize }, Occurrence::DecodeType::Binary, std::endian::native });
results.push_back(Occurrence { Region { occurrenceAddress, patternSize }, Occurrence::DecodeType::Binary, std::endian::native, false });
it.setAddress(occurrenceAddress);
matchedBytes = 0;
}
@ -348,7 +358,7 @@ namespace hex::plugin::builtin {
}
if (match)
results.push_back(Occurrence { Region { address, patternSize }, Occurrence::DecodeType::Binary, std::endian::native });
results.push_back(Occurrence { Region { address, patternSize }, Occurrence::DecodeType::Binary, std::endian::native, false });
}
}
@ -419,7 +429,7 @@ namespace hex::plugin::builtin {
}
}();
results.push_back(Occurrence { Region { address, size }, decodeType, settings.endian });
results.push_back(Occurrence { Region { address, size }, decodeType, settings.endian, false });
}
}
@ -507,9 +517,11 @@ namespace hex::plugin::builtin {
return result;
}
static void drawContextMenu(const std::string &value) {
void ViewFind::drawContextMenu(Occurrence &target, const std::string &value) {
if (ImGui::IsMouseClicked(ImGuiMouseButton_Right) && ImGui::IsItemHovered()) {
ImGui::OpenPopup("FindContextMenu");
target.selected = true;
this->m_replaceBuffer.clear();
}
if (ImGui::BeginPopup("FindContextMenu")) {
@ -517,6 +529,53 @@ namespace hex::plugin::builtin {
ImGui::SetClipboardText(value.c_str());
if (ImGui::MenuItem("hex.builtin.view.find.context.copy_demangle"_lang))
ImGui::SetClipboardText(llvm::demangle(value).c_str());
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)) {
ImGui::InputTextIcon("##replace_input", ICON_VS_SYMBOL_NAMESPACE, this->m_replaceBuffer);
ImGui::BeginDisabled(this->m_replaceBuffer.empty());
if (ImGui::Button("hex.builtin.view.find.context.replace"_lang)) {
for (const auto &occurrence : *this->m_sortedOccurrences) {
if (occurrence.selected) {
auto bytes = decodeByteString(this->m_replaceBuffer);
size_t size = std::min<size_t>(occurrence.region.size, bytes.size());
auto provider = ImHexApi::Provider::get();
provider->write(occurrence.region.getStartAddress(), bytes.data(), size);
}
}
}
ImGui::EndDisabled();
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem("hex.builtin.view.find.context.replace.ascii"_lang)) {
ImGui::InputTextIcon("##replace_input", ICON_VS_SYMBOL_KEY, this->m_replaceBuffer);
ImGui::BeginDisabled(this->m_replaceBuffer.empty());
if (ImGui::Button("hex.builtin.view.find.context.replace"_lang)) {
for (const auto &occurrence : *this->m_sortedOccurrences) {
if (occurrence.selected) {
size_t size = std::min<size_t>(occurrence.region.size, this->m_replaceBuffer.size());
auto provider = ImHexApi::Provider::get();
provider->write(occurrence.region.getStartAddress(), this->m_replaceBuffer.data(), size);
}
}
}
ImGui::EndDisabled();
ImGui::EndTabItem();
}
ImGui::EndTabBar();
}
ImGui::EndMenu();
}
ImGui::EndPopup();
}
@ -840,9 +899,17 @@ namespace hex::plugin::builtin {
auto value = this->decodeValue(provider, foundItem, 256);
ImGui::TextFormatted("{}", value);
ImGui::SameLine();
if (ImGui::Selectable("##line", false, ImGuiSelectableFlags_SpanAllColumns))
ImHexApi::HexEditor::setSelection(foundItem.region.getStartAddress(), foundItem.region.getSize());
drawContextMenu(value);
if (ImGui::Selectable("##line", foundItem.selected, ImGuiSelectableFlags_SpanAllColumns)) {
if (ImGui::GetIO().KeyCtrl) {
foundItem.selected = !foundItem.selected;
} else {
for (auto &occurrence : *this->m_sortedOccurrences)
occurrence.selected = false;
foundItem.selected = true;
ImHexApi::HexEditor::setSelection(foundItem.region.getStartAddress(), foundItem.region.getSize());
}
}
drawContextMenu(foundItem, value);
ImGui::PopID();
}