Compare commits

..

22 Commits

Author SHA1 Message Date
WerWolv
3db8e2aec2 build: Bumped version to 1.19.2 2022-07-16 13:41:37 +02:00
WerWolv
499b68b7ad build: Updated nativefiledialog library 2022-07-16 13:26:07 +02:00
WerWolv
2e3bb8e555 patterns: Don't display empty strings in pattern data view 2022-07-16 13:08:08 +02:00
WerWolv
0c9eab70d5 fix: Crash when searching for an empty string 2022-07-16 13:01:40 +02:00
WerWolv
0d3eaa5d86 patterns: Updated pattern language 2022-07-16 12:57:33 +02:00
WerWolv
c20634e093 sys: Fixed crash on exit 2022-07-16 12:14:15 +02:00
WerWolv
5ee3b550bc ui: Fixed advanced decoding cell sizes 2022-07-16 12:14:06 +02:00
WerWolv
831dac9b47 patterns: Updated pattern language 2022-07-15 11:38:46 +02:00
WerWolv
626c34dce8 sys: Upgrade codebase to C++23 2022-07-15 11:37:10 +02:00
Lukas Cone
ed67c20cba fix: User folders didnt load at startup (#578) 2022-07-14 11:38:23 +02:00
Lukas Cone
35c209c791 fix: In/Out variables not working, add recusive pattern scan (#579) 2022-07-14 11:37:02 +02:00
WerWolv
315109aa1f fix: Open File shortcut only working when Hex Editor view is selected
Fixes #576
2022-07-08 14:26:13 +02:00
WerWolv
a57fa34f82 build: Added option for Offline builds 2022-07-08 14:17:22 +02:00
iTrooz_
d1a2f7d6ed build: Cleanup package dependencies (#573)
* removed DEBIAN/imhex.desktop

* added licence to cmake install directory + fixed PKGBUILD to copy desktop file/licence

* removed gtk3 from packaging files

* added xdg-desktop-portal dependency

* adwaita theme should not be needed anymore

* added dbus dependency
2022-07-08 09:23:53 +02:00
WerWolv
8382f68601 fix: Data inspector string row not being editable correctly
Fixes #575
2022-07-08 09:21:49 +02:00
WerWolv
3aa1dd1e06 build: Added usp10 library to maybe provide Windows 7 support 2022-07-07 23:30:09 +02:00
WerWolv
0571fe383c fix: Duplicate file chooser popup entries not being selectable 2022-07-07 23:29:50 +02:00
WerWolv
461c5eac3e fix: Crash when closing the file picker without picking a file 2022-07-07 23:28:40 +02:00
KokaKiwi
e34f94bb79 build: Add xdg-desktop-portal for AUR package (#572)
* Add xdg-desktop-portal for AUR package

* Fix archlinux package build
2022-07-07 22:08:27 +02:00
WerWolv
071bae345e patterns: Fixed passing placed values to functions 2022-07-07 21:32:25 +02:00
WerWolv
9f4625aa00 fix: Editing float and double data inspector rows yielding wrong values
Fixes #571
2022-07-07 18:35:10 +02:00
iTrooz_
9837473810 git: Automatically create PatternLanguage release on new ImHex releases (#570) 2022-07-07 16:10:21 +02:00
30 changed files with 180 additions and 147 deletions

View File

@@ -90,3 +90,12 @@ jobs:
ssh_private_key: ${{ secrets.AUR_SSH_PRIVATE_KEY }} ssh_private_key: ${{ secrets.AUR_SSH_PRIVATE_KEY }}
commit_message: Bump to version ${{env.version}} commit_message: Bump to version ${{env.version}}
ssh_keyscan_types: rsa,dsa,ecdsa,ed25519 ssh_keyscan_types: rsa,dsa,ecdsa,ed25519
- uses: ncipollo/release-action@v1
env:
MY_KEY: ${{ secrets.RELEASE_TOKEN }}
if: "${{ env.MY_KEY != '' }}"
with:
tag: ImHex-v${{env.version}}
repo: PatternLanguage
token: ${{ secrets.RELEASE_TOKEN }}

View File

@@ -5,11 +5,13 @@ file(READ "VERSION" IMHEX_VERSION)
project(imhex VERSION ${IMHEX_VERSION}) project(imhex VERSION ${IMHEX_VERSION})
message("Project version ${IMHEX_VERSION}") message("Project version ${IMHEX_VERSION}")
set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD 23)
set(IMHEX_BASE_FOLDER ${CMAKE_CURRENT_SOURCE_DIR}) set(IMHEX_BASE_FOLDER ${CMAKE_CURRENT_SOURCE_DIR})
set(CMAKE_MODULE_PATH "${IMHEX_BASE_FOLDER}/cmake/modules") set(CMAKE_MODULE_PATH "${IMHEX_BASE_FOLDER}/cmake/modules")
include("${IMHEX_BASE_FOLDER}/cmake/build_helpers.cmake") include("${IMHEX_BASE_FOLDER}/cmake/build_helpers.cmake")
option(IMHEX_OFFLINE_BUILD "Enable offline build" OFF)
# Make sure project is configured correctly # Make sure project is configured correctly
setDefaultBuiltTypeIfUnset() setDefaultBuiltTypeIfUnset()
detectBadClone() detectBadClone()

View File

@@ -1 +1 @@
1.19.1 1.19.2

View File

@@ -222,6 +222,7 @@ macro(createPackage)
configure_file(${CMAKE_SOURCE_DIR}/dist/DEBIAN/control.in ${CMAKE_BINARY_DIR}/DEBIAN/control) configure_file(${CMAKE_SOURCE_DIR}/dist/DEBIAN/control.in ${CMAKE_BINARY_DIR}/DEBIAN/control)
install(FILES ${CMAKE_SOURCE_DIR}/LICENSE DESTINATION ${CMAKE_INSTALL_PREFIX}/share/licenses/imhex)
install(FILES ${CMAKE_SOURCE_DIR}/dist/imhex.desktop DESTINATION ${CMAKE_INSTALL_PREFIX}/share/applications) install(FILES ${CMAKE_SOURCE_DIR}/dist/imhex.desktop DESTINATION ${CMAKE_INSTALL_PREFIX}/share/applications)
install(FILES ${CMAKE_SOURCE_DIR}/resources/icon.png DESTINATION ${CMAKE_INSTALL_PREFIX}/share/pixmaps RENAME imhex.png) install(FILES ${CMAKE_SOURCE_DIR}/resources/icon.png DESTINATION ${CMAKE_INSTALL_PREFIX}/share/pixmaps RENAME imhex.png)
install(FILES "$<TARGET_FILE:libimhex>" DESTINATION "${CMAKE_INSTALL_LIBDIR}") install(FILES "$<TARGET_FILE:libimhex>" DESTINATION "${CMAKE_INSTALL_LIBDIR}")
@@ -289,17 +290,19 @@ endmacro()
function(downloadImHexPatternsFiles dest) function(downloadImHexPatternsFiles dest)
FetchContent_Declare( if (NOT IMHEX_OFFLINE_BUILD)
imhex_patterns FetchContent_Declare(
GIT_REPOSITORY https://github.com/WerWolv/ImHex-Patterns.git imhex_patterns
GIT_TAG master GIT_REPOSITORY https://github.com/WerWolv/ImHex-Patterns.git
) GIT_TAG master
)
FetchContent_Populate(imhex_patterns) FetchContent_Populate(imhex_patterns)
set(PATTERNS_FOLDERS_TO_INSTALL constants encodings includes patterns magic) set(PATTERNS_FOLDERS_TO_INSTALL constants encodings includes patterns magic)
foreach (FOLDER ${PATTERNS_FOLDERS_TO_INSTALL}) foreach (FOLDER ${PATTERNS_FOLDERS_TO_INSTALL})
install(DIRECTORY "${imhex_patterns_SOURCE_DIR}/${FOLDER}" DESTINATION ${dest}) install(DIRECTORY "${imhex_patterns_SOURCE_DIR}/${FOLDER}" DESTINATION ${dest})
endforeach() endforeach ()
endif ()
endfunction() endfunction()

View File

@@ -26,7 +26,6 @@ AppDir:
- sourceline: deb http://security.ubuntu.com/ubuntu jammy-security universe - sourceline: deb http://security.ubuntu.com/ubuntu jammy-security universe
- sourceline: deb http://security.ubuntu.com/ubuntu jammy-security multiverse - sourceline: deb http://security.ubuntu.com/ubuntu jammy-security multiverse
include: include:
- adwaita-icon-theme-full
- librsvg2-common - librsvg2-common
- libbz2-1.0:amd64 - libbz2-1.0:amd64
- libcap2:amd64 - libcap2:amd64
@@ -85,7 +84,6 @@ AppDir:
- /lib/x86_64-linux-gnu/libgnutls.so.30 - /lib/x86_64-linux-gnu/libgnutls.so.30
- /lib/x86_64-linux-gnu/libgobject-2.0.so.0 - /lib/x86_64-linux-gnu/libgobject-2.0.so.0
- /lib/x86_64-linux-gnu/libgraphite2.so.3 - /lib/x86_64-linux-gnu/libgraphite2.so.3
- /lib/x86_64-linux-gnu/libgtk-3.so.0
- /lib/x86_64-linux-gnu/libharfbuzz.so.0 - /lib/x86_64-linux-gnu/libharfbuzz.so.0
- /lib/x86_64-linux-gnu/libhogweed.so.6 - /lib/x86_64-linux-gnu/libhogweed.so.6
- /lib/x86_64-linux-gnu/libicudata.so.70 - /lib/x86_64-linux-gnu/libicudata.so.70

5
dist/Arch/PKGBUILD vendored
View File

@@ -8,7 +8,7 @@ url="https://github.com/WerWolv/ImHex"
repo=$url repo=$url
license=('GPL 2.0') license=('GPL 2.0')
groups=() groups=()
depends=(glfw mbedtls python freetype2 libglvnd gtk3) depends=(glfw mbedtls python freetype2 libglvnd dbus xdg-desktop-portal)
makedepends=(git) makedepends=(git)
checkdepends=() checkdepends=()
optdepends=() optdepends=()
@@ -34,5 +34,6 @@ package() {
done done
cp -r $srcdir/usr/share/imhex/{constants,encodings,includes,magic,patterns} $pkgdir/usr/share/imhex cp -r $srcdir/usr/share/imhex/{constants,encodings,includes,magic,patterns} $pkgdir/usr/share/imhex
install -d $pkgdir/usr/share/imhex cp -r $srcdir/usr/share/{applications,licenses} $pkgdir/usr/share
install -d $pkgdir/usr/share
} }

View File

@@ -4,7 +4,7 @@ Section: editors
Priority: optional Priority: optional
Architecture: amd64 Architecture: amd64
License: GNU GPL-2 License: GNU GPL-2
Depends: libglfw3, libmagic1, libmbedtls14, libpython3.10, libfreetype6, libopengl0, libgtk-3-0 Depends: libglfw3, libmagic1, libmbedtls14, libpython3.10, libfreetype6, libopengl0, libdbus-1-3, xdg-desktop-portal
Maintainer: WerWolv <hey@werwolv.net> Maintainer: WerWolv <hey@werwolv.net>
Description: ImHex Hex Editor Description: ImHex Hex Editor
A Hex Editor for Reverse Engineers, Programmers and A Hex Editor for Reverse Engineers, Programmers and

View File

@@ -1,11 +0,0 @@
[Desktop Entry]
Name=ImHex
Comment=ImHex Hex Editor
GenericName=Hex Editor
Exec=/usr/bin/imhex %U
Icon=/usr/share/pixmaps/imhex.png
Type=Application
StartupNotify=true
Categories=GNOME;GTK;Development;
StartupWMClass=imhex

3
dist/Dockerfile vendored
View File

@@ -15,7 +15,8 @@ RUN pacman -S --needed --noconfirm \
mbedtls \ mbedtls \
python3 \ python3 \
freetype2 \ freetype2 \
gtk3 dbus \
xdg-desktop-portal
# Clone ImHex # Clone ImHex
RUN git clone https://github.com/WerWolv/ImHex --recurse-submodules /root/ImHex RUN git clone https://github.com/WerWolv/ImHex --recurse-submodules /root/ImHex

View File

@@ -27,6 +27,7 @@ RDEPEND="${DEPEND}
sys-apps/file sys-apps/file
dev-libs/mbedtls dev-libs/mbedtls
dev-cpp/nlohmann_json dev-cpp/nlohmann_json
x11-libs/gtk+ dbus
xdg-desktop-portal
" "
BDEPEND="${DEPEND}" BDEPEND="${DEPEND}"

View File

@@ -9,4 +9,5 @@ pacman -S $@ --needed \
mbedtls \ mbedtls \
python3 \ python3 \
freetype2 \ freetype2 \
gtk3 dbus \
xdg-desktop-portal

View File

@@ -21,4 +21,5 @@ apt install -y \
libmbedtls-dev \ libmbedtls-dev \
python3-dev \ python3-dev \
libfreetype-dev \ libfreetype-dev \
libgtk-3-dev libdbus-1-dev \
xdg-desktop-portal

View File

@@ -10,4 +10,5 @@ dnf install \
mbedtls-devel \ mbedtls-devel \
python-devel \ python-devel \
freetype-devel \ freetype-devel \
gtk3-devel dbus \
xdg-desktop-portal

View File

@@ -38,8 +38,6 @@ namespace hex {
{ {
auto delimiterPos = line.find('='); auto delimiterPos = line.find('=');
if (delimiterPos == std::string::npos)
continue;
if (delimiterPos >= line.length()) if (delimiterPos >= line.length())
continue; continue;
@@ -47,12 +45,16 @@ namespace hex {
to = line.substr(delimiterPos + 1); to = line.substr(delimiterPos + 1);
if (from.empty()) continue; if (from.empty()) continue;
if (to.empty()) to = " ";
} }
auto fromBytes = hex::parseByteString(from); auto fromBytes = hex::parseByteString(from);
if (fromBytes.empty()) continue; if (fromBytes.empty()) continue;
if (to.length() > 1)
hex::trim(to);
if (to.empty())
to = " ";
if (!this->m_mapping.contains(fromBytes.size())) if (!this->m_mapping.contains(fromBytes.size()))
this->m_mapping.insert({ fromBytes.size(), {} }); this->m_mapping.insert({ fromBytes.size(), {} });
this->m_mapping[fromBytes.size()].insert({ fromBytes, to }); this->m_mapping[fromBytes.size()].insert({ fromBytes, to });

View File

@@ -71,7 +71,7 @@ namespace hex::fs {
bool openFileBrowser(DialogMode mode, const std::vector<nfdfilteritem_t> &validExtensions, const std::function<void(std::fs::path)> &callback, const std::string &defaultPath) { bool openFileBrowser(DialogMode mode, const std::vector<nfdfilteritem_t> &validExtensions, const std::function<void(std::fs::path)> &callback, const std::string &defaultPath) {
NFD::Init(); NFD::Init();
nfdchar_t *outPath; nfdchar_t *outPath = nullptr;
nfdresult_t result; nfdresult_t result;
switch (mode) { switch (mode) {
case DialogMode::Open: case DialogMode::Open:
@@ -87,18 +87,8 @@ namespace hex::fs {
hex::unreachable(); hex::unreachable();
} }
std::fs::path path; if (result == NFD_OKAY && outPath != nullptr) {
#if defined(OS_LINUX) callback(reinterpret_cast<char8_t*>(outPath));
// xdg-desktop-portal, which is the file picker backend used on Linux, returns all paths with URI encoding.
// This is a bit ugly and will most likely be fixed sometime in the future but until then, we'll just use
// curl to decode the URI string into a valid file path string
path = Net().decode(outPath);
#else
path = reinterpret_cast<char8_t*>(outPath);
#endif
if (result == NFD_OKAY) {
callback(path);
NFD::FreePath(outPath); NFD::FreePath(outPath);
} }

View File

@@ -26,7 +26,7 @@ set_target_properties(main PROPERTIES
add_compile_definitions(IMHEX_PROJECT_NAME="${PROJECT_NAME}") add_compile_definitions(IMHEX_PROJECT_NAME="${PROJECT_NAME}")
if (WIN32) if (WIN32)
target_link_libraries(main PUBLIC libimhex wsock32 ws2_32 Dwmapi.lib) target_link_libraries(main PUBLIC usp10 libimhex wsock32 ws2_32 Dwmapi.lib)
else () else ()
target_link_libraries(main PUBLIC libimhex pthread) target_link_libraries(main PUBLIC libimhex pthread)
endif () endif ()

View File

@@ -21,7 +21,7 @@ namespace hex::plugin::builtin {
void drawContent() override; void drawContent() override;
private: private:
std::map<prv::Provider *, std::vector<std::shared_ptr<pl::Pattern>>> m_sortedPatterns; std::map<prv::Provider *, std::vector<pl::Pattern*>> m_sortedPatterns;
hex::PatternDrawer m_patternDrawer; hex::PatternDrawer m_patternDrawer;
}; };

View File

@@ -56,7 +56,6 @@ namespace hex::plugin::builtin {
}; };
std::map<std::string, PatternVariable> m_patternVariables; std::map<std::string, PatternVariable> m_patternVariables;
std::vector<std::string> m_patternTypes;
enum class EnvVarType enum class EnvVarType
{ {
@@ -102,4 +101,4 @@ namespace hex::plugin::builtin {
void evaluatePattern(const std::string &code); void evaluatePattern(const std::string &code);
}; };
} }

View File

@@ -54,7 +54,7 @@ namespace hex::plugin::builtin {
template<std::floating_point T> template<std::floating_point T>
static std::vector<u8> stringToFloat(const std::string &value, std::endian endian) requires(sizeof(T) <= sizeof(long double)) { static std::vector<u8> stringToFloat(const std::string &value, std::endian endian) requires(sizeof(T) <= sizeof(long double)) {
auto result = std::strtold(value.c_str(), nullptr); T result = std::strtold(value.c_str(), nullptr);
std::vector<u8> bytes(sizeof(T), 0x00); std::vector<u8> bytes(sizeof(T), 0x00);
std::memcpy(bytes.data(), &result, bytes.size()); std::memcpy(bytes.data(), &result, bytes.size());
@@ -349,7 +349,7 @@ namespace hex::plugin::builtin {
ContentRegistry::DataInspector::add("hex.builtin.inspector.string", 1, ContentRegistry::DataInspector::add("hex.builtin.inspector.string", 1,
[](auto buffer, auto endian, auto style) { [](auto buffer, auto endian, auto style) {
hex::unused(endian, style); hex::unused(buffer, endian, style);
auto currSelection = ImHexApi::HexEditor::getSelection(); auto currSelection = ImHexApi::HexEditor::getSelection();
@@ -358,14 +358,15 @@ namespace hex::plugin::builtin {
std::string value, copyValue; std::string value, copyValue;
if (currSelection.has_value()) { if (currSelection.has_value()) {
std::vector<u8> stringBuffer(std::min<size_t>(MaxStringLength, currSelection->size), 0x00); std::vector<u8> stringBuffer(std::min<size_t>(currSelection->size, 0x1000), 0x00);
ImHexApi::Provider::get()->read(currSelection->address, stringBuffer.data(), stringBuffer.size()); ImHexApi::Provider::get()->read(currSelection->address, stringBuffer.data(), stringBuffer.size());
value = hex::encodeByteString(stringBuffer); value = copyValue = hex::encodeByteString(stringBuffer);
copyValue = hex::encodeByteString(buffer);
if (currSelection->size > MaxStringLength) if (currSelection->size > MaxStringLength) {
value.resize(MaxStringLength);
value += "..."; value += "...";
}
} else { } else {
value = ""; value = "";
copyValue = ""; copyValue = "";

View File

@@ -91,7 +91,7 @@ namespace hex::plugin::builtin {
} }
void load(nlohmann::json &j) override { void load(nlohmann::json &j) override {
this->m_value = j["data"]; this->m_value = j["data"].get<std::string>();
} }
private: private:
@@ -213,7 +213,7 @@ namespace hex::plugin::builtin {
} }
void load(nlohmann::json &j) override { void load(nlohmann::json &j) override {
this->m_comment = j["comment"]; this->m_comment = j["comment"].get<std::string>();
} }
private: private:

View File

@@ -13,6 +13,19 @@
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
namespace {
static std::vector<std::fs::path> userFolders;
static void loadUserFoldersFromSetting(nlohmann::json &setting) {
userFolders.clear();
std::vector<std::string> paths = setting;
for (const auto &path : paths) {
// JSON reads char8_t as array, char8_t is not supported as of now
std::u8string_view uString(reinterpret_cast<const char8_t *>(&path.front()), reinterpret_cast<const char8_t *>(std::next(&path.back())));
userFolders.emplace_back(uString);
}
}
};
namespace hex::plugin::builtin { namespace hex::plugin::builtin {
void registerSettings() { void registerSettings() {
@@ -247,7 +260,7 @@ namespace hex::plugin::builtin {
for (const auto &[unlocalizedName, visualizer] : visualizers) { for (const auto &[unlocalizedName, visualizer] : visualizers) {
if (ImGui::Selectable(LangEntry(unlocalizedName))) { if (ImGui::Selectable(LangEntry(unlocalizedName))) {
setting = unlocalizedName; setting = unlocalizedName;
result = true; result = true;
} }
} }
@@ -314,34 +327,27 @@ namespace hex::plugin::builtin {
ContentRegistry::Settings::add(dirsSetting, dirsSetting, std::vector<std::string> {}, [](auto name, nlohmann::json &setting) { ContentRegistry::Settings::add(dirsSetting, dirsSetting, std::vector<std::string> {}, [](auto name, nlohmann::json &setting) {
hex::unused(name); hex::unused(name);
static size_t currentItemIndex = 0; static size_t currentItemIndex = [&setting] {loadUserFoldersFromSetting(setting); return 0; }();
static std::vector<std::fs::path> folders = [&setting]{
std::vector<std::fs::path> result;
std::vector<std::u8string> paths = setting; auto saveToSetting = [&setting] {
for (const auto &path : paths) std::vector<std::string> folderStrings;
result.emplace_back(path); for (const auto &folder : userFolders) {
auto utfString = folder.u8string();
return result; // JSON stores char8_t as array, char8_t is not supported as of now
}(); folderStrings.emplace_back(reinterpret_cast<const char *>(&utfString.front()), reinterpret_cast<const char *>(std::next(&utfString.back())));
}
setting = folderStrings;
ImHexApi::System::setAdditionalFolderPaths(userFolders);
};
bool result = false; bool result = false;
auto writeSetting = [&setting]{
std::vector<std::u8string> folderStrings;
for (const auto &folder : folders)
folderStrings.push_back(folder.u8string());
setting = folderStrings;
ImHexApi::System::setAdditionalFolderPaths(folders);
};
if (!ImGui::BeginListBox("", ImVec2(-38, -FLT_MIN))) { if (!ImGui::BeginListBox("", ImVec2(-38, -FLT_MIN))) {
return false; return false;
} else { } else {
for (size_t n = 0; n < folders.size(); n++) { for (size_t n = 0; n < userFolders.size(); n++) {
const bool isSelected = (currentItemIndex == n); const bool isSelected = (currentItemIndex == n);
if (ImGui::Selectable(folders.at(n).string().c_str(), isSelected)) { currentItemIndex = n; } if (ImGui::Selectable(userFolders.at(n).string().c_str(), isSelected)) { currentItemIndex = n; }
if (isSelected) { ImGui::SetItemDefaultFocus(); } if (isSelected) { ImGui::SetItemDefaultFocus(); }
} }
ImGui::EndListBox(); ImGui::EndListBox();
@@ -351,12 +357,9 @@ namespace hex::plugin::builtin {
if (ImGui::IconButton(ICON_VS_NEW_FOLDER, ImGui::GetCustomColorVec4(ImGuiCustomCol_DescButton), ImVec2(30, 30))) { if (ImGui::IconButton(ICON_VS_NEW_FOLDER, ImGui::GetCustomColorVec4(ImGuiCustomCol_DescButton), ImVec2(30, 30))) {
fs::openFileBrowser(fs::DialogMode::Folder, {}, [&](const std::fs::path &path) { fs::openFileBrowser(fs::DialogMode::Folder, {}, [&](const std::fs::path &path) {
if (std::find(userFolders.begin(), userFolders.end(), path) == userFolders.end()) {
if (std::find(folders.begin(), folders.end(), path) == folders.end()) { userFolders.emplace_back(path);
folders.emplace_back(path); saveToSetting();
writeSetting();
result = true; result = true;
} }
}); });
@@ -364,10 +367,9 @@ namespace hex::plugin::builtin {
ImGui::InfoTooltip("hex.builtin.setting.folders.add_folder"_lang); ImGui::InfoTooltip("hex.builtin.setting.folders.add_folder"_lang);
if (ImGui::IconButton(ICON_VS_REMOVE_CLOSE, ImGui::GetCustomColorVec4(ImGuiCustomCol_DescButton), ImVec2(30, 30))) { if (ImGui::IconButton(ICON_VS_REMOVE_CLOSE, ImGui::GetCustomColorVec4(ImGuiCustomCol_DescButton), ImVec2(30, 30))) {
if (!folders.empty()) { if (!userFolders.empty()) {
folders.erase(std::next(folders.begin(), currentItemIndex)); userFolders.erase(std::next(userFolders.begin(), currentItemIndex));
saveToSetting();
writeSetting();
result = true; result = true;
} }
@@ -480,10 +482,18 @@ namespace hex::plugin::builtin {
ImHexApi::System::setTheme(static_cast<ImHexApi::System::Theme>(theme)); ImHexApi::System::setTheme(static_cast<ImHexApi::System::Theme>(theme));
} }
static void loadFoldersSettings() {
static const std::string dirsSetting { "hex.builtin.setting.folders" };
auto dirs = ContentRegistry::Settings::getSetting(dirsSetting, dirsSetting);
loadUserFoldersFromSetting(dirs);
ImHexApi::System::setAdditionalFolderPaths(userFolders);
}
void loadSettings() { void loadSettings() {
loadInterfaceScalingSetting(); loadInterfaceScalingSetting();
loadFontSettings(); loadFontSettings();
loadThemeSettings(); loadThemeSettings();
loadFoldersSettings();
} }
} }

View File

@@ -712,8 +712,8 @@ namespace hex::plugin::builtin {
auto json = nlohmann::json::parse(response.body); auto json = nlohmann::json::parse(response.body);
resultTitle = json["query"]["pages"][0]["title"]; resultTitle = json["query"]["pages"][0]["title"].get<std::string>();
resultExtract = json["query"]["pages"][0]["extract"]; resultExtract = json["query"]["pages"][0]["extract"].get<std::string>();
if (!extendedSearch && resultExtract.ends_with(':')) { if (!extendedSearch && resultExtract.ends_with(':')) {
extendedSearch = true; extendedSearch = true;

View File

@@ -107,8 +107,11 @@ namespace hex::plugin::builtin {
u32 index = 0; u32 index = 0;
for (auto &path : s_selectableFiles) { for (auto &path : s_selectableFiles) {
ImGui::PushID(index);
if (ImGui::Selectable(path.filename().string().c_str(), index == s_selectableFileIndex)) if (ImGui::Selectable(path.filename().string().c_str(), index == s_selectableFileIndex))
s_selectableFileIndex = index; s_selectableFileIndex = index;
ImGui::PopID();
index++; index++;
} }

View File

@@ -34,11 +34,11 @@ namespace hex::plugin::builtin {
for (auto value : content["values"]) { for (auto value : content["values"]) {
Constant constant; Constant constant;
constant.category = content["name"]; constant.category = content["name"].get<std::string>();
constant.name = value["name"]; constant.name = value["name"].get<std::string>();
if (value.contains("desc")) if (value.contains("desc"))
constant.description = value["desc"]; constant.description = value["desc"].get<std::string>();
constant.value = value["value"]; constant.value = value["value"].get<std::string>();
auto type = value["type"]; auto type = value["type"];
if (type == "int10") if (type == "int10")

View File

@@ -104,8 +104,10 @@ namespace hex::plugin::builtin {
if (ImGui::BeginTabBar("##find_tabs")) { if (ImGui::BeginTabBar("##find_tabs")) {
if (ImGui::BeginTabItem("hex.builtin.view.hex_editor.search.hex"_lang)) { if (ImGui::BeginTabItem("hex.builtin.view.hex_editor.search.hex"_lang)) {
if (ImGui::InputText("##input", this->m_input, ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_CharsHexadecimal)) { if (ImGui::InputText("##input", this->m_input, ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_CharsHexadecimal)) {
this->m_shouldSearch = true; if (!this->m_input.empty()) {
this->m_backwards = false; this->m_shouldSearch = true;
this->m_backwards = false;
}
} }
this->drawButtons(); this->drawButtons();
@@ -119,8 +121,10 @@ namespace hex::plugin::builtin {
if (ImGui::BeginTabItem("hex.builtin.view.hex_editor.search.string"_lang)) { if (ImGui::BeginTabItem("hex.builtin.view.hex_editor.search.string"_lang)) {
if (ImGui::InputText("##input", this->m_input, ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_AutoSelectAll)) { if (ImGui::InputText("##input", this->m_input, ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_AutoSelectAll)) {
this->m_shouldSearch = true; if (!this->m_input.empty()) {
this->m_backwards = false; this->m_shouldSearch = true;
this->m_backwards = false;
}
} }
this->drawButtons(); this->drawButtons();
@@ -434,15 +438,15 @@ namespace hex::plugin::builtin {
const auto [decoded, advance] = encodingFile.getEncodingFor(buffer); const auto [decoded, advance] = encodingFile.getEncodingFor(buffer);
const ImColor color = [&decoded = decoded, &advance = advance]{ const ImColor color = [&decoded = decoded, &advance = advance]{
if (decoded.length() == 1 && std::isalnum(decoded[0])) if (decoded.length() == 1 && std::isalnum(decoded[0]))
return 0xFFFF8000; return ImGui::GetCustomColorU32(ImGuiCustomCol_ToolbarBlue);
else if (decoded.length() == 1 && advance == 1) else if (decoded.length() == 1 && advance == 1)
return 0xFF0000FF; return ImGui::GetCustomColorU32(ImGuiCustomCol_ToolbarRed);
else if (decoded.length() > 1 && advance == 1) else if (decoded.length() > 1 && advance == 1)
return 0xFF00FFFF; return ImGui::GetCustomColorU32(ImGuiCustomCol_ToolbarYellow);
else if (advance > 1) else if (advance > 1)
return 0xFFFFFFFF; return ImGui::GetColorU32(ImGuiCol_Text);
else else
return 0xFFFF8000; return ImGui::GetCustomColorU32(ImGuiCustomCol_ToolbarBlue);
}(); }();
return { std::string(decoded), advance, color }; return { std::string(decoded), advance, color };
@@ -830,16 +834,18 @@ namespace hex::plugin::builtin {
} while (offset < this->m_bytesPerRow); } while (offset < this->m_bytesPerRow);
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, ImVec2(0, 0)); ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, ImVec2(0, 0));
if (ImGui::BeginTable("##encoding_cell", encodingData.size(), ImGuiTableFlags_SizingFixedFit)) { ImGui::PushID(y);
if (ImGui::BeginTable("##encoding_cell", encodingData.size(), ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_NoKeepColumnsVisible)) {
ImGui::TableNextRow(); ImGui::TableNextRow();
for (const auto &[address, data] : encodingData) { for (const auto &[address, data] : encodingData) {
ImGui::TableNextColumn(); ImGui::TableNextColumn();
const auto cellStartPos = getCellPosition(); const auto cellStartPos = getCellPosition();
const auto cellSize = CharacterSize * data.advance; const auto cellSize = CharacterSize * ImVec2(std::max<float>(1, data.displayValue.length()), 1);
const bool cellHovered = ImGui::IsMouseHoveringRect(cellStartPos, cellStartPos + cellSize, true); const bool cellHovered = ImGui::IsMouseHoveringRect(cellStartPos, cellStartPos + cellSize, true);
const auto x = address % this->m_bytesPerRow; const auto x = address % this->m_bytesPerRow;
if (x < validBytes) { if (x < validBytes) {
auto [foregroundColor, backgroundColor] = cellColors[x]; auto [foregroundColor, backgroundColor] = cellColors[x];
@@ -854,7 +860,9 @@ namespace hex::plugin::builtin {
this->drawSelectionFrame(x, y, address, 1, cellStartPos, cellSize); this->drawSelectionFrame(x, y, address, 1, cellStartPos, cellSize);
} }
ImGui::PushItemWidth(cellSize.x);
ImGui::TextFormattedColored(data.color, "{}", data.displayValue); ImGui::TextFormattedColored(data.color, "{}", data.displayValue);
ImGui::PopItemWidth();
this->handleSelection(address, data.advance, &bytes[address % this->m_bytesPerRow], cellHovered); this->handleSelection(address, data.advance, &bytes[address % this->m_bytesPerRow], cellHovered);
} }
@@ -863,6 +871,7 @@ namespace hex::plugin::builtin {
ImGui::EndTable(); ImGui::EndTable();
} }
ImGui::PopStyleVar(); ImGui::PopStyleVar();
ImGui::PopID();
} }
@@ -1222,7 +1231,7 @@ namespace hex::plugin::builtin {
}); });
// Open file // Open file
ShortcutManager::addShortcut(this, CTRL + Keys::O, [] { ShortcutManager::addGlobalShortcut(CTRL + Keys::O, [] {
fs::openFileBrowser(fs::DialogMode::Open, {}, [](const auto &path) { fs::openFileBrowser(fs::DialogMode::Open, {}, [](const auto &path) {
EventManager::post<RequestOpenFile>(path); EventManager::post<RequestOpenFile>(path);
}); });

View File

@@ -67,7 +67,7 @@ namespace hex::plugin::builtin {
return false; return false;
} }
static bool beginPatternTable(prv::Provider *&provider, const std::vector<std::shared_ptr<pl::Pattern>> &patterns, std::vector<std::shared_ptr<pl::Pattern>> &sortedPatterns) { static bool beginPatternTable(prv::Provider *&provider, const std::vector<std::shared_ptr<pl::Pattern>> &patterns, std::vector<pl::Pattern*> &sortedPatterns) {
if (ImGui::BeginTable("##Patterntable", 6, ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_Sortable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_RowBg | ImGuiTableFlags_ScrollY)) { if (ImGui::BeginTable("##Patterntable", 6, ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_Sortable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_RowBg | ImGuiTableFlags_ScrollY)) {
ImGui::TableSetupScrollFreeze(0, 1); ImGui::TableSetupScrollFreeze(0, 1);
ImGui::TableSetupColumn("hex.builtin.view.pattern_data.var_name"_lang, 0, 0, ImGui::GetID("name")); ImGui::TableSetupColumn("hex.builtin.view.pattern_data.var_name"_lang, 0, 0, ImGui::GetID("name"));
@@ -80,10 +80,12 @@ namespace hex::plugin::builtin {
auto sortSpecs = ImGui::TableGetSortSpecs(); auto sortSpecs = ImGui::TableGetSortSpecs();
if (sortSpecs->SpecsDirty || sortedPatterns.empty()) { if (sortSpecs->SpecsDirty || sortedPatterns.empty()) {
sortedPatterns = patterns; std::transform(patterns.begin(), patterns.end(), std::back_inserter(sortedPatterns), [](const std::shared_ptr<pl::Pattern> &pattern) {
return pattern.get();
});
std::sort(sortedPatterns.begin(), sortedPatterns.end(), [&sortSpecs, &provider](const std::shared_ptr<pl::Pattern> &left, const std::shared_ptr<pl::Pattern> &right) -> bool { std::sort(sortedPatterns.begin(), sortedPatterns.end(), [&sortSpecs, &provider](pl::Pattern *left, pl::Pattern *right) -> bool {
return sortPatterns(provider, sortSpecs, left.get(), right.get()); return sortPatterns(provider, sortSpecs, left, right);
}); });
for (auto &pattern : sortedPatterns) for (auto &pattern : sortedPatterns)

View File

@@ -28,7 +28,7 @@ namespace hex::plugin::builtin {
langDef.mKeywords.insert(k); langDef.mKeywords.insert(k);
static constexpr std::array builtInTypes = { static constexpr std::array builtInTypes = {
"u8", "u16", "u32", "u64", "u128", "s8", "s16", "s32", "s64", "s128", "float", "double", "char", "char16", "bool", "padding", "str", "auto" "u8", "u16", "u24", "u32", "u48", "u64", "u96", "u128", "s8", "s16", "s24", "s32", "s48", "s64", "s96", "s128", "float", "double", "char", "char16", "bool", "padding", "str", "auto"
}; };
for (const auto name : builtInTypes) { for (const auto name : builtInTypes) {
TextEditor::Identifier id; TextEditor::Identifier id;
@@ -93,9 +93,7 @@ namespace hex::plugin::builtin {
}); });
EventManager::subscribe<RequestSetPatternLanguageCode>(this, [this](const std::string &code) { EventManager::subscribe<RequestSetPatternLanguageCode>(this, [this](const std::string &code) {
this->m_textEditor.SelectAll(); this->m_textEditor.SetText(code);
this->m_textEditor.Delete();
this->m_textEditor.InsertText(code);
}); });
EventManager::subscribe<EventFileLoaded>(this, [this](const std::fs::path &path) { EventManager::subscribe<EventFileLoaded>(this, [this](const std::fs::path &path) {
@@ -127,7 +125,7 @@ namespace hex::plugin::builtin {
std::error_code errorCode; std::error_code errorCode;
for (const auto &dir : fs::getDefaultPaths(fs::ImHexPath::Patterns)) { for (const auto &dir : fs::getDefaultPaths(fs::ImHexPath::Patterns)) {
for (auto &entry : std::fs::directory_iterator(dir, errorCode)) { for (auto &entry : std::fs::recursive_directory_iterator(dir, errorCode)) {
foundCorrectType = false; foundCorrectType = false;
if (!entry.is_regular_file()) if (!entry.is_regular_file())
continue; continue;
@@ -236,31 +234,42 @@ namespace hex::plugin::builtin {
if (this->m_runningEvaluators != 0) if (this->m_runningEvaluators != 0)
return std::nullopt; return std::nullopt;
const auto pattern = ImHexApi::Provider::get()->getPatternLanguageRuntime().getPattern(address); bool foundColor = false;
if (pattern != nullptr) ImColor color = ImColor(0xFF, 0xFF, 0xFF, 0x70);
return pattern->getColor(); for (const auto &pattern : ImHexApi::Provider::get()->getPatternLanguageRuntime().getPatterns(address)) {
else color = ImAlphaBlendColors(color, pattern->getColor());
foundColor = true;
}
if (!foundColor)
return std::nullopt; return std::nullopt;
else {
color.Value.w = 0x70;
return color;
}
}); });
ImHexApi::HexEditor::addTooltipProvider([this](u64 address, const u8 *data, size_t size) { ImHexApi::HexEditor::addTooltipProvider([this](u64 address, const u8 *data, size_t size) {
hex::unused(data, size); hex::unused(data, size);
auto pattern = ImHexApi::Provider::get()->getPatternLanguageRuntime().getPattern(address); auto patterns = ImHexApi::Provider::get()->getPatternLanguageRuntime().getPatterns(address);
if (pattern != nullptr) { if (!patterns.empty()) {
ImGui::BeginTooltip(); ImGui::BeginTooltip();
if (ImGui::BeginTable("##tooltips", 1, ImGuiTableFlags_NoHostExtendX | ImGuiTableFlags_RowBg | ImGuiTableFlags_NoClip)) { if (ImGui::BeginTable("##tooltips", 1, ImGuiTableFlags_NoHostExtendX | ImGuiTableFlags_RowBg | ImGuiTableFlags_NoClip)) {
ImGui::TableNextRow(); for (const auto &pattern : patterns) {
ImGui::TableNextColumn(); auto tooltipColor = (pattern->getColor() & 0x00FF'FFFF) | 0x7000'0000;
ImGui::PushStyleColor(ImGuiCol_TableRowBg, tooltipColor);
ImGui::PushStyleColor(ImGuiCol_TableRowBgAlt, tooltipColor);
this->drawPatternTooltip(pattern); ImGui::TableNextRow();
ImGui::TableNextColumn();
auto tooltipColor = (pattern->getColor() & 0x00FF'FFFF) | 0x7000'0000; ImGui::PopStyleColor(2);
ImGui::PushStyleColor(ImGuiCol_TableRowBg, tooltipColor);
ImGui::PushStyleColor(ImGuiCol_TableRowBgAlt, tooltipColor); this->drawPatternTooltip(pattern);
}
ImGui::EndTable(); ImGui::EndTable();
ImGui::PopStyleColor(2);
} }
ImGui::EndTooltip(); ImGui::EndTooltip();
} }
@@ -558,25 +567,27 @@ namespace hex::plugin::builtin {
if (variable.outVariable) { if (variable.outVariable) {
ImGui::TextUnformatted(pl::Token::literalToString(variable.value, true).c_str()); ImGui::TextUnformatted(pl::Token::literalToString(variable.value, true).c_str());
} else if (variable.inVariable) { } else if (variable.inVariable) {
const std::string label { "##" + name };
if (pl::Token::isSigned(variable.type)) { if (pl::Token::isSigned(variable.type)) {
i64 value = hex::get_or<i128>(variable.value, 0); i64 value = hex::get_or<i128>(variable.value, 0);
ImGui::InputScalar("", ImGuiDataType_S64, &value); ImGui::InputScalar(label.c_str(), ImGuiDataType_S64, &value);
variable.value = i128(value); variable.value = i128(value);
} else if (pl::Token::isUnsigned(variable.type)) { } else if (pl::Token::isUnsigned(variable.type)) {
u64 value = hex::get_or<u128>(variable.value, 0); u64 value = hex::get_or<u128>(variable.value, 0);
ImGui::InputScalar("", ImGuiDataType_U64, &value); ImGui::InputScalar(label.c_str(), ImGuiDataType_U64, &value);
variable.value = u128(value); variable.value = u128(value);
} else if (pl::Token::isFloatingPoint(variable.type)) { } else if (pl::Token::isFloatingPoint(variable.type)) {
double value = hex::get_or<double>(variable.value, 0.0); double value = hex::get_or<double>(variable.value, 0.0);
ImGui::InputScalar("", ImGuiDataType_Double, &value); ImGui::InputScalar(label.c_str(), ImGuiDataType_Double, &value);
variable.value = value; variable.value = value;
} else if (variable.type == pl::Token::ValueType::Boolean) { } else if (variable.type == pl::Token::ValueType::Boolean) {
bool value = hex::get_or<bool>(variable.value, false); bool value = hex::get_or<bool>(variable.value, false);
ImGui::Checkbox("", &value); ImGui::Checkbox(label.c_str(), &value);
variable.value = value; variable.value = value;
} else if (variable.type == pl::Token::ValueType::Character) { } else if (variable.type == pl::Token::ValueType::Character) {
char buffer[2]; char buffer[2];
ImGui::InputText("", buffer, 2); ImGui::InputText(label.c_str(), buffer, 2);
variable.value = buffer[0]; variable.value = buffer[0];
} }
} }
@@ -717,7 +728,6 @@ namespace hex::plugin::builtin {
auto ast = this->m_parserRuntime->parseString(code); auto ast = this->m_parserRuntime->parseString(code);
this->m_patternVariables.clear(); this->m_patternVariables.clear();
this->m_patternTypes.clear();
if (ast) { if (ast) {
for (auto &node : *ast) { for (auto &node : *ast) {
@@ -752,7 +762,7 @@ namespace hex::plugin::builtin {
this->m_textEditor.SetErrorMarkers({}); this->m_textEditor.SetErrorMarkers({});
this->m_console.clear(); this->m_console.clear();
this->clearPatterns(); ImHexApi::Provider::get()->getPatternLanguageRuntime().reset();
EventManager::post<EventHighlightingChanged>(); EventManager::post<EventHighlightingChanged>();

View File

@@ -167,8 +167,9 @@ namespace hex {
} }
void PatternDrawer::visit(pl::PatternString& pattern) { void PatternDrawer::visit(pl::PatternString& pattern) {
this->createDefaultEntry(pattern, pattern.getFormattedValue(), pattern.getValue()); if (pattern.getSize() > 0)
} this->createDefaultEntry(pattern, pattern.getFormattedValue(), pattern.getValue());
}
void PatternDrawer::visit(pl::PatternStruct& pattern) { void PatternDrawer::visit(pl::PatternStruct& pattern) {
bool open = true; bool open = true;
@@ -237,9 +238,8 @@ namespace hex {
} }
void PatternDrawer::visit(pl::PatternWideString& pattern) { void PatternDrawer::visit(pl::PatternWideString& pattern) {
std::string utf8String = pattern.getValue(); if (pattern.getSize() > 0)
this->createDefaultEntry(pattern, pattern.getFormattedValue(), pattern.getValue());
this->createDefaultEntry(pattern, pattern.getFormattedValue(), utf8String);
} }
void PatternDrawer::createDefaultEntry(const pl::Pattern &pattern, const std::string &value, pl::Token::Literal &&literal) const { void PatternDrawer::createDefaultEntry(const pl::Pattern &pattern, const std::string &value, pl::Token::Literal &&literal) const {