1
0
mirror of synced 2025-01-31 12:03:46 +01:00

ux: Make New File command create a new file in memory

Closes #792
This commit is contained in:
WerWolv 2022-10-21 12:01:28 +02:00
parent 241b93aab5
commit 6a8611d98d
16 changed files with 218 additions and 5 deletions

View File

@ -30,6 +30,7 @@ add_library(${PROJECT_NAME} SHARED
source/content/providers/disk_provider.cpp
source/content/providers/intel_hex_provider.cpp
source/content/providers/motorola_srec_provider.cpp
source/content/providers/memory_file_provider.cpp
source/content/views/view_hex_editor.cpp
source/content/views/view_pattern_editor.cpp

View File

@ -0,0 +1,48 @@
#pragma once
#include <hex/providers/provider.hpp>
namespace hex::plugin::builtin::prv {
class MemoryFileProvider : public hex::prv::Provider {
public:
explicit MemoryFileProvider() = default;
~MemoryFileProvider() override = default;
[[nodiscard]] bool isAvailable() const override { return true; }
[[nodiscard]] bool isReadable() const override { return true; }
[[nodiscard]] bool isWritable() const override { return true; }
[[nodiscard]] bool isResizable() const override { return true; }
[[nodiscard]] bool isSavable() const override { return true; }
[[nodiscard]] bool open() override;
void close() override { }
void readRaw(u64 offset, void *buffer, size_t size) override;
void writeRaw(u64 offset, const void *buffer, size_t size) override;
[[nodiscard]] size_t getActualSize() const override { return this->m_data.size(); }
void resize(size_t newSize) override;
void insert(u64 offset, size_t size) override;
void remove(u64 offset, size_t size) override;
void save() override;
void saveAs(const std::fs::path &path) override;
[[nodiscard]] std::string getName() const override { return "hex.builtin.provider.mem_file.unsaved"; }
[[nodiscard]] std::vector<std::pair<std::string, std::string>> getDataInformation() const override { return { }; }
[[nodiscard]] std::string getTypeName() const override {
return "hex.builtin.provider.mem_file";
}
[[nodiscard]] std::pair<Region, bool> getRegionValidity(u64 address) const override;
void loadSettings(const nlohmann::json &settings) override { hex::unused(settings); }
[[nodiscard]] nlohmann::json storeSettings(nlohmann::json settings) const override { return settings; }
private:
std::vector<u8> m_data;
};
}

View File

@ -21,7 +21,11 @@ namespace hex::plugin::builtin {
bool taskRunning = TaskManager::getRunningTaskCount() > 0;
if (ImGui::MenuItem("hex.builtin.menu.file.create_file"_lang, "CTRL + N", false, !taskRunning)) {
EventManager::post<RequestOpenWindow>("Create File");
auto newProvider = hex::ImHexApi::Provider::createProvider("hex.builtin.provider.mem_file", true);
if (newProvider != nullptr && !newProvider->open())
hex::ImHexApi::Provider::remove(newProvider);
else
EventManager::post<EventProviderOpened>(newProvider);
}
if (ImGui::MenuItem("hex.builtin.menu.file.open_file"_lang, "CTRL + O", false, !taskRunning)) {

View File

@ -6,6 +6,7 @@
#include "content/providers/disk_provider.hpp"
#include "content/providers/intel_hex_provider.hpp"
#include "content/providers/motorola_srec_provider.hpp"
#include "content/providers/memory_file_provider.hpp"
#include <hex/api/project_file_manager.hpp>
#include <nlohmann/json.hpp>
@ -21,6 +22,7 @@ namespace hex::plugin::builtin {
ContentRegistry::Provider::add<prv::GDBProvider>();
ContentRegistry::Provider::add<prv::IntelHexProvider>();
ContentRegistry::Provider::add<prv::MotorolaSRECProvider>();
ContentRegistry::Provider::add<prv::MemoryFileProvider>(false);
ProjectFile::registerHandler({
.basePath = "providers",

View File

@ -145,6 +145,7 @@ namespace hex::plugin::builtin::prv {
this->resize(newSize);
Provider::insert(offset, size);
Provider::remove(offset, size);
}
size_t FileProvider::getActualSize() const {

View File

@ -0,0 +1,130 @@
#include "content/providers/memory_file_provider.hpp"
#include "content/providers/file_provider.hpp"
#include <cstring>
#include <hex/api/imhex_api.hpp>
#include <hex/api/localization.hpp>
#include <hex/api/event.hpp>
#include <hex/helpers/file.hpp>
namespace hex::plugin::builtin::prv {
bool MemoryFileProvider::open() {
this->m_data.resize(1);
this->markDirty();
return true;
}
void MemoryFileProvider::readRaw(u64 offset, void *buffer, size_t size) {
if ((offset + size) > this->getActualSize() || buffer == nullptr || size == 0)
return;
std::memcpy(buffer, &this->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);
}
void MemoryFileProvider::save() {
fs::openFileBrowser(fs::DialogMode::Save, { }, [this](const std::fs::path &path) {
if (path.empty())
return;
this->saveAs(path);
auto newProvider = hex::ImHexApi::Provider::createProvider("hex.builtin.provider.file", true);
if (auto fileProvider = dynamic_cast<FileProvider*>(newProvider); fileProvider != nullptr && (fileProvider->setPath(path), !fileProvider->open()))
ImHexApi::Provider::remove(newProvider);
else {
fileProvider->markDirty(false);
EventManager::post<EventProviderOpened>(newProvider);
ImHexApi::Provider::remove(this, true);
}
});
}
void MemoryFileProvider::saveAs(const std::fs::path &path) {
fs::File file(path, fs::File::Mode::Create);
if (file.isValid()) {
auto provider = ImHexApi::Provider::get();
std::vector<u8> buffer(std::min<size_t>(0xFF'FFFF, provider->getActualSize()), 0x00);
size_t bufferSize = buffer.size();
for (u64 offset = 0; offset < provider->getActualSize(); offset += bufferSize) {
if (bufferSize > provider->getActualSize() - offset)
bufferSize = provider->getActualSize() - offset;
provider->read(offset + this->getBaseAddress(), buffer.data(), bufferSize);
file.write(buffer);
}
}
}
void MemoryFileProvider::resize(size_t newSize) {
this->m_data.resize(newSize);
Provider::resize(newSize);
}
void MemoryFileProvider::insert(u64 offset, size_t size) {
auto oldSize = this->getActualSize();
this->resize(oldSize + size);
std::vector<u8> buffer(0x1000);
const std::vector<u8> zeroBuffer(0x1000);
auto position = oldSize;
while (position > offset) {
const auto readSize = std::min<size_t>(position - offset, buffer.size());
position -= readSize;
this->readRaw(position, buffer.data(), readSize);
this->writeRaw(position, zeroBuffer.data(), readSize);
this->writeRaw(position + size, buffer.data(), readSize);
}
Provider::insert(offset, size);
}
void MemoryFileProvider::remove(u64 offset, size_t size) {
auto oldSize = this->getActualSize();
this->resize(oldSize + size);
std::vector<u8> buffer(0x1000);
const auto newSize = oldSize - size;
auto position = offset;
while (position < newSize) {
const auto readSize = std::min<size_t>(newSize - position, buffer.size());
this->readRaw(position + size, buffer.data(), readSize);
this->writeRaw(position, buffer.data(), readSize);
position += readSize;
}
this->resize(newSize);
Provider::insert(offset, size);
Provider::remove(offset, size);
}
std::pair<Region, bool> MemoryFileProvider::getRegionValidity(u64 address) const {
address -= this->getBaseAddress();
if (address < this->getActualSize())
return { Region { this->getBaseAddress() + address, this->getActualSize() - address }, true };
else
return { Region::Invalid(), false };
}
}

View File

@ -1,4 +1,5 @@
#include <hex/api/content_registry.hpp>
#include <hex/api/imhex_api.hpp>
#include <hex/api/localization.hpp>
#include <hex/ui/view.hpp>
@ -303,8 +304,13 @@ namespace hex::plugin::builtin {
ImGui::BeginDisabled(tasksRunning);
{
// Create new file
if (ImGui::ToolBarButton(ICON_VS_FILE, ImGui::GetCustomColorVec4(ImGuiCustomCol_ToolbarGray)))
EventManager::post<RequestOpenWindow>("Create File");
if (ImGui::ToolBarButton(ICON_VS_FILE, ImGui::GetCustomColorVec4(ImGuiCustomCol_ToolbarGray))) {
auto newProvider = hex::ImHexApi::Provider::createProvider("hex.builtin.provider.mem_file", true);
if (newProvider != nullptr && !newProvider->open())
hex::ImHexApi::Provider::remove(newProvider);
else
EventManager::post<EventProviderOpened>(newProvider);
}
// Open file
if (ImGui::ToolBarButton(ICON_VS_FOLDER_OPENED, ImGui::GetCustomColorVec4(ImGuiCustomCol_ToolbarBrown)))

View File

@ -208,8 +208,13 @@ namespace hex::plugin::builtin {
ImGui::UnderlinedText("hex.builtin.welcome.header.start"_lang);
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 5_scaled);
{
if (ImGui::IconHyperlink(ICON_VS_NEW_FILE, "hex.builtin.welcome.start.create_file"_lang))
EventManager::post<RequestOpenWindow>("Create File");
if (ImGui::IconHyperlink(ICON_VS_NEW_FILE, "hex.builtin.welcome.start.create_file"_lang)) {
auto newProvider = hex::ImHexApi::Provider::createProvider("hex.builtin.provider.mem_file", true);
if (newProvider != nullptr && !newProvider->open())
hex::ImHexApi::Provider::remove(newProvider);
else
EventManager::post<EventProviderOpened>(newProvider);
}
if (ImGui::IconHyperlink(ICON_VS_GO_TO_FILE, "hex.builtin.welcome.start.open_file"_lang))
EventManager::post<RequestOpenWindow>("Open File");
if (ImGui::IconHyperlink(ICON_VS_NOTEBOOK, "hex.builtin.welcome.start.open_project"_lang))

View File

@ -833,6 +833,8 @@ namespace hex::plugin::builtin {
{ "hex.builtin.provider.intel_hex.name", "Intel Hex {0}" },
{ "hex.builtin.provider.motorola_srec", "Motorola SREC Provider" },
{ "hex.builtin.provider.motorola_srec.name", "Motorola SREC {0}" },
{ "hex.builtin.provider.mem_file", "RAM Datei" },
{ "hex.builtin.provider.mem_file.unsaved", "Ungespeicherte Datei" },
{ "hex.builtin.layouts.default", "Standard" },

View File

@ -837,6 +837,8 @@ namespace hex::plugin::builtin {
{ "hex.builtin.provider.intel_hex.name", "Intel Hex {0}" },
{ "hex.builtin.provider.motorola_srec", "Motorola SREC Provider" },
{ "hex.builtin.provider.motorola_srec.name", "Motorola SREC {0}" },
{ "hex.builtin.provider.mem_file", "Memory File" },
{ "hex.builtin.provider.mem_file.unsaved", "Unsaved File" },
{ "hex.builtin.layouts.default", "Default" },

View File

@ -842,6 +842,8 @@ namespace hex::plugin::builtin {
// { "hex.builtin.provider.intel_hex.name", "Intel Hex {0}" },
//{ "hex.builtin.provider.motorola_srec", "Motorola SREC Provider" },
// { "hex.builtin.provider.motorola_srec.name", "Motorola SREC {0}" },
//{ "hex.builtin.provider.mem_file", "Memory File" },
// { "hex.builtin.provider.mem_file.unsaved", "Unsaved File" },
{ "hex.builtin.layouts.default", "Default" },

View File

@ -839,6 +839,8 @@ namespace hex::plugin::builtin {
// { "hex.builtin.provider.intel_hex.name", "Intel Hex {0}" },
//{ "hex.builtin.provider.motorola_srec", "Motorola SREC Provider" },
// { "hex.builtin.provider.motorola_srec.name", "Motorola SREC {0}" },
//{ "hex.builtin.provider.mem_file", "Memory File" },
// { "hex.builtin.provider.mem_file.unsaved", "Unsaved File" },
{ "hex.builtin.layouts.default", "標準" },

View File

@ -836,6 +836,8 @@ namespace hex::plugin::builtin {
{ "hex.builtin.provider.intel_hex.name", "Intel Hex {0}" },
{ "hex.builtin.provider.motorola_srec", "Motorola SREC 공급자" },
{ "hex.builtin.provider.motorola_srec.name", "Motorola SREC {0}" },
//{ "hex.builtin.provider.mem_file", "Memory File" },
// { "hex.builtin.provider.mem_file.unsaved", "Unsaved File" },
{ "hex.builtin.layouts.default", "기본 값" },

View File

@ -835,6 +835,8 @@ namespace hex::plugin::builtin {
// { "hex.builtin.provider.intel_hex.name", "Intel Hex {0}" },
//{ "hex.builtin.provider.motorola_srec", "Motorola SREC Provider" },
// { "hex.builtin.provider.motorola_srec.name", "Motorola SREC {0}" },
//{ "hex.builtin.provider.mem_file", "Memory File" },
// { "hex.builtin.provider.mem_file.unsaved", "Unsaved File" },
{ "hex.builtin.layouts.default", "Default" },

View File

@ -838,6 +838,8 @@ namespace hex::plugin::builtin {
{ "hex.builtin.provider.intel_hex.name", "Intel Hex {0}" },
{ "hex.builtin.provider.motorola_srec", "Motorola SREC" },
{ "hex.builtin.provider.motorola_srec.name", "Motorola SREC {0}" },
//{ "hex.builtin.provider.mem_file", "Memory File" },
// { "hex.builtin.provider.mem_file.unsaved", "Unsaved File" },
{ "hex.builtin.layouts.default", "默认" },

View File

@ -835,6 +835,8 @@ namespace hex::plugin::builtin {
// { "hex.builtin.provider.intel_hex.name", "Intel Hex {0}" },
//{ "hex.builtin.provider.motorola_srec", "Motorola SREC Provider" },
// { "hex.builtin.provider.motorola_srec.name", "Motorola SREC {0}" },
//{ "hex.builtin.provider.mem_file", "Memory File" },
// { "hex.builtin.provider.mem_file.unsaved", "Unsaved File" },
{ "hex.builtin.layouts.default", "預設" },