diff --git a/include/providers/file_provider.hpp b/include/providers/file_provider.hpp index 100d953a8..ee4f4de2e 100644 --- a/include/providers/file_provider.hpp +++ b/include/providers/file_provider.hpp @@ -24,9 +24,11 @@ namespace hex::prv { bool isAvailable() override; bool isReadable() override; bool isWritable() override; + bool isResizable() override; void read(u64 offset, void *buffer, size_t size, bool overlays) override; void write(u64 offset, const void *buffer, size_t size) override; + void resize(ssize_t newSize) override; void readRaw(u64 offset, void *buffer, size_t size) override; void writeRaw(u64 offset, const void *buffer, size_t size) override; @@ -41,6 +43,7 @@ namespace hex::prv { #else int m_file; #endif + std::string m_path; void *m_mappedFile; size_t m_fileSize; @@ -49,6 +52,9 @@ namespace hex::prv { struct stat m_fileStats = { 0 }; bool m_readable, m_writable; + + void open(); + void close(); }; } \ No newline at end of file diff --git a/include/views/view_hexeditor.hpp b/include/views/view_hexeditor.hpp index 77a61551a..2154b2111 100644 --- a/include/views/view_hexeditor.hpp +++ b/include/views/view_hexeditor.hpp @@ -46,6 +46,7 @@ namespace hex { s64 m_gotoAddress = 0; char m_baseAddressBuffer[0x20] = { 0 }; + u64 m_resizeSize = 0; std::vector m_dataToSave; @@ -59,9 +60,10 @@ namespace hex { void drawGotoPopup(); void drawEditPopup(); - void openFile(std::string path); - bool saveToFile(std::string path, const std::vector& data); - bool loadFromFile(std::string path, std::vector& data); + bool createFile(std::string_view path); + void openFile(std::string_view path); + bool saveToFile(std::string_view path, const std::vector& data); + bool loadFromFile(std::string_view path, std::vector& data); enum class Language { C, Cpp, CSharp, Rust, Python, Java, JavaScript }; void copyBytes(); diff --git a/plugins/builtin/source/lang/de_DE.cpp b/plugins/builtin/source/lang/de_DE.cpp index 9e5dde76e..f0b399c15 100644 --- a/plugins/builtin/source/lang/de_DE.cpp +++ b/plugins/builtin/source/lang/de_DE.cpp @@ -16,6 +16,7 @@ namespace hex::plugin::builtin { { "hex.welcome.header.main", "Wilkommen zu ImHex" }, { "hex.welcome.header.start", "Start" }, + { "hex.welcome.start.create_file", "Neue Datei Erstellen" }, { "hex.welcome.start.open_file", "Datei Öffnen" }, { "hex.welcome.start.open_project", "Projekt Öffnen" }, { "hex.welcome.start.recent", "Kürzlich geöffnet" }, @@ -139,7 +140,8 @@ namespace hex::plugin::builtin { { "hex.view.help.calc_cheat_sheet", "Rechner Cheat Sheet" }, { "hex.view.hexeditor.name", "Hex editor" }, - { "hex.view.hexeditor.open_file", "Datei öffnen" }, + { "hex.view.hexeditor.create_file", "Neu" }, + { "hex.view.hexeditor.open_file", "Öffnen" }, { "hex.view.hexeditor.open_project", "Projekt öffnen" }, { "hex.view.hexeditor.save_project", "Projekt speichern" }, { "hex.view.hexeditor.save_data", "Daten speichern" }, @@ -189,6 +191,7 @@ namespace hex::plugin::builtin { { "hex.view.hexeditor.goto.offset.end", "Ende" }, { "hex.view.hexeditor.error.read_only", "Schreibzugriff konnte nicht erlangt werden. Datei wurde im Lesemodus geöffnet." }, { "hex.view.hexeditor.error.open", "Öffnen der Datei fehlgeschlagen!" }, + { "hex.view.hexeditor.error.create", "Erstellen der neuen Datei fehlgeschlagen!" }, { "hex.view.hexeditor.menu.edit.undo", "Rückgängig" }, { "hex.view.hexeditor.menu.edit.redo", "Wiederholen" }, { "hex.view.hexeditor.menu.edit.copy", "Kopieren" }, @@ -206,6 +209,7 @@ namespace hex::plugin::builtin { { "hex.view.hexeditor.menu.edit.paste", "Einfügen" }, { "hex.view.hexeditor.menu.edit.bookmark", "Lesezeichen erstellen" }, { "hex.view.hexeditor.menu.edit.set_base", "Basisadresse setzen" }, + { "hex.view.hexeditor.menu.edit.resize", "Grösse ändern" }, { "hex.view.information.name", "Dateninformationen" }, { "hex.view.information.control", "Einstellungen" }, @@ -276,6 +280,8 @@ namespace hex::plugin::builtin { { "hex.view.yara.whole_data", "Gesammte Daten Übereinstimmung!" }, { "hex.view.yara.no_rules", "Keine Yara Regeln gefunden. Platziere sie in ImHex' 'yara' Ordner" }, + { "hex.view.constants.name", "Konstanten" }, + /* Builtin plugin features */ { "hex.builtin.command.calc.desc", "Rechner" }, diff --git a/plugins/builtin/source/lang/en_US.cpp b/plugins/builtin/source/lang/en_US.cpp index 5e1f6742a..254c9aad0 100644 --- a/plugins/builtin/source/lang/en_US.cpp +++ b/plugins/builtin/source/lang/en_US.cpp @@ -16,6 +16,7 @@ namespace hex::plugin::builtin { { "hex.welcome.header.main", "Welcome to ImHex" }, { "hex.welcome.header.start", "Start" }, + { "hex.welcome.start.create_file", "Create New File" }, { "hex.welcome.start.open_file", "Open File" }, { "hex.welcome.start.open_project", "Open Project" }, { "hex.welcome.start.recent", "Recent Files" }, @@ -139,7 +140,8 @@ namespace hex::plugin::builtin { { "hex.view.help.calc_cheat_sheet", "Calculator Cheat Sheet" }, { "hex.view.hexeditor.name", "Hex editor" }, - { "hex.view.hexeditor.open_file", "Open File" }, + { "hex.view.hexeditor.create_file", "New" }, + { "hex.view.hexeditor.open_file", "Open" }, { "hex.view.hexeditor.open_project", "Open Project" }, { "hex.view.hexeditor.save_project", "Save Project" }, { "hex.view.hexeditor.save_data", "Save Data" }, @@ -189,6 +191,7 @@ namespace hex::plugin::builtin { { "hex.view.hexeditor.goto.offset.end", "End" }, { "hex.view.hexeditor.error.read_only", "Couldn't get write access. File opened in read-only mode." }, { "hex.view.hexeditor.error.open", "Failed to open file!" }, + { "hex.view.hexeditor.error.create", "Failed to create new file!" }, { "hex.view.hexeditor.menu.edit.undo", "Undo" }, { "hex.view.hexeditor.menu.edit.redo", "Redo" }, { "hex.view.hexeditor.menu.edit.copy", "Copy" }, @@ -206,6 +209,7 @@ namespace hex::plugin::builtin { { "hex.view.hexeditor.menu.edit.paste", "Paste" }, { "hex.view.hexeditor.menu.edit.bookmark", "Create bookmark" }, { "hex.view.hexeditor.menu.edit.set_base", "Set base address" }, + { "hex.view.hexeditor.menu.edit.resize", "Resize" }, { "hex.view.information.name", "Data Information" }, { "hex.view.information.control", "Control" }, @@ -276,6 +280,8 @@ namespace hex::plugin::builtin { { "hex.view.yara.whole_data", "Whole file matches!" }, { "hex.view.yara.no_rules", "No YARA rules found. Put them in ImHex' 'yara' folder" }, + { "hex.view.constants.name", "Constants" }, + /* Builtin plugin features */ { "hex.builtin.command.calc.desc", "Calculator" }, diff --git a/plugins/builtin/source/lang/it_IT.cpp b/plugins/builtin/source/lang/it_IT.cpp index bf1047b80..14b8cc769 100644 --- a/plugins/builtin/source/lang/it_IT.cpp +++ b/plugins/builtin/source/lang/it_IT.cpp @@ -16,6 +16,7 @@ namespace hex::plugin::builtin { { "hex.welcome.header.main", "Benvenuto in ImHex" }, { "hex.welcome.header.start", "Inizia" }, + // { "hex.welcome.start.create_file", "Create New File" }, { "hex.welcome.start.open_file", "Apri un File" }, { "hex.welcome.start.open_project", "Apri un Progetto" }, { "hex.welcome.start.recent", "File recenti" }, @@ -139,7 +140,8 @@ namespace hex::plugin::builtin { { "hex.view.help.calc_cheat_sheet", "Calcolatrice Cheat Sheet" }, { "hex.view.hexeditor.name", "Hex editor" }, - { "hex.view.hexeditor.open_file", "Apri File" }, + // { "hex.view.hexeditor.create_file", "New" }, + { "hex.view.hexeditor.open_file", "Apri" }, { "hex.view.hexeditor.menu.file.open_recent", "File recenti" }, { "hex.view.hexeditor.open_project", "Apri i Progetti" }, { "hex.view.hexeditor.save_project", "Salva i Progetti" }, @@ -189,6 +191,7 @@ namespace hex::plugin::builtin { { "hex.view.hexeditor.goto.offset.end", "Fine" }, { "hex.view.hexeditor.error.read_only", "Impossibile scrivere sul File. File aperto solo in modalità lettura" }, { "hex.view.hexeditor.error.open", "Impossibile aprire il File!" }, + // { "hex.view.hexeditor.error.create", "Failed to create new file!" }, { "hex.view.hexeditor.menu.edit.undo", "Annulla" }, { "hex.view.hexeditor.menu.edit.redo", "Ripeti" }, { "hex.view.hexeditor.menu.edit.copy", "Copia" }, @@ -206,6 +209,7 @@ namespace hex::plugin::builtin { { "hex.view.hexeditor.menu.edit.paste", "Incolla" }, { "hex.view.hexeditor.menu.edit.bookmark", "Crea segnalibro" }, { "hex.view.hexeditor.menu.edit.set_base", "Imposta indirizzo di base" }, + // { "hex.view.hexeditor.menu.edit.resize", "Resize" }, { "hex.view.information.name", "Informazione sui Dati" }, { "hex.view.information.control", "Controllo" }, @@ -276,6 +280,8 @@ namespace hex::plugin::builtin { { "hex.view.yara.whole_data", "Tutti i file combaciano!" }, { "hex.view.yara.no_rules", "Nessuna regola di YARA. Aggiungile in nella cartella 'yara' di 'ImHex'" }, + // { "hex.view.constants.name", "Constants" }, + /* Builtin plugin features */ { "hex.builtin.command.calc.desc", "Calcolatrice" }, diff --git a/plugins/libimhex/include/hex/providers/provider.hpp b/plugins/libimhex/include/hex/providers/provider.hpp index 72ddf05ee..fccd76420 100644 --- a/plugins/libimhex/include/hex/providers/provider.hpp +++ b/plugins/libimhex/include/hex/providers/provider.hpp @@ -22,12 +22,15 @@ namespace hex::prv { virtual bool isAvailable() = 0; virtual bool isReadable() = 0; virtual bool isWritable() = 0; + virtual bool isResizable() = 0; virtual void read(u64 offset, void *buffer, size_t size, bool overlays = true); virtual void readRelative(u64 offset, void *buffer, size_t size, bool overlays = true); virtual void write(u64 offset, const void *buffer, size_t size); virtual void writeRelative(u64 offset, const void *buffer, size_t size); + virtual void resize(ssize_t newSize); + virtual void readRaw(u64 offset, void *buffer, size_t size) = 0; virtual void writeRaw(u64 offset, const void *buffer, size_t size) = 0; virtual size_t getActualSize() = 0; diff --git a/plugins/libimhex/source/providers/provider.cpp b/plugins/libimhex/source/providers/provider.cpp index 7f75d88bd..3b79b7392 100644 --- a/plugins/libimhex/source/providers/provider.cpp +++ b/plugins/libimhex/source/providers/provider.cpp @@ -34,6 +34,8 @@ namespace hex::prv { this->write(offset + this->getBaseAddress(), buffer, size); } + void Provider::resize(ssize_t newSize) { } + void Provider::applyOverlays(u64 offset, void *buffer, size_t size) { for (auto &overlay : this->m_overlays) { auto overlayOffset = overlay->getAddress(); diff --git a/source/providers/file_provider.cpp b/source/providers/file_provider.cpp index 462687a31..5569471e3 100644 --- a/source/providers/file_provider.cpp +++ b/source/providers/file_provider.cpp @@ -13,7 +13,128 @@ namespace hex::prv { FileProvider::FileProvider(std::string_view path) : Provider(), m_path(path) { - this->m_fileStatsValid = stat(path.data(), &this->m_fileStats) == 0; + this->open(); + } + + FileProvider::~FileProvider() { + this->close(); + } + + + bool FileProvider::isAvailable() { + #if defined(OS_WINDOWS) + return this->m_file != nullptr && this->m_mapping != nullptr && this->m_mappedFile != nullptr; + #else + return this->m_file != -1 && this->m_mappedFile != nullptr; + #endif + } + + bool FileProvider::isReadable() { + return isAvailable() && this->m_readable; + } + + bool FileProvider::isWritable() { + return isAvailable() && this->m_writable; + } + + bool FileProvider::isResizable() { + return true; + } + + + void FileProvider::read(u64 offset, void *buffer, size_t size, bool overlays) { + + if (((offset - this->getBaseAddress()) + size) > this->getSize() || buffer == nullptr || size == 0) + return; + + std::memcpy(buffer, reinterpret_cast(this->m_mappedFile) + PageSize * this->m_currPage + offset - this->getBaseAddress(), size); + + for (u64 i = 0; i < size; i++) + if (getPatches().contains(offset + i)) + reinterpret_cast(buffer)[i] = getPatches()[offset + PageSize * this->m_currPage + i]; + + if (overlays) + this->applyOverlays(offset, buffer, size); + } + + void FileProvider::write(u64 offset, const void *buffer, size_t size) { + if (((offset - this->getBaseAddress()) + size) > this->getSize() || buffer == nullptr || size == 0) + return; + + addPatch(offset, buffer, size); + } + + void FileProvider::readRaw(u64 offset, void *buffer, size_t size) { + offset -= this->getBaseAddress(); + + if ((offset + size) > this->getSize() || buffer == nullptr || size == 0) + return; + + std::memcpy(buffer, reinterpret_cast(this->m_mappedFile) + PageSize * this->m_currPage + offset, size); + } + + void FileProvider::writeRaw(u64 offset, const void *buffer, size_t size) { + offset -= this->getBaseAddress(); + + if ((offset + size) > this->getSize() || buffer == nullptr || size == 0) + return; + + std::memcpy(reinterpret_cast(this->m_mappedFile) + PageSize * this->m_currPage + offset, buffer, size); + } + + void FileProvider::resize(ssize_t newSize) { + close(); + + #if defined(OS_WINDOWS) + std::wstring widePath; + { + auto length = static_cast(this->m_path.length() + 1); + auto wideLength = MultiByteToWideChar(CP_UTF8, 0, this->m_path.data(), length, nullptr, 0); + auto buffer = new wchar_t[wideLength]; + MultiByteToWideChar(CP_UTF8, 0, this->m_path.data(), length, buffer, wideLength); + widePath = buffer; + delete[] buffer; + } + + auto handle = ::CreateFileW(widePath.data(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); + + if (handle != INVALID_HANDLE_VALUE) { + ::SetFilePointerEx(handle, LARGE_INTEGER { .QuadPart = newSize }, nullptr, FILE_BEGIN); + ::SetEndOfFile(handle); + ::CloseHandle(handle); + } + #else + auto handle = ::open(path.data(), O_RDWR | O_CREAT); + + truncate(handle, newSize - 1); + + close(handle); + #endif + + open(); + } + + size_t FileProvider::getActualSize() { + return this->m_fileSize; + } + + std::vector> FileProvider::getDataInformation() { + std::vector> result; + + result.emplace_back("hex.builtin.provider.file.path"_lang, this->m_path); + result.emplace_back("hex.builtin.provider.file.size"_lang, hex::toByteString(this->getActualSize())); + + if (this->m_fileStatsValid) { + result.emplace_back("hex.builtin.provider.file.creation"_lang, ctime(&this->m_fileStats.st_ctime)); + result.emplace_back("hex.builtin.provider.file.access"_lang, ctime(&this->m_fileStats.st_atime)); + result.emplace_back("hex.builtin.provider.file.modification"_lang, ctime(&this->m_fileStats.st_mtime)); + } + + return result; + } + + void FileProvider::open() { + this->m_fileStatsValid = stat(this->m_path.data(), &this->m_fileStats) == 0; this->m_readable = true; this->m_writable = true; @@ -21,10 +142,10 @@ namespace hex::prv { #if defined(OS_WINDOWS) std::wstring widePath; { - auto length = path.length() + 1; - auto wideLength = MultiByteToWideChar(CP_UTF8, 0, path.data(), length, 0, 0); + auto length = this->m_path.length() + 1; + auto wideLength = MultiByteToWideChar(CP_UTF8, 0, this->m_path.data(), length, 0, 0); wchar_t* buffer = new wchar_t[wideLength]; - MultiByteToWideChar(CP_UTF8, 0, path.data(), length, buffer, wideLength); + MultiByteToWideChar(CP_UTF8, 0, this->m_path.data(), length, buffer, wideLength); widePath = buffer; delete[] buffer; } @@ -72,12 +193,12 @@ namespace hex::prv { fileCleanup.release(); mappingCleanup.release(); - ProjectFile::setFilePath(path); + ProjectFile::setFilePath(this->m_path); #else - this->m_file = open(path.data(), O_RDWR); + this->m_file = ::open(path.data(), O_RDWR); if (this->m_file == -1) { - this->m_file = open(path.data(), O_RDONLY); + this->m_file = ::open(path.data(), O_RDONLY); this->m_writable = false; } @@ -90,97 +211,21 @@ namespace hex::prv { this->m_mappedFile = mmap(nullptr, this->m_fileSize, PROT_READ | PROT_WRITE, MAP_PRIVATE, this->m_file, 0); - #endif + #endif } - FileProvider::~FileProvider() { - #if defined(OS_WINDOWS) + void FileProvider::close() { + #if defined(OS_WINDOWS) if (this->m_mappedFile != nullptr) - UnmapViewOfFile(this->m_mappedFile); + ::UnmapViewOfFile(this->m_mappedFile); if (this->m_mapping != nullptr) - CloseHandle(this->m_mapping); + ::CloseHandle(this->m_mapping); if (this->m_file != nullptr) - CloseHandle(this->m_file); - #else - munmap(this->m_mappedFile, this->m_fileSize); - close(this->m_file); - #endif - } - - - bool FileProvider::isAvailable() { - #if defined(OS_WINDOWS) - return this->m_file != nullptr && this->m_mapping != nullptr && this->m_mappedFile != nullptr; - #else - return this->m_file != -1 && this->m_mappedFile != nullptr; - #endif - } - - bool FileProvider::isReadable() { - return isAvailable() && this->m_readable; - } - - bool FileProvider::isWritable() { - return isAvailable() && this->m_writable; - } - - - void FileProvider::read(u64 offset, void *buffer, size_t size, bool overlays) { - - if (((offset - this->getBaseAddress()) + size) > this->getSize() || buffer == nullptr || size == 0) - return; - - std::memcpy(buffer, reinterpret_cast(this->m_mappedFile) + PageSize * this->m_currPage + offset - this->getBaseAddress(), size); - - for (u64 i = 0; i < size; i++) - if (getPatches().contains(offset + i)) - reinterpret_cast(buffer)[i] = getPatches()[offset + PageSize * this->m_currPage + i]; - - if (overlays) - this->applyOverlays(offset, buffer, size); - } - - void FileProvider::write(u64 offset, const void *buffer, size_t size) { - if (((offset - this->getBaseAddress()) + size) > this->getSize() || buffer == nullptr || size == 0) - return; - - addPatch(offset, buffer, size); - } - - void FileProvider::readRaw(u64 offset, void *buffer, size_t size) { - offset -= this->getBaseAddress(); - - if ((offset + size) > this->getSize() || buffer == nullptr || size == 0) - return; - - std::memcpy(buffer, reinterpret_cast(this->m_mappedFile) + PageSize * this->m_currPage + offset, size); - } - - void FileProvider::writeRaw(u64 offset, const void *buffer, size_t size) { - offset -= this->getBaseAddress(); - - if ((offset + size) > this->getSize() || buffer == nullptr || size == 0) - return; - - std::memcpy(reinterpret_cast(this->m_mappedFile) + PageSize * this->m_currPage + offset, buffer, size); - } - size_t FileProvider::getActualSize() { - return this->m_fileSize; - } - - std::vector> FileProvider::getDataInformation() { - std::vector> result; - - result.emplace_back("hex.builtin.provider.file.path"_lang, this->m_path); - result.emplace_back("hex.builtin.provider.file.size"_lang, hex::toByteString(this->getActualSize())); - - if (this->m_fileStatsValid) { - result.emplace_back("hex.builtin.provider.file.creation"_lang, ctime(&this->m_fileStats.st_ctime)); - result.emplace_back("hex.builtin.provider.file.access"_lang, ctime(&this->m_fileStats.st_atime)); - result.emplace_back("hex.builtin.provider.file.modification"_lang, ctime(&this->m_fileStats.st_mtime)); - } - - return result; + ::CloseHandle(this->m_file); + #else + ::munmap(this->m_mappedFile, this->m_fileSize); + ::close(this->m_file); + #endif } } \ No newline at end of file diff --git a/source/views/view_hexeditor.cpp b/source/views/view_hexeditor.cpp index 1ff42570f..9a2f0d87c 100644 --- a/source/views/view_hexeditor.cpp +++ b/source/views/view_hexeditor.cpp @@ -16,6 +16,13 @@ #include +#if defined(OS_WINDOWS) + #include +#else + #include + #include +#endif + namespace hex { ViewHexEditor::ViewHexEditor() : View("hex.view.hexeditor.name"_lang) { @@ -168,7 +175,16 @@ namespace hex { }); EventManager::subscribe(this, [this](std::string name) { - if (name == "Open File") { + if (name == "Create File") { + View::openFileBrowser("hex.view.hexeditor.create_file"_lang, DialogMode::Save, { }, [this](auto path) { + if (!this->createFile(path)) { + View::showErrorPopup("hex.view.hexeditor.error.create"_lang); + return; + } + this->openFile(path); + this->getWindowOpenState() = true; + }); + } else if (name == "Open File") { View::openFileBrowser("hex.view.hexeditor.open_file"_lang, DialogMode::Open, { }, [this](auto path) { this->openFile(path); this->getWindowOpenState() = true; @@ -361,6 +377,24 @@ namespace hex { ImGui::EndPopup(); } + + if (ImGui::BeginPopupModal("hex.view.hexeditor.menu.edit.resize"_lang, nullptr, ImGuiWindowFlags_AlwaysAutoResize)) { + ImGui::InputScalar("hex.common.size"_lang, ImGuiDataType_U64, &this->m_resizeSize, nullptr, nullptr, "0x%016llx", ImGuiInputTextFlags_CharsHexadecimal); + ImGui::NewLine(); + + confirmButtons("hex.common.set"_lang, "hex.common.cancel"_lang, + [this, &provider]{ + provider->resize(this->m_resizeSize); + ImGui::CloseCurrentPopup(); + }, []{ + ImGui::CloseCurrentPopup(); + }); + + if (ImGui::IsKeyDown(ImGui::GetKeyIndex(ImGuiKey_Escape))) + ImGui::CloseCurrentPopup(); + + ImGui::EndPopup(); + } } void ViewHexEditor::drawMenu() { @@ -583,17 +617,47 @@ namespace hex { } } - - return false; } + bool ViewHexEditor::createFile(std::string_view path) { + #if defined(OS_WINDOWS) + std::wstring widePath; + { + auto length = path.length() + 1; + auto wideLength = MultiByteToWideChar(CP_UTF8, 0, path.data(), length, 0, 0); + auto buffer = new wchar_t[wideLength]; + MultiByteToWideChar(CP_UTF8, 0, path.data(), length, buffer, wideLength); + widePath = buffer; + delete[] buffer; + } - void ViewHexEditor::openFile(std::string path) { + auto handle = ::CreateFileW(widePath.data(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); + + if (handle == INVALID_HANDLE_VALUE) + return false; + + ::SetFilePointer(handle, 1, nullptr, FILE_BEGIN); + ::SetEndOfFile(handle); + ::CloseHandle(handle); + #else + auto handle = ::open(path.data(), O_RDWR | O_CREAT); + if (handle == -1) + return false; + + lseek(handle, 0, SEEK_SET); + write(handle, "", 1); + + close(handle); + #endif + + return true; + } + + void ViewHexEditor::openFile(std::string_view path) { auto& provider = SharedData::currentProvider; - if (provider != nullptr) - delete provider; + delete provider; provider = new prv::FileProvider(path); if (!provider->isWritable()) { @@ -615,13 +679,13 @@ namespace hex { this->getWindowOpenState() = true; - EventManager::post(path); + EventManager::post(std::string(path)); EventManager::post(); EventManager::post(); } - bool ViewHexEditor::saveToFile(std::string path, const std::vector& data) { - FILE *file = fopen(path.c_str(), "wb"); + bool ViewHexEditor::saveToFile(std::string_view path, const std::vector& data) { + FILE *file = fopen(path.data(), "wb"); if (file == nullptr) return false; @@ -632,8 +696,8 @@ namespace hex { return true; } - bool ViewHexEditor::loadFromFile(std::string path, std::vector& data) { - FILE *file = fopen(path.c_str(), "rb"); + bool ViewHexEditor::loadFromFile(std::string_view path, std::vector& data) { + FILE *file = fopen(path.data(), "rb"); if (file == nullptr) return false; @@ -1228,6 +1292,13 @@ R"( std::memset(this->m_baseAddressBuffer, 0x00, sizeof(this->m_baseAddressBuffer)); View::doLater([]{ ImGui::OpenPopup("hex.view.hexeditor.menu.edit.set_base"_lang); }); } + + if (ImGui::MenuItem("hex.view.hexeditor.menu.edit.resize"_lang, nullptr, false, provider != nullptr && provider->isResizable())) { + View::doLater([this, &provider]{ + this->m_resizeSize = provider->getActualSize(); + ImGui::OpenPopup("hex.view.hexeditor.menu.edit.resize"_lang); + }); + } } } \ No newline at end of file diff --git a/source/window.cpp b/source/window.cpp index ef411390f..70ce8b5c4 100644 --- a/source/window.cpp +++ b/source/window.cpp @@ -424,6 +424,8 @@ namespace hex { ImGui::TableNextColumn(); ImGui::TextUnformatted("hex.welcome.header.start"_lang); { + if (ImGui::BulletHyperlink("hex.welcome.start.create_file"_lang)) + EventManager::post("Create File"); if (ImGui::BulletHyperlink("hex.welcome.start.open_file"_lang)) EventManager::post("Open File"); if (ImGui::BulletHyperlink("hex.welcome.start.open_project"_lang))