1
0
mirror of synced 2025-02-22 04:49:44 +01:00

impr: Allow a entire 64 bit address space to be displayed in the hex editor

This commit is contained in:
WerWolv 2023-12-22 16:58:50 +01:00
parent 0da6c03a8f
commit b934ca6ad3
3 changed files with 117 additions and 98 deletions

View File

@ -33,7 +33,7 @@ namespace hex::prv {
std::function<void()> callback; std::function<void()> callback;
}; };
constexpr static size_t MaxPageSize = 0x1000'0000; constexpr static u64 MaxPageSize = 0xFFFF'FFFF'FFFF'FFFF;
Provider(); Provider();
virtual ~Provider(); virtual ~Provider();

View File

@ -230,7 +230,7 @@ namespace hex::plugin::builtin::ui {
std::optional<u64> m_selectionStart; std::optional<u64> m_selectionStart;
std::optional<u64> m_selectionEnd; std::optional<u64> m_selectionEnd;
std::optional<u64> m_cursorPosition; std::optional<u64> m_cursorPosition;
float m_scrollPosition = 0; i64 m_scrollPosition = 0;
u16 m_bytesPerRow = 16; u16 m_bytesPerRow = 16;
std::endian m_dataVisualizerEndianness = std::endian::little; std::endian m_dataVisualizerEndianness = std::endian::little;

View File

@ -315,8 +315,40 @@ namespace hex::plugin::builtin::ui {
ImGuiExt::TextFormattedCentered("{}", "hex.builtin.hex_editor.no_bytes"_lang); ImGuiExt::TextFormattedCentered("{}", "hex.builtin.hex_editor.no_bytes"_lang);
} }
if (ImGui::BeginChild("Hex View", size, ImGuiChildFlags_None, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse)) {
// Draw scrollbar
{
const auto window = ImGui::GetCurrentWindowRead();
const auto axis = ImGuiAxis_Y;
i64 numRows = (m_provider->getSize() / m_bytesPerRow) + ((m_provider->getSize() % m_bytesPerRow) == 0 ? 0 : 1);
const auto outerRect = window->Rect();
const auto innerRect = window->InnerRect;
const auto borderSize = window->WindowBorderSize;
const auto scrollbarWidth = ImGui::GetStyle().ScrollbarSize;
const ImRect bb = ImRect(ImMax(outerRect.Min.x, outerRect.Max.x - borderSize - scrollbarWidth), innerRect.Min.y, outerRect.Max.x, innerRect.Max.y);
const ImDrawFlags roundingCorners = ImDrawFlags_RoundCornersTopRight | ImDrawFlags_RoundCornersBottomRight;
ImGui::ScrollbarEx(
bb,
ImGui::GetWindowScrollbarID(window, axis),
axis,
&m_scrollPosition,
(std::ceil(innerRect.Max.y - innerRect.Min.y) / CharacterSize.y) - (m_visibleRowCount - 1),
std::nextafterf(numRows, std::numeric_limits<float>::max()),
roundingCorners);
if (ImGui::IsWindowHovered()) {
m_scrollPosition += i64(ImGui::GetIO().MouseWheel * -5);
}
if (m_scrollPosition < 0)
m_scrollPosition = 0;
if (m_scrollPosition > (numRows - 1))
m_scrollPosition = numRows - 1;
}
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, ImVec2(0.5, 0)); ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, ImVec2(0.5, 0));
if (ImGui::BeginTable("##hex", byteColumnCount, ImGuiTableFlags_ScrollY | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_NoKeepColumnsVisible, size)) { if (ImGui::BeginTable("##hex", byteColumnCount, ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_NoKeepColumnsVisible, size)) {
View::discardNavigationRequests(); View::discardNavigationRequests();
ImGui::TableSetupScrollFreeze(0, 2); ImGui::TableSetupScrollFreeze(0, 2);
@ -371,21 +403,17 @@ namespace hex::plugin::builtin::ui {
return currRegionValid; return currRegionValid;
}; };
ImGuiListClipper clipper; i64 numRows = (m_provider->getSize() / m_bytesPerRow) + ((m_provider->getSize() % m_bytesPerRow) == 0 ? 0 : 1);
u64 numRows = std::ceil(m_provider->getSize() / static_cast<long double>(m_bytesPerRow));
if (numRows == 0) { if (numRows == 0) {
ImGui::TableNextRow(); ImGui::TableNextRow();
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGuiExt::TextFormatted(" "); ImGuiExt::TextFormatted(" ");
} }
clipper.Begin(numRows + size.y / CharacterSize.y - 3, CharacterSize.y); m_visibleRowCount = ImGui::GetWindowSize().y / CharacterSize.y;
while (clipper.Step()) {
m_visibleRowCount = clipper.DisplayEnd - clipper.DisplayStart;
// Loop over rows // Loop over rows
for (u64 y = u64(clipper.DisplayStart); y < std::min(numRows, u64(clipper.DisplayEnd)); y++) { for (i64 y = m_scrollPosition; y < (m_scrollPosition + m_visibleRowCount + 5) && y < numRows; y++) {
// Draw address column // Draw address column
ImGui::TableNextRow(); ImGui::TableNextRow();
ImGui::TableNextColumn(); ImGui::TableNextColumn();
@ -459,7 +487,7 @@ namespace hex::plugin::builtin::ui {
cellSize.x += SeparatorColumWidth + 1; cellSize.x += SeparatorColumWidth + 1;
} }
if (y == u64(clipper.DisplayStart)) if (y == m_scrollPosition)
cellSize.y -= (ImGui::GetStyle().CellPadding.y); cellSize.y -= (ImGui::GetStyle().CellPadding.y);
backgroundColor = applySelectionColor(byteAddress, backgroundColor); backgroundColor = applySelectionColor(byteAddress, backgroundColor);
@ -555,7 +583,7 @@ namespace hex::plugin::builtin::ui {
m_encodingLineStartAddresses.push_back(0); m_encodingLineStartAddresses.push_back(0);
} }
if (y < m_encodingLineStartAddresses.size()) { if (size_t(y) < m_encodingLineStartAddresses.size()) {
std::vector<std::pair<u64, CustomEncodingData>> encodingData; std::vector<std::pair<u64, CustomEncodingData>> encodingData;
if (m_encodingLineStartAddresses[y] >= m_bytesPerRow) { if (m_encodingLineStartAddresses[y] >= m_bytesPerRow) {
@ -619,17 +647,15 @@ namespace hex::plugin::builtin::ui {
if (m_shouldScrollToSelection && isSelectionValid()) { if (m_shouldScrollToSelection && 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::IsMouseDragging(ImGuiMouseButton_Left) && *m_selectionStart != *m_selectionEnd)) { if ((ImGui::IsMouseDragging(ImGuiMouseButton_Left) && *m_selectionStart != *m_selectionEnd)) {
auto fractionPerLine = 1.0 / (m_visibleRowCount + 1); if (y == (m_scrollPosition + 3)) {
if (i128(m_selectionEnd.value() - m_provider->getBaseAddress() - m_provider->getCurrentPageAddress()) <= (i64(m_scrollPosition + 3) * m_bytesPerRow)) {
if (y == (u64(clipper.DisplayStart) + 3)) {
if (i128(m_selectionEnd.value() - m_provider->getBaseAddress() - m_provider->getCurrentPageAddress()) <= (i64(clipper.DisplayStart + 3) * m_bytesPerRow)) {
m_shouldScrollToSelection = false; m_shouldScrollToSelection = false;
ImGui::SetScrollHereY(fractionPerLine * 5); m_scrollPosition -= 3;
} }
} else if (y == (u64(clipper.DisplayEnd) - 1)) { } else if (y == ((m_scrollPosition + m_visibleRowCount) - 1)) {
if (i128(m_selectionEnd.value() - m_provider->getBaseAddress() - m_provider->getCurrentPageAddress()) >= (i64(clipper.DisplayEnd - 2) * m_bytesPerRow)) { if (i128(m_selectionEnd.value() - m_provider->getBaseAddress() - m_provider->getCurrentPageAddress()) >= (i64((m_scrollPosition + m_visibleRowCount) - 2) * m_bytesPerRow)) {
m_shouldScrollToSelection = false; m_shouldScrollToSelection = false;
ImGui::SetScrollHereY(fractionPerLine * (m_visibleRowCount)); m_scrollPosition += 3;
} }
} }
} }
@ -642,14 +668,13 @@ namespace hex::plugin::builtin::ui {
auto newSelection = getSelection(); auto newSelection = getSelection();
newSelection.address -= pageAddress; newSelection.address -= pageAddress;
if ((newSelection.getStartAddress()) < u64(clipper.DisplayStart * m_bytesPerRow)) if ((newSelection.getStartAddress()) < u64(m_scrollPosition * m_bytesPerRow))
this->jumpToSelection(false); this->jumpToSelection(false);
if ((newSelection.getEndAddress()) > u64(clipper.DisplayEnd * m_bytesPerRow)) if ((newSelection.getEndAddress()) > u64((m_scrollPosition + m_visibleRowCount) * m_bytesPerRow))
this->jumpToSelection(false); this->jumpToSelection(false);
} }
} }
} }
}
// Handle jumping to selection // Handle jumping to selection
if (m_shouldJumpToSelection) { if (m_shouldJumpToSelection) {
@ -659,31 +684,25 @@ namespace hex::plugin::builtin::ui {
m_provider->setCurrentPage(m_provider->getPageOfAddress(newSelection.address).value_or(0)); m_provider->setCurrentPage(m_provider->getPageOfAddress(newSelection.address).value_or(0));
const auto pageAddress = m_provider->getCurrentPageAddress() + m_provider->getBaseAddress(); const auto pageAddress = m_provider->getCurrentPageAddress() + m_provider->getBaseAddress();
auto scrollPos = (static_cast<long double>(newSelection.getStartAddress() - pageAddress) / m_bytesPerRow) * CharacterSize.y;
bool scrollUpwards = scrollPos < ImGui::GetScrollY();
auto scrollFraction = scrollUpwards ? 0.0F : (1.0F - ((1.0F / m_visibleRowCount) * 2));
if (m_centerOnJump) { if (m_centerOnJump) {
scrollFraction = 0.5F; m_scrollPosition = (newSelection.getStartAddress() - pageAddress) / m_bytesPerRow;
m_centerOnJump = false; m_scrollPosition -= (m_visibleRowCount / 2);
}
ImGui::SetScrollFromPosY(ImGui::GetCursorStartPos().y + scrollPos, scrollFraction);
}
if (!m_syncScrolling) {
if (m_shouldUpdateScrollPosition) {
m_shouldUpdateScrollPosition = false;
ImGui::SetScrollY(m_scrollPosition);
} else { } else {
m_scrollPosition = ImGui::GetScrollY(); m_scrollPosition = (newSelection.getStartAddress() - pageAddress) / m_bytesPerRow;
} }
m_centerOnJump = false;
} }
} }
ImGui::EndTable(); ImGui::EndTable();
}
ImGui::PopStyleVar(); ImGui::PopStyleVar();
}
ImGui::EndChild();
}
m_shouldScrollToSelection = false; m_shouldScrollToSelection = false;
} }