Skip to content

Commit

Permalink
GetOffset interface method added.
Browse files Browse the repository at this point in the history
IHexVirtData new interface method added "void OnHexGetOffset(HEXDATAINFO& hdi, bool fGetVirt)".
This method is basically for custom offsets in Virtual mode. Virtual offsets are mostly used in processes memory model.
HEXDATA new member "ULONGLONG ullMaxVirtOffset" added, to set maximum Virtual offset for the data. This is needed for the offset digits amount calculation.
Code for internal dialogs has changed respectively (GoTo, Search, etc...).
std::accumulate replaced with std::reduce along the way all over the codebase.
  • Loading branch information
jovibor committed May 15, 2024
1 parent ae35e60 commit 869a78b
Show file tree
Hide file tree
Showing 12 changed files with 111 additions and 44 deletions.
9 changes: 6 additions & 3 deletions HexCtrl/HexCtrl.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ namespace HEXCTRL {
********************************************************************************************/
struct HEXDATAINFO {
NMHDR hdr { }; //Standard Windows header.
HEXSPAN stHexSpan; //Offset and size of the data bytes.
HEXSPAN stHexSpan; //Offset and size of the data.
SpanByte spnData; //Data span.
};

Expand All @@ -124,7 +124,8 @@ namespace HEXCTRL {
********************************************************************************************/
class IHexVirtData {
public:
virtual void OnHexGetData(HEXDATAINFO&) = 0; //Data to get.
virtual void OnHexGetData(HEXDATAINFO&) = 0; //Data to get.
virtual void OnHexGetOffset(HEXDATAINFO& hdi, bool fGetVirt) = 0; //Offset<->VirtOffset conversion.
virtual void OnHexSetData(const HEXDATAINFO&) = 0; //Data to set, if mutable.
};

Expand Down Expand Up @@ -243,7 +244,7 @@ namespace HEXCTRL {
********************************************************************************************/
class IHexTemplates {
public:
virtual auto AddTemplate(const HEXTEMPLATE& stTempl) -> int = 0; //Adds existing template.
virtual auto AddTemplate(const HEXTEMPLATE& hts) -> int = 0; //Adds existing template.
virtual auto ApplyTemplate(ULONGLONG ullOffset, int iTemplateID) -> int = 0; //Applies template to offset, returns AppliedID.
virtual void DisapplyAll() = 0;
virtual void DisapplyByID(int iAppliedID) = 0;
Expand Down Expand Up @@ -305,6 +306,7 @@ namespace HEXCTRL {
SpanByte spnData; //Data span to display.
IHexVirtData* pHexVirtData { }; //Pointer for VirtualData mode.
IHexVirtColors* pHexVirtColors { }; //Pointer for Custom Colors class.
ULONGLONG ullMaxVirtOffset { }; //Maximum virtual offset.
DWORD dwCacheSize { 0x800000UL }; //Data cache size for VirtualData mode.
bool fMutable { false }; //Is data mutable or read-only.
bool fHighLatency { false }; //Do not redraw until scroll thumb is released.
Expand Down Expand Up @@ -409,6 +411,7 @@ namespace HEXCTRL {
[[nodiscard]] virtual auto GetFont()const->LOGFONTW = 0; //Get current font.
[[nodiscard]] virtual auto GetGroupSize()const->DWORD = 0; //Retrieves current data grouping size.
[[nodiscard]] virtual auto GetMenuHandle()const->HMENU = 0; //Context menu handle.
[[nodiscard]] virtual auto GetOffset(ULONGLONG ullOffset, bool fGetVirt)const->ULONGLONG = 0; //Offset<->VirtOffset conversion.
[[nodiscard]] virtual auto GetPagesCount()const->ULONGLONG = 0; //Get count of pages.
[[nodiscard]] virtual auto GetPagePos()const->ULONGLONG = 0; //Get a page number that the cursor stays at.
[[nodiscard]] virtual auto GetPageSize()const->DWORD = 0; //Current page size.
Expand Down
6 changes: 3 additions & 3 deletions HexCtrl/res/HexCtrl.rc
Original file line number Diff line number Diff line change
Expand Up @@ -210,9 +210,9 @@ BEGIN
CONTROL "Hex numbers",IDC_HEXCTRL_TEMPLMGR_CHK_HEX,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,363,29,55,8
CONTROL "Swap endianness",IDC_HEXCTRL_TEMPLMGR_CHK_SWAP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,420,29,68,8
LTEXT "Template offset:",IDC_HEXCTRL_TEMPLMGR_STAT_OFFSETTXT,5,48,55,8
LTEXT "",IDC_HEXCTRL_TEMPLMGR_STAT_OFFSETNUM,62,48,54,8
LTEXT "Template size:",IDC_HEXCTRL_TEMPLMGR_STAT_SIZETXT,121,48,49,8
LTEXT "",IDC_HEXCTRL_TEMPLMGR_STAT_SIZENUM,172,48,45,8
LTEXT "",IDC_HEXCTRL_TEMPLMGR_STAT_OFFSETNUM,62,48,70,8
LTEXT "Template size:",IDC_HEXCTRL_TEMPLMGR_STAT_SIZETXT,138,48,49,8
LTEXT "",IDC_HEXCTRL_TEMPLMGR_STAT_SIZENUM,189,48,72,8
CONTROL "",IDC_HEXCTRL_TEMPLMGR_TREE_APPLIED,"SysTreeView32",TVS_HASBUTTONS | TVS_LINESATROOT | TVS_SHOWSELALWAYS | TVS_FULLROWSELECT | WS_BORDER | WS_HSCROLL | WS_TABSTOP,1,59,139,256
CONTROL "",IDC_HEXCTRL_TEMPLMGR_LIST_APPLIED,"SysListView32",LVS_REPORT | LVS_ALIGNLEFT | LVS_OWNERDATA | WS_BORDER | WS_TABSTOP,141,59,489,256
CONTROL "",IDC_HEXCTRL_TEMPLMGR_CHK_MIN,"Button",BS_AUTOCHECKBOX | BS_BITMAP | BS_PUSHLIKE | WS_TABSTOP,616,4,11,10
Expand Down
41 changes: 32 additions & 9 deletions HexCtrl/src/CHexCtrl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,7 @@ void CHexCtrl::ClearData()
m_pScrollV->SetScrollSizes(0, 0, 0);
m_pDlgBkmMgr->RemoveAll();
m_pSelection->ClearAll();
m_pDlgSearch->ClearData();
Redraw();
}

Expand Down Expand Up @@ -766,6 +767,22 @@ auto CHexCtrl::GetMenuHandle()const->HMENU
return m_menuMain.GetSubMenu(0)->GetSafeHmenu();
}

auto CHexCtrl::GetOffset(ULONGLONG ullOffset, bool fGetVirt)const->ULONGLONG
{
assert(IsCreated());
assert(IsDataSet());
if (!IsCreated() || !IsDataSet())
return { };

if (IsVirtual()) {
HEXDATAINFO hdi { .hdr { m_hWnd, static_cast<UINT>(GetDlgCtrlID()) }, .stHexSpan { .ullOffset { ullOffset } } };
m_pHexVirtData->OnHexGetOffset(hdi, fGetVirt);
return hdi.stHexSpan.ullOffset;
}

return ullOffset;
}

auto CHexCtrl::GetPagesCount()const->ULONGLONG
{
assert(IsCreated());
Expand Down Expand Up @@ -2303,7 +2320,7 @@ void CHexCtrl::Redraw()
return;

if (IsDataSet()) {
const auto ullCaretPos = GetCaretPos();
const auto ullCaretPos = GetVirtualOffset(GetCaretPos());
//^ - encloses Data name, ` (tilda) - encloses a data itself.
m_wstrInfoBar = std::vformat(GetLocale(), IsOffsetAsHex() ? L"^Caret: ^`0x{:X} `" : L"^Caret: ^`{:L} `",
std::make_wformat_args(ullCaretPos));
Expand All @@ -2316,8 +2333,8 @@ void CHexCtrl::Redraw()
}

if (HasSelection()) {
const auto ullSelStart = GetVirtualOffset(m_pSelection->GetSelStart());
const auto ullSelSize = m_pSelection->GetSelSize();
const auto ullSelStart = m_pSelection->GetSelStart();
if (ullSelSize == 1) { //In case of just one byte selected.
m_wstrInfoBar += std::vformat(GetLocale(), IsOffsetAsHex() ? L"^Selected: ^`0x{:X} [0x{:X}] `" :
L"^ Selected: ^`{} [{:L}] `", std::make_wformat_args(ullSelSize, ullSelStart));
Expand Down Expand Up @@ -2709,7 +2726,7 @@ void CHexCtrl::SetData(const HEXDATA& hds)
m_fMutable = hds.fMutable;
m_fHighLatency = hds.fHighLatency;

const auto ullDataSize = hds.spnData.size();
const auto ullDataSize = hds.pHexVirtData ? (std::max)(hds.ullMaxVirtOffset, hds.spnData.size()) : hds.spnData.size();
if (ullDataSize <= 0xffffffffUL) {
m_dwDigitsOffsetDec = 10;
m_dwDigitsOffsetHex = 8;
Expand Down Expand Up @@ -4547,14 +4564,14 @@ auto CHexCtrl::GetCommandFromMenu(WORD wMenuID)const->std::optional<EHexCmd>
return std::nullopt;
}

long CHexCtrl::GetFontSize()const
auto CHexCtrl::GetDigitsOffset()const->DWORD
{
return GetFont().lfHeight;
return IsOffsetAsHex() ? m_dwDigitsOffsetHex : m_dwDigitsOffsetDec;
}

auto CHexCtrl::GetDigitsOffset()const->DWORD
long CHexCtrl::GetFontSize()const
{
return IsOffsetAsHex() ? m_dwDigitsOffsetHex : m_dwDigitsOffsetDec;
return GetFont().lfHeight;
}

auto CHexCtrl::GetRectTextCaption()const->CRect
Expand All @@ -4574,6 +4591,11 @@ auto CHexCtrl::GetTopLine()const->ULONGLONG
return m_pScrollV->GetScrollPos() / m_sizeFontMain.cy;
}

auto CHexCtrl::GetVirtualOffset(ULONGLONG ullOffset)const->ULONGLONG
{
return GetOffset(ullOffset, true);
}

void CHexCtrl::HexChunkPoint(ULONGLONG ullOffset, int& iCx, int& iCy)const
{
//This func computes x and y pos of the given Hex chunk.
Expand Down Expand Up @@ -4667,7 +4689,7 @@ void CHexCtrl::ModifyWorker(const HEXCTRL::HEXMODIFY& hms, const auto& FuncWorke
return;

const auto& vecSpanRef = hms.vecSpan;
const auto ullTotalSize = std::accumulate(vecSpanRef.begin(), vecSpanRef.end(), 0ULL,
const auto ullTotalSize = std::reduce(vecSpanRef.begin(), vecSpanRef.end(), 0ULL,
[](ULONGLONG ullSumm, const HEXSPAN& ref) { return ullSumm + ref.ullSize; });
assert(ullTotalSize <= GetDataSize());

Expand Down Expand Up @@ -4797,6 +4819,7 @@ void CHexCtrl::ModifyWorker(const HEXCTRL::HEXMODIFY& hms, const auto& FuncWorke
auto CHexCtrl::OffsetToWstr(ULONGLONG ullOffset)const->std::wstring
{
const auto dwDigitsOffset = GetDigitsOffset();
ullOffset = GetVirtualOffset(ullOffset);
return std::vformat(IsOffsetAsHex() ? L"{:0>{}X}" : L"{:0>{}}", std::make_wformat_args(ullOffset, dwDigitsOffset));
}

Expand Down Expand Up @@ -5448,7 +5471,7 @@ void CHexCtrl::SetFontSize(long lSize)
void CHexCtrl::SnapshotUndo(const VecSpan& vecSpan)
{
constexpr auto dwUndoMax { 512U }; //Undo's max limit.
const auto ullTotalSize = std::accumulate(vecSpan.begin(), vecSpan.end(), 0ULL,
const auto ullTotalSize = std::reduce(vecSpan.begin(), vecSpan.end(), 0ULL,
[](ULONGLONG ullSumm, const HEXSPAN& ref) { return ullSumm + ref.ullSize; });

//Check for very big undo size.
Expand Down
4 changes: 3 additions & 1 deletion HexCtrl/src/CHexCtrl.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ namespace HEXCTRL::INTERNAL {
[[nodiscard]] auto GetFont()const->LOGFONTW override;
[[nodiscard]] auto GetGroupSize()const->DWORD override;
[[nodiscard]] auto GetMenuHandle()const->HMENU override;
[[nodiscard]] auto GetOffset(ULONGLONG ullOffset, bool fGetVirt)const->ULONGLONG override;
[[nodiscard]] auto GetPagesCount()const->ULONGLONG override;
[[nodiscard]] auto GetPagePos()const->ULONGLONG override;
[[nodiscard]] auto GetPageSize()const->DWORD override;
Expand Down Expand Up @@ -146,11 +147,12 @@ namespace HEXCTRL::INTERNAL {
[[nodiscard]] auto GetCharWidthNative()const->int; //Width of the one char, in px.
[[nodiscard]] auto GetCommandFromKey(UINT uKey, bool fCtrl, bool fShift, bool fAlt)const->std::optional<EHexCmd>; //Get command from keybinding.
[[nodiscard]] auto GetCommandFromMenu(WORD wMenuID)const->std::optional<EHexCmd>; //Get command from menuID.
[[nodiscard]] long GetFontSize()const;
[[nodiscard]] auto GetDigitsOffset()const->DWORD;
[[nodiscard]] long GetFontSize()const;
[[nodiscard]] auto GetRectTextCaption()const->CRect; //Returns rect of the text caption area.
[[nodiscard]] auto GetScrollPageSize()const->ULONGLONG; //Get the "Page" size of the scroll.
[[nodiscard]] auto GetTopLine()const->ULONGLONG; //Returns current top line number in view.
[[nodiscard]] auto GetVirtualOffset(ULONGLONG ullOffset)const->ULONGLONG;
void HexChunkPoint(ULONGLONG ullOffset, int& iCx, int& iCy)const; //Point of Hex chunk.
[[nodiscard]] auto HitTest(POINT pt)const->std::optional<HEXHITTEST>; //Is any hex chunk withing given point?
[[nodiscard]] bool IsCurTextArea()const; //Whether last focus was set at Text or Hex chunks area.
Expand Down
22 changes: 14 additions & 8 deletions HexCtrl/src/Dialogs/CHexDlgBkmMgr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -302,9 +302,9 @@ void CHexDlgBkmMgr::SortData(int iColumn, bool fAscending)
break;
case 2: //Size.
if (!st1.vecSpan.empty() && !st2.vecSpan.empty()) {
auto ullSize1 = std::accumulate(st1.vecSpan.begin(), st1.vecSpan.end(), 0ULL,
auto ullSize1 = std::reduce(st1.vecSpan.begin(), st1.vecSpan.end(), 0ULL,
[](auto ullTotal, const HEXSPAN& ref) { return ullTotal + ref.ullSize; });
auto ullSize2 = std::accumulate(st2.vecSpan.begin(), st2.vecSpan.end(), 0ULL,
auto ullSize2 = std::reduce(st2.vecSpan.begin(), st2.vecSpan.end(), 0ULL,
[](auto ullTotal, const HEXSPAN& ref) { return ullTotal + ref.ullSize; });
iCompare = ullSize1 != ullSize2 ? (ullSize1 < ullSize2 ? -1 : 1) : 0;
}
Expand Down Expand Up @@ -348,6 +348,11 @@ void CHexDlgBkmMgr::DoDataExchange(CDataExchange* pDX)
DDX_Control(pDX, IDC_HEXCTRL_BKMMGR_CHK_HEX, m_btnHex);
}

auto CHexDlgBkmMgr::GetHexCtrl()const->IHexCtrl*
{
return m_pHexCtrl;
}

bool CHexDlgBkmMgr::IsNoEsc()const
{
return m_u64Flags & HEXCTRL_FLAG_DLG_NOESC;
Expand Down Expand Up @@ -479,13 +484,13 @@ void CHexDlgBkmMgr::OnListGetDispInfo(NMHDR* pNMHDR, LRESULT* /*pResult*/)
break;
case 1: //Offset.
if (!pBkm->vecSpan.empty()) {
ullOffset = pBkm->vecSpan.front().ullOffset;
ullOffset = GetHexCtrl()->GetOffset(pBkm->vecSpan.front().ullOffset, true); //Display virtual offset.
}
*std::vformat_to(pItem->pszText, IsShowAsHex() ? L"0x{:X}" : L"{}", std::make_wformat_args(ullOffset)) = L'\0';
break;
case 2: //Size.
if (!pBkm->vecSpan.empty()) {
ullSize = std::accumulate(pBkm->vecSpan.begin(), pBkm->vecSpan.end(), 0ULL,
ullSize = std::reduce(pBkm->vecSpan.begin(), pBkm->vecSpan.end(), 0ULL,
[](auto ullTotal, const HEXSPAN& ref) { return ullTotal + ref.ullSize; });
}
*std::vformat_to(pItem->pszText, IsShowAsHex() ? L"0x{:X}" : L"{}", std::make_wformat_args(ullSize)) = L'\0';
Expand Down Expand Up @@ -600,12 +605,13 @@ void CHexDlgBkmMgr::OnListSetData(NMHDR* pNMHDR, LRESULT* /*pResult*/)
return;
}

const auto ullOffset = GetHexCtrl()->GetOffset(*optOffset, false); //Always use flat offset.
const auto ullOffsetCurr = pBkm->vecSpan.front().ullOffset;
if (ullOffsetCurr != *optOffset) {
const auto ullSizeCurr = std::accumulate(pBkm->vecSpan.begin(), pBkm->vecSpan.end(), 0ULL,
if (ullOffsetCurr != ullOffset) {
const auto ullSizeCurr = std::reduce(pBkm->vecSpan.begin(), pBkm->vecSpan.end(), 0ULL,
[](auto ullTotal, const HEXSPAN& ref) { return ullTotal + ref.ullSize; });
pBkm->vecSpan.clear();
pBkm->vecSpan.emplace_back(*optOffset, ullSizeCurr);
pBkm->vecSpan.emplace_back(ullOffset, ullSizeCurr);
}
}
break;
Expand All @@ -622,7 +628,7 @@ void CHexDlgBkmMgr::OnListSetData(NMHDR* pNMHDR, LRESULT* /*pResult*/)
return;
}

const auto ullSizeCurr = std::accumulate(pBkm->vecSpan.begin(), pBkm->vecSpan.end(), 0ULL,
const auto ullSizeCurr = std::reduce(pBkm->vecSpan.begin(), pBkm->vecSpan.end(), 0ULL,
[](auto ullTotal, const HEXSPAN& ref) { return ullTotal + ref.ullSize; });
if (ullSizeCurr != *optSize) {
const auto ullOffsetCurr = pBkm->vecSpan.front().ullOffset;
Expand Down
1 change: 1 addition & 0 deletions HexCtrl/src/Dialogs/CHexDlgBkmMgr.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ namespace HEXCTRL::INTERNAL {
private:
enum class EMenuID : std::uint16_t;
void DoDataExchange(CDataExchange* pDX)override;
[[nodiscard]] auto GetHexCtrl()const->IHexCtrl*;
[[nodiscard]] bool IsNoEsc()const;
[[nodiscard]] bool IsShowAsHex()const;
void OnCancel()override;
Expand Down
2 changes: 1 addition & 1 deletion HexCtrl/src/Dialogs/CHexDlgGoTo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ void CHexDlgGoTo::GoTo(bool fForward)
using enum EGoMode;
switch (GetGoMode()) {
case MODE_OFFSET:
ullOffsetResult = ullGoTo;
ullOffsetResult = pHexCtrl->GetOffset(ullGoTo, false); //Always use flat offset.
break;
case MODE_OFFSETFWD:
ullOffsetResult = ullOffsetCurr + ullGoTo * iFwdBack;
Expand Down
20 changes: 14 additions & 6 deletions HexCtrl/src/Dialogs/CHexDlgSearch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,14 @@ BEGIN_MESSAGE_MAP(CHexDlgSearch, CDialogEx)
ON_WM_DESTROY()
END_MESSAGE_MAP()

void CHexDlgSearch::ClearData()
{
if (!IsWindow(m_hWnd))
return;

ClearList();
}

auto CHexDlgSearch::GetDlgItemHandle(EHexDlgItem eItem)const->HWND
{
if (!IsWindow(m_hWnd)) {
Expand Down Expand Up @@ -1012,7 +1020,7 @@ void CHexDlgSearch::OnListGetDispInfo(NMHDR* pNMHDR, LRESULT* /*pResult*/)
*std::format_to(pItem->pszText, L"{}", nItemID + 1) = L'\0';
break;
case 1: //Offset.
*std::format_to(pItem->pszText, L"0x{:X}", m_vecSearchRes[nItemID]) = L'\0';
*std::format_to(pItem->pszText, L"0x{:X}", GetHexCtrl()->GetOffset(m_vecSearchRes[nItemID], true)) = L'\0';
break;
default:
break;
Expand Down Expand Up @@ -1042,7 +1050,7 @@ void CHexDlgSearch::OnListItemChanged(NMHDR* pNMHDR, LRESULT* /*pResult*/)
const auto ullOffset = m_vecSearchRes[static_cast<std::size_t>(pNMI->iItem)];
vecSpan.emplace_back(ullOffset, m_fReplace ? m_vecReplaceData.size() : m_vecSearchData.size());
HexCtrlHighlight(vecSpan);
SetEditStartFrom(ullOffset);
SetEditStartFrom(GetHexCtrl()->GetOffset(ullOffset, true)); //Show virtual offset.
m_ullStartFrom = ullOffset;
}

Expand Down Expand Up @@ -1253,7 +1261,7 @@ void CHexDlgSearch::Prepare()
return;
}

ullRngStart = *optRngStart;
ullRngStart = pHexCtrl->GetOffset(*optRngStart, false); //Always use flat offset.
}

//"Search range end offset".
Expand All @@ -1270,7 +1278,7 @@ void CHexDlgSearch::Prepare()
return;
}

ullRngEnd = *optRngEnd;
ullRngEnd = pHexCtrl->GetOffset(*optRngEnd, false); //Always use flat offset.
}

//"Start from".
Expand All @@ -1287,7 +1295,7 @@ void CHexDlgSearch::Prepare()
return;
}

ullStartFrom = *optStartFrom;
ullStartFrom = pHexCtrl->GetOffset(*optStartFrom, false); //Always use flat offset.
}
}
else {
Expand Down Expand Up @@ -1679,7 +1687,7 @@ void CHexDlgSearch::Search()
ullStartFrom += m_vecReplaceData.size() <= GetStep() ? GetStep() : m_vecReplaceData.size();
}

SetEditStartFrom(ullStartFrom);
SetEditStartFrom(GetHexCtrl()->GetOffset(ullStartFrom, true));
}
}
else {
Expand Down
1 change: 1 addition & 0 deletions HexCtrl/src/Dialogs/CHexDlgSearch.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import HEXCTRL.HexUtility;
namespace HEXCTRL::INTERNAL {
class CHexDlgSearch final : public CDialogEx {
public:
void ClearData();
[[nodiscard]] auto GetDlgItemHandle(EHexDlgItem eItem)const->HWND;
void Initialize(IHexCtrl* pHexCtrl);
[[nodiscard]] bool IsSearchAvail()const; //Can we do search next/prev?
Expand Down

0 comments on commit 869a78b

Please sign in to comment.