Compare commits

..

18 Commits

Author SHA1 Message Date
WerWolv
ee2838bada build: Bumped version to 1.24.2 2022-10-10 20:52:48 +02:00
iTrooz_
4d17265e90 git: Use action to manage ccache + minor fixes (#775)
* use action for ccache + limit cache size

* remove 'prepare cache' step for Windows

* remove libpython from CI

* fix the restore key for MacOS

* remove Rust from CI

* do not pin appimage-builder version since issue with it has been resolved

* use ccache action for CodeQL

* Rebased onto latest master

Co-authored-by: WerWolv <werwolv98@gmail.com>
2022-10-10 20:37:00 +02:00
WerWolv
6a6b860622 patterns: Updated pattern language 2022-10-10 20:33:43 +02:00
WerWolv
e78c452daf fix: Hex editor selection not showing rendering properly 2022-10-10 20:33:34 +02:00
WerWolv
86e33a1ee9 build: Bumped version to 1.24.1 2022-10-10 19:11:30 +02:00
WerWolv
37850ad85a patterns: Updated pattern language 2022-10-10 18:15:11 +02:00
WerWolv
daca49658e ui: Fix highlighting of separator column in hex editor
Fixes #776
2022-10-10 17:26:05 +02:00
WerWolv
6975d7e2cd patterns: Updated pattern language 2022-10-10 16:09:50 +02:00
WerWolv
5b8bed6083 patterns: Updated pattern language 2022-10-10 14:42:13 +02:00
WerWolv
7474aa3e5d fix: New lines in wide string messing up data inspector drawing 2022-10-10 14:41:24 +02:00
WerWolv
c6d2d51d4c ui: Make sure sealed patterns get highlighted properly when selected 2022-10-10 14:40:49 +02:00
WerWolv
9055105627 fix: Evaluator not exiting evaluating state correctly on error 2022-10-09 17:31:06 +02:00
WerWolv
a44de63e24 fix: Build failing on Linux 2022-10-09 16:34:53 +02:00
WerWolv
8fc7931132 patterns: Updated pattern language 2022-10-09 15:56:41 +02:00
WerWolv
4070833229 ui: Highlight selected patterns in pattern data view 2022-10-09 15:56:26 +02:00
WerWolv
3a9c3f939e sys: Properly center hex view around selection when jumping 2022-10-09 14:47:38 +02:00
WerWolv
aa42fb5076 patterns: Updated pattern language 2022-10-08 16:28:49 +02:00
WerWolv
50158a7977 sys: Fixed hex editor scrolling issues 2022-10-08 16:23:15 +02:00
14 changed files with 188 additions and 138 deletions

View File

@@ -25,14 +25,13 @@ jobs:
with: with:
languages: 'cpp' languages: 'cpp'
- name: 📜 Restore ccache - name: 📜 Setup ccache
uses: actions/cache@v3 uses: hendrikmuhs/ccache-action@v1.2
with: with:
path: |
~/.cache/ccache
key: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build-${{ github.run_id }} key: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build-${{ github.run_id }}
restore-keys: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build restore-keys: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build
max-size: 50M
- name: 📜 Restore CMakeCache - name: 📜 Restore CMakeCache
uses: actions/cache@v3 uses: actions/cache@v3
with: with:

View File

@@ -28,21 +28,13 @@ jobs:
with: with:
submodules: recursive submodules: recursive
- name: 📜 Prepare Cache - name: 📜 Setup ccache
id: prep-ccache uses: hendrikmuhs/ccache-action@v1.2
shell: bash
run: |
mkdir -p "${CCACHE_DIR}"
echo "::set-output name=dir::$CCACHE_DIR"
- name: 📜 Restore ccache
uses: actions/cache@v3
id: cache-ccache id: cache-ccache
with: with:
path: |
${{ steps.prep-ccache.outputs.dir }}
key: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build-${{ github.run_id }} key: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build-${{ github.run_id }}
restore-keys: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build restore-keys: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build
max-size: 50M
- name: 📜 Restore CMakeCache - name: 📜 Restore CMakeCache
uses: actions/cache@v3 uses: actions/cache@v3
@@ -64,37 +56,23 @@ jobs:
glfw:p glfw:p
file:p file:p
mbedtls:p mbedtls:p
python:p
freetype:p freetype:p
dlfcn:p dlfcn:p
- name: ⬇️ Install dependencies
run: |
curl --proto '=https' --tlsv1.2 -sSf https://win.rustup.rs > rustup-init.exe
./rustup-init.exe -y --default-host=x86_64-pc-windows-gnu --default-toolchain=none
rm rustup-init.exe
$USERPROFILE/.cargo/bin/rustup.exe target add x86_64-pc-windows-gnu
$USERPROFILE/.cargo/bin/rustup.exe default nightly
# Windows cmake build # Windows cmake build
- name: 🛠️ Build - name: 🛠️ Build
run: | run: |
mkdir -p build mkdir -p build
cd build cd build
# Get path to mingw python library
PYTHON_LIB_NAME=$(pkg-config --libs-only-l python3 | sed 's/^-l//' | sed 's/ //')
PYTHON_LIB_PATH=$(cygpath -m $(which lib${PYTHON_LIB_NAME}.dll))
cmake -G "MinGW Makefiles" \ cmake -G "MinGW Makefiles" \
-DCMAKE_BUILD_TYPE=$BUILD_TYPE \ -DCMAKE_BUILD_TYPE=$BUILD_TYPE \
-DCMAKE_INSTALL_PREFIX="$PWD/install" \ -DCMAKE_INSTALL_PREFIX="$PWD/install" \
-DCREATE_PACKAGE=ON \ -DCREATE_PACKAGE=ON \
-DPython_LIBRARY="$PYTHON_LIB_PATH" \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \ -DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \ -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DCMAKE_C_FLAGS="-fuse-ld=lld" \ -DCMAKE_C_FLAGS="-fuse-ld=lld" \
-DCMAKE_CXX_FLAGS="-fuse-ld=lld" \ -DCMAKE_CXX_FLAGS="-fuse-ld=lld" \
-DRUST_PATH="$USERPROFILE/.cargo/bin/" \
-DIMHEX_PATTERNS_PULL_MASTER=ON \ -DIMHEX_PATTERNS_PULL_MASTER=ON \
.. ..
mingw32-make -j4 install mingw32-make -j4 install
@@ -166,13 +144,12 @@ jobs:
run: | run: |
echo "IMHEX_VERSION=`cat VERSION`" >> $GITHUB_ENV echo "IMHEX_VERSION=`cat VERSION`" >> $GITHUB_ENV
- name: 📜 Restore ccache - name: 📜 Setup ccache
uses: actions/cache@v3 uses: hendrikmuhs/ccache-action@v1.2
with: with:
path: |
~/Library/Caches/ccache
key: ${{ runner.os }}-${{ matrix.suffix }}-${{ secrets.CACHE_VERSION }}-build-${{ github.run_id }} key: ${{ runner.os }}-${{ matrix.suffix }}-${{ secrets.CACHE_VERSION }}-build-${{ github.run_id }}
restore-keys: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build restore-keys: ${{ runner.os }}-${{ matrix.suffix }}-${{ secrets.CACHE_VERSION }}-build
max-size: 50M
- name: 📜 Restore CMakeCache - name: 📜 Restore CMakeCache
@@ -260,13 +237,12 @@ jobs:
with: with:
submodules: recursive submodules: recursive
- name: 📜 Restore ccache - name: 📜 Setup ccache
uses: actions/cache@v3 uses: hendrikmuhs/ccache-action@v1.2
with: with:
path: |
~/.cache/ccache
key: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build-${{ github.run_id }} key: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build-${{ github.run_id }}
restore-keys: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build restore-keys: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build
max-size: 50M
- name: 📜 Restore other caches - name: 📜 Restore other caches
uses: actions/cache@v3 uses: actions/cache@v3
@@ -290,14 +266,7 @@ jobs:
sudo apt install -y python3-pip python3-setuptools desktop-file-utils libgdk-pixbuf2.0-dev fuse sudo apt install -y python3-pip python3-setuptools desktop-file-utils libgdk-pixbuf2.0-dev fuse
sudo wget https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage -O /usr/local/bin/appimagetool sudo wget https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage -O /usr/local/bin/appimagetool
sudo chmod +x /usr/local/bin/appimagetool sudo chmod +x /usr/local/bin/appimagetool
sudo pip3 install appimage-builder==1.0.0 sudo pip3 install appimage-builder
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > rustup-init.sh
sh rustup-init.sh -y --default-toolchain none
rm rustup-init.sh
$HOME/.cargo/bin/rustup install nightly
$HOME/.cargo/bin/rustup target add x86_64-unknown-linux-gnu
$HOME/.cargo/bin/rustup default nightly
# Ubuntu cmake build # Ubuntu cmake build
- name: 🛠️ Build - name: 🛠️ Build
@@ -311,7 +280,6 @@ jobs:
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \ -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DCMAKE_C_FLAGS="-fuse-ld=lld" \ -DCMAKE_C_FLAGS="-fuse-ld=lld" \
-DCMAKE_CXX_FLAGS="-fuse-ld=lld" \ -DCMAKE_CXX_FLAGS="-fuse-ld=lld" \
-DRUST_PATH="$HOME/.cargo/bin/" \
-DIMHEX_PATTERNS_PULL_MASTER=ON \ -DIMHEX_PATTERNS_PULL_MASTER=ON \
.. ..
make -j 4 install DESTDIR=DebDir make -j 4 install DESTDIR=DebDir
@@ -347,7 +315,6 @@ jobs:
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \ -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DCMAKE_C_FLAGS="-fuse-ld=lld" \ -DCMAKE_C_FLAGS="-fuse-ld=lld" \
-DCMAKE_CXX_FLAGS="-fuse-ld=lld" \ -DCMAKE_CXX_FLAGS="-fuse-ld=lld" \
-DRUST_PATH="$HOME/.cargo/bin/" \
-DIMHEX_PATTERNS_PULL_MASTER=ON \ -DIMHEX_PATTERNS_PULL_MASTER=ON \
-DIMHEX_PLUGINS_IN_SHARE=ON \ -DIMHEX_PLUGINS_IN_SHARE=ON \
-DIMHEX_USE_BUNDLED_CA=ON \ -DIMHEX_USE_BUNDLED_CA=ON \
@@ -412,13 +379,12 @@ jobs:
run: | run: |
dist/get_deps_archlinux.sh --noconfirm dist/get_deps_archlinux.sh --noconfirm
- name: 📜 Restore ccache - name: 📜 Setup ccache
uses: actions/cache@v3 uses: hendrikmuhs/ccache-action@v1.2
with: with:
path: |
~/.cache/ccache
key: archlinux-${{ secrets.CACHE_VERSION }}-build-${{ github.run_id }} key: archlinux-${{ secrets.CACHE_VERSION }}-build-${{ github.run_id }}
restore-keys: archlinux-${{ secrets.CACHE_VERSION }}-build restore-keys: archlinux-${{ secrets.CACHE_VERSION }}-build
max-size: 50M
- name: 📜 Restore CMakeCache - name: 📜 Restore CMakeCache
uses: actions/cache@v3 uses: actions/cache@v3
@@ -514,7 +480,6 @@ jobs:
libcurl-devel \ libcurl-devel \
llvm-devel \ llvm-devel \
mbedtls-devel \ mbedtls-devel \
python3-devel \
rpm-build \ rpm-build \
yara-devel yara-devel
@@ -527,13 +492,12 @@ jobs:
run: | run: |
dist/get_deps_fedora.sh dist/get_deps_fedora.sh
- name: 📜 Restore ccache - name: 📜 Setup ccache
uses: actions/cache@v3 uses: hendrikmuhs/ccache-action@v1.2
with: with:
path: |
~/.cache/ccache
key: fedora-${{ matrix.release }}-${{ secrets.CACHE_VERSION }}-build-${{ github.run_id }} key: fedora-${{ matrix.release }}-${{ secrets.CACHE_VERSION }}-build-${{ github.run_id }}
restore-keys: fedora-${{ matrix.release }}-${{ secrets.CACHE_VERSION }}-build restore-keys: fedora-${{ matrix.release }}-${{ secrets.CACHE_VERSION }}-build
max-size: 50M
- name: 📜 Set version variable - name: 📜 Set version variable
run: | run: |

View File

@@ -22,13 +22,12 @@ jobs:
with: with:
submodules: recursive submodules: recursive
- name: 📜 Restore ccache - name: 📜 Setup ccache
uses: actions/cache@v3 uses: hendrikmuhs/ccache-action@v1.2
with: with:
path: |
~/.cache/ccache
key: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build-${{ github.run_id }} key: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build-${{ github.run_id }}
restore-keys: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build restore-keys: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build
max-size: 50M
- name: 📜 Restore CMakeCache - name: 📜 Restore CMakeCache

View File

@@ -1 +1 @@
1.24.0 1.24.2

View File

@@ -137,6 +137,7 @@ set(LIBIMHEX_SOURCES
source/helpers/encoding_file.cpp source/helpers/encoding_file.cpp
source/helpers/logger.cpp source/helpers/logger.cpp
source/helpers/tar.cpp source/helpers/tar.cpp
source/helpers/types.cpp
source/providers/provider.cpp source/providers/provider.cpp

View File

@@ -1,8 +1,5 @@
#pragma once #pragma once
#include <cstdint>
#include <cstddef>
#include <hex/helpers/types.hpp> #include <hex/helpers/types.hpp>
#include <hex/helpers/intrinsics.hpp> #include <hex/helpers/intrinsics.hpp>

View File

@@ -1,5 +1,8 @@
#pragma once #pragma once
#include <cstddef>
#include <cstdint>
using u8 = std::uint8_t; using u8 = std::uint8_t;
using u16 = std::uint16_t; using u16 = std::uint16_t;
using u32 = std::uint32_t; using u32 = std::uint32_t;
@@ -20,29 +23,14 @@ namespace hex {
u64 address; u64 address;
size_t size; size_t size;
[[nodiscard]] constexpr bool isWithin(const Region &other) const { [[nodiscard]] bool isWithin(const Region &other) const;
return (this->getStartAddress() >= other.getStartAddress()) && (this->getEndAddress() <= other.getEndAddress()) && *this != Invalid() && other != Invalid(); [[nodiscard]] bool overlaps(const Region &other) const;
}
[[nodiscard]] constexpr bool overlaps(const Region &other) const { [[nodiscard]] u64 getStartAddress() const;
return (this->getEndAddress() >= other.getStartAddress()) && (this->getStartAddress() < other.getEndAddress()) && *this != Invalid() && other != Invalid(); [[nodiscard]] u64 getEndAddress() const;
} [[nodiscard]] size_t getSize() const;
[[nodiscard]] constexpr u64 getStartAddress() const { bool operator==(const Region &other) const;
return this->address;
}
[[nodiscard]] constexpr u64 getEndAddress() const {
return this->address + this->size - 1;
}
[[nodiscard]] constexpr size_t getSize() const {
return this->size;
}
constexpr bool operator==(const Region &other) const {
return this->address == other.address && this->size == other.size;
}
constexpr static Region Invalid() { constexpr static Region Invalid() {
return { 0, 0 }; return { 0, 0 };

View File

@@ -0,0 +1,41 @@
#include <hex/helpers/types.hpp>
namespace hex {
[[nodiscard]] bool Region::isWithin(const Region &other) const {
if (*this == Invalid() || other == Invalid())
return false;
if (this->getStartAddress() >= other.getStartAddress() && this->getEndAddress() <= other.getEndAddress())
return true;
return false;
}
[[nodiscard]] bool Region::overlaps(const Region &other) const {
if (*this == Invalid() || other == Invalid())
return false;
if (this->getEndAddress() >= other.getStartAddress() && this->getStartAddress() <= other.getEndAddress())
return true;
return false;
}
[[nodiscard]] u64 Region::getStartAddress() const {
return this->address;
}
[[nodiscard]] u64 Region::getEndAddress() const {
return this->address + this->size - 1;
}
[[nodiscard]] size_t Region::getSize() const {
return this->size;
}
bool Region::operator==(const Region &other) const {
return this->address == other.address && this->size == other.size;
}
}

View File

@@ -68,8 +68,11 @@ namespace hex::plugin::builtin {
return data.selectionStart.has_value() && data.selectionEnd.has_value(); return data.selectionStart.has_value() && data.selectionEnd.has_value();
} }
void jumpToSelection() { void jumpToSelection(bool center = true) {
this->m_shouldJumpToSelection = true; this->m_shouldJumpToSelection = true;
if (center)
this->m_centerOnJump = true;
} }
void scrollToSelection() { void scrollToSelection() {
@@ -111,6 +114,7 @@ namespace hex::plugin::builtin {
void drawFooter(const ImVec2 &size); void drawFooter(const ImVec2 &size);
void handleSelection(u64 address, u32 bytesPerCell, const u8 *data, bool cellHovered); void handleSelection(u64 address, u32 bytesPerCell, const u8 *data, bool cellHovered);
std::optional<color_t> applySelectionColor(u64 byteAddress, std::optional<color_t> color);
private: private:
u16 m_bytesPerRow = 16; u16 m_bytesPerRow = 16;
@@ -118,6 +122,7 @@ namespace hex::plugin::builtin {
ContentRegistry::HexEditor::DataVisualizer *m_currDataVisualizer; ContentRegistry::HexEditor::DataVisualizer *m_currDataVisualizer;
bool m_shouldJumpToSelection = false; bool m_shouldJumpToSelection = false;
bool m_centerOnJump = false;
bool m_shouldScrollToSelection = false; bool m_shouldScrollToSelection = false;
bool m_shouldJumpWhenOffScreen = false; bool m_shouldJumpWhenOffScreen = false;
bool m_shouldUpdateScrollPosition = false; bool m_shouldUpdateScrollPosition = false;

View File

@@ -450,7 +450,8 @@ namespace hex::plugin::builtin {
[](auto c) { return c == 0x00; }); [](auto c) { return c == 0x00; });
buffer.erase(it, buffer.end()); buffer.erase(it, buffer.end());
value = copyValue = std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t>("Invalid").to_bytes(stringBuffer.data()); auto string = std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t>("Invalid").to_bytes(stringBuffer.data());
value = copyValue = hex::encodeByteString({ string.begin(), string.end() });
if (value.size() > MaxStringLength) { if (value.size() > MaxStringLength) {
value.resize(MaxStringLength); value.resize(MaxStringLength);

View File

@@ -34,6 +34,43 @@ namespace hex {
using namespace ::std::literals::string_literals; using namespace ::std::literals::string_literals;
bool isPatternSelected(u64 address, u64 size) {
auto currSelection = ImHexApi::HexEditor::getSelection();
if (!currSelection.has_value())
return false;
return Region{ address, size }.overlaps(*currSelection);
}
template<typename T>
auto highlightWhenSelected(u64 address, u64 size, const T &callback) {
constexpr bool HasReturn = !requires(T t) { { t() } -> std::same_as<void>; };
auto selected = isPatternSelected(address, size);
if (selected)
ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetStyleColorVec4(ImGuiCol_HeaderActive));
if constexpr (HasReturn) {
auto result = callback();
if (selected)
ImGui::PopStyleColor();
return result;
} else {
callback();
if (selected)
ImGui::PopStyleColor();
}
}
template<typename T>
auto highlightWhenSelected(const pl::ptrn::Pattern& pattern, const T &callback) {
return highlightWhenSelected(pattern.getOffset(), pattern.getSize(), callback);
}
void createLeafNode(const pl::ptrn::Pattern& pattern) { void createLeafNode(const pl::ptrn::Pattern& pattern) {
ImGui::TreeNodeEx(pattern.getDisplayName().c_str(), ImGuiTreeNodeFlags_Leaf | ImGui::TreeNodeEx(pattern.getDisplayName().c_str(), ImGuiTreeNodeFlags_Leaf |
ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_NoTreePushOnOpen |
@@ -44,12 +81,13 @@ namespace hex {
bool createTreeNode(const pl::ptrn::Pattern& pattern) { bool createTreeNode(const pl::ptrn::Pattern& pattern) {
if (pattern.isSealed()) { if (pattern.isSealed()) {
ImGui::Indent(); ImGui::Indent();
ImGui::TextUnformatted(pattern.getDisplayName().c_str()); highlightWhenSelected(pattern, [&]{ ImGui::TextUnformatted(pattern.getDisplayName().c_str()); });
ImGui::Unindent(); ImGui::Unindent();
return false; return false;
} }
else else {
return ImGui::TreeNodeEx(pattern.getDisplayName().c_str(), ImGuiTreeNodeFlags_SpanFullWidth); return highlightWhenSelected(pattern, [&]{ return ImGui::TreeNodeEx(pattern.getDisplayName().c_str(), ImGuiTreeNodeFlags_SpanFullWidth);});
}
} }
void drawTypenameColumn(const pl::ptrn::Pattern& pattern, const std::string& pattern_name) { void drawTypenameColumn(const pl::ptrn::Pattern& pattern, const std::string& pattern_name) {
@@ -60,7 +98,7 @@ namespace hex {
} }
void drawNameColumn(const pl::ptrn::Pattern& pattern) { void drawNameColumn(const pl::ptrn::Pattern& pattern) {
ImGui::TextUnformatted(pattern.getDisplayName().c_str()); highlightWhenSelected(pattern, [&]{ ImGui::TextUnformatted(pattern.getDisplayName().c_str()); });
ImGui::TableNextColumn(); ImGui::TableNextColumn();
} }
@@ -387,7 +425,7 @@ namespace hex {
size_t chunkSize = (endOffset - startOffset) + endSize; size_t chunkSize = (endOffset - startOffset) + endSize;
auto chunkOpen = ImGui::TreeNode(hex::format("[{} ... {}]", i, endIndex - 1).c_str()); auto chunkOpen = highlightWhenSelected(startOffset, ((endOffset + endSize) - startOffset) - 1, [&]{ return ImGui::TreeNodeEx(hex::format("[{} ... {}]", i, endIndex - 1).c_str(), ImGuiTreeNodeFlags_SpanFullWidth); });
ImGui::TableNextColumn(); ImGui::TableNextColumn();
drawColorColumn(pattern); drawColorColumn(pattern);
ImGui::TextFormatted("0x{0:08X} : 0x{1:08X}", startOffset, startOffset + chunkSize - (pattern.getSize() == 0 ? 0 : 1)); ImGui::TextFormatted("0x{0:08X} : 0x{1:08X}", startOffset, startOffset + chunkSize - (pattern.getSize() == 0 ? 0 : 1));

View File

@@ -522,6 +522,24 @@ namespace hex::plugin::builtin {
return std::nullopt; return std::nullopt;
} }
std::optional<color_t> ViewHexEditor::applySelectionColor(u64 byteAddress, std::optional<color_t> color) {
if (this->isSelectionValid()) {
auto selection = this->getSelection();
if (byteAddress >= selection.getStartAddress() && byteAddress <= selection.getEndAddress()) {
if (color.has_value())
color = (ImAlphaBlendColors(color.value(), this->m_selectionColor)) & 0x00FFFFFF;
else
color = this->m_selectionColor;
}
}
if (color.has_value())
color = (*color & 0x00FFFFFF) | (this->m_selectionColor & 0xFF000000);
return color;
}
struct CustomEncodingData { struct CustomEncodingData {
std::string displayValue; std::string displayValue;
size_t advance; size_t advance;
@@ -811,25 +829,7 @@ namespace hex::plugin::builtin {
// Query cell colors // Query cell colors
if (x < std::ceil(float(validBytes) / bytesPerCell)) { if (x < std::ceil(float(validBytes) / bytesPerCell)) {
const auto foregroundColor = queryForegroundColor(byteAddress, &bytes[x * cellBytes], cellBytes); const auto foregroundColor = queryForegroundColor(byteAddress, &bytes[x * cellBytes], cellBytes);
const auto backgroundColor = [&]{ const auto backgroundColor = queryBackgroundColor(byteAddress, &bytes[x * cellBytes], cellBytes);
auto color = queryBackgroundColor(byteAddress, &bytes[x * cellBytes], cellBytes);
if (this->isSelectionValid()) {
auto selection = this->getSelection();
if (byteAddress >= selection.getStartAddress() && byteAddress <= selection.getEndAddress()) {
if (color.has_value())
color = (ImAlphaBlendColors(color.value(), this->m_selectionColor)) & 0x00FFFFFF;
else
color = this->m_selectionColor;
}
}
if (color.has_value())
color = (*color & 0x00FFFFFF) | (this->m_selectionColor & 0xFF000000);
return color;
}();
cellColors.emplace_back( cellColors.emplace_back(
foregroundColor, foregroundColor,
@@ -862,13 +862,16 @@ namespace hex::plugin::builtin {
auto [foregroundColor, backgroundColor] = cellColors[x]; auto [foregroundColor, backgroundColor] = cellColors[x];
if (isColumnSeparatorColumn(x + 1, columnCount)) { if (isColumnSeparatorColumn(x + 1, columnCount)) {
if (this->isSelectionValid() && this->getSelection().getEndAddress() != x + y * columnCount) auto separatorAddress = x + y * columnCount;
cellSize.x += SeparatorColumWidth + 1; if ((this->isSelectionValid() && this->getSelection().overlaps({ separatorAddress, 1 }) && this->getSelection().getEndAddress() != separatorAddress) || cellColors[x] == cellColors[x + 1])
cellSize.x += SeparatorColumWidth + 1;
} }
if (y == u64(clipper.DisplayStart)) if (y == u64(clipper.DisplayStart))
cellSize.y -= (ImGui::GetStyle().CellPadding.y + 1); cellSize.y -= (ImGui::GetStyle().CellPadding.y + 1);
backgroundColor = applySelectionColor(byteAddress, backgroundColor);
// Draw highlights and selection // Draw highlights and selection
if (backgroundColor.has_value()) { if (backgroundColor.has_value()) {
auto drawList = ImGui::GetWindowDrawList(); auto drawList = ImGui::GetWindowDrawList();
@@ -931,6 +934,8 @@ namespace hex::plugin::builtin {
auto [foregroundColor, backgroundColor] = cellColors[x / bytesPerCell]; auto [foregroundColor, backgroundColor] = cellColors[x / bytesPerCell];
backgroundColor = applySelectionColor(byteAddress, backgroundColor);
// Draw highlights and selection // Draw highlights and selection
if (backgroundColor.has_value()) { if (backgroundColor.has_value()) {
auto drawList = ImGui::GetWindowDrawList(); auto drawList = ImGui::GetWindowDrawList();
@@ -989,6 +994,8 @@ namespace hex::plugin::builtin {
if (x < validBytes && isCurrRegionValid(address)) { if (x < validBytes && isCurrRegionValid(address)) {
auto [foregroundColor, backgroundColor] = cellColors[x / bytesPerCell]; auto [foregroundColor, backgroundColor] = cellColors[x / bytesPerCell];
backgroundColor = applySelectionColor(address, backgroundColor);
// Draw highlights and selection // Draw highlights and selection
if (backgroundColor.has_value()) { if (backgroundColor.has_value()) {
auto drawList = ImGui::GetWindowDrawList(); auto drawList = ImGui::GetWindowDrawList();
@@ -1017,21 +1024,20 @@ namespace hex::plugin::builtin {
// Scroll to the cursor if it's either at the top or bottom edge of the screen // Scroll to the cursor if it's either at the top or bottom edge of the screen
if (this->m_shouldScrollToSelection && this->isSelectionValid()) { if (this->m_shouldScrollToSelection && this->isSelectionValid()) {
// Make sure simply clicking on a byte at the edge of the screen won't cause scrolling // Make sure simply clicking on a byte at the edge of the screen won't cause scrolling
if ((ImGui::IsMouseDown(ImGuiMouseButton_Left) && providerData.selectionStart != providerData.selectionEnd && providerData.selectionEnd.has_value())) { if ((ImGui::IsMouseDown(ImGuiMouseButton_Left) && providerData.selectionStart != providerData.selectionEnd)) {
auto scrollPerLine = ImGui::GetScrollMaxY() / (provider->getSize() / (long double)(this->m_bytesPerRow)); auto fractionPerLine = 1.0 / (this->m_visibleRowCount + 1);
auto scrollPos = ImGui::GetScrollY(); if (y == (u64(clipper.DisplayStart) + 3)) {
auto scrollUpStartPos = scrollPos + scrollPerLine * 2; if (i128(*providerData.selectionEnd - provider->getBaseAddress() - provider->getCurrentPageAddress()) <= (i64(clipper.DisplayStart + 3) * this->m_bytesPerRow)) {
auto scrollDownStartPos = scrollPos + ImGui::GetWindowHeight() - scrollPerLine * 4; this->m_shouldScrollToSelection = false;
ImGui::SetScrollHereY(fractionPerLine * 5);
auto cursorPos = float(u64(*providerData.selectionEnd / this->m_bytesPerRow)) * CharacterSize.y; }
} else if (y == (u64(clipper.DisplayEnd) - 1)) {
if (cursorPos <= scrollUpStartPos && y == u64(clipper.DisplayStart)) { if (i128(*providerData.selectionEnd - provider->getBaseAddress() - provider->getCurrentPageAddress()) >= (i64(clipper.DisplayEnd - 2) * this->m_bytesPerRow)) {
this->m_shouldScrollToSelection = false; this->m_shouldScrollToSelection = false;
ImGui::SetScrollHereY(0.1F); ImGui::SetScrollHereY(fractionPerLine * (this->m_visibleRowCount));
} else if (cursorPos >= scrollDownStartPos && y == u64(clipper.DisplayEnd - 1)) { }
this->m_shouldScrollToSelection = false;
ImGui::SetScrollHereY(0.95F);
} }
} }
@@ -1044,9 +1050,9 @@ namespace hex::plugin::builtin {
newSelection.address -= pageAddress; newSelection.address -= pageAddress;
if ((newSelection.getStartAddress()) < u64(clipper.DisplayStart * this->m_bytesPerRow)) if ((newSelection.getStartAddress()) < u64(clipper.DisplayStart * this->m_bytesPerRow))
this->jumpToSelection(); this->jumpToSelection(false);
if ((newSelection.getEndAddress()) > u64(clipper.DisplayEnd * this->m_bytesPerRow)) if ((newSelection.getEndAddress()) > u64(clipper.DisplayEnd * this->m_bytesPerRow))
this->jumpToSelection(); this->jumpToSelection(false);
} }
} }
@@ -1061,7 +1067,16 @@ namespace hex::plugin::builtin {
provider->setCurrentPage(provider->getPageOfAddress(newSelection.address).value_or(0)); provider->setCurrentPage(provider->getPageOfAddress(newSelection.address).value_or(0));
const auto pageAddress = provider->getCurrentPageAddress() + provider->getBaseAddress(); const auto pageAddress = provider->getCurrentPageAddress() + provider->getBaseAddress();
ImGui::SetScrollFromPosY(ImGui::GetCursorStartPos().y + (static_cast<long double>(newSelection.getStartAddress() - pageAddress) / this->m_bytesPerRow) * CharacterSize.y, 0.5); auto scrollPos = (static_cast<long double>(newSelection.getStartAddress() - pageAddress) / this->m_bytesPerRow) * CharacterSize.y;
bool scrollUpwards = scrollPos < ImGui::GetScrollY();
auto scrollFraction = scrollUpwards ? 0.0F : (1.0F - ((1.0F / this->m_visibleRowCount) * 2));
if (this->m_centerOnJump) {
scrollFraction = 0.5F;
this->m_centerOnJump = false;
}
ImGui::SetScrollFromPosY(ImGui::GetCursorStartPos().y + scrollPos, scrollFraction);
} }
if (!this->m_syncScrolling) { if (!this->m_syncScrolling) {

View File

@@ -854,16 +854,18 @@ namespace hex::plugin::builtin {
return this->m_dangerousFunctionsAllowed == DangerousFunctionPerms::Allow; return this->m_dangerousFunctionsAllowed == DangerousFunctionPerms::Allow;
}); });
ON_SCOPE_EXIT {
this->m_lastEvaluationLog = runtime->getConsoleLog();
this->m_lastEvaluationOutVars = runtime->getOutVariables();
this->m_runningEvaluators--;
this->m_lastEvaluationProcessed = false;
};
this->m_lastEvaluationResult = runtime->executeString(code, envVars, inVariables); this->m_lastEvaluationResult = runtime->executeString(code, envVars, inVariables);
if (!this->m_lastEvaluationResult) { if (!this->m_lastEvaluationResult) {
this->m_lastEvaluationError = runtime->getError(); this->m_lastEvaluationError = runtime->getError();
} }
this->m_lastEvaluationLog = runtime->getConsoleLog();
this->m_lastEvaluationOutVars = runtime->getOutVariables();
this->m_runningEvaluators--;
this->m_lastEvaluationProcessed = false;
}); });
} }