feat: Added primitive replace feature to find view
This commit is contained in:
parent
ea756e620e
commit
c8c3f5e753
@ -37,6 +37,9 @@ namespace hex {
|
||||
void ShortcutManager::process(const std::unique_ptr<View> ¤tView, 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]();
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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",
|
||||
|
@ -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();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user