Skip to content

Commit 4c1b342

Browse files
committed
Add copy/paste feature to memory view
Enhanced user experience by providing a way to copy and paste value directly in the memory view.
1 parent d3d5c91 commit 4c1b342

File tree

1 file changed

+48
-1
lines changed

1 file changed

+48
-1
lines changed

src/ui/win32/bindings/MemoryViewerControlBinding.cpp

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "ra_fwd.h"
44
#include "ra_utility.h"
55

6+
#include "services\IClipboard.hh"
67
#include "ui/EditorTheme.hh"
78
#include "ui/drawing/gdi/GDISurface.hh"
89

@@ -231,6 +232,50 @@ bool MemoryViewerControlBinding::HandleNavigation(UINT nChar)
231232
}
232233
return true;
233234

235+
case 'C':
236+
if (bControlHeld)
237+
{
238+
const auto& pEmulatorContext = ra::services::ServiceLocator::Get<ra::data::context::EmulatorContext>();
239+
const auto iValue = pEmulatorContext.ReadMemory(m_pViewModel.GetAddress(), m_pViewModel.GetSize());
240+
std::wstring sValue = ra::data::MemSizeFormat(iValue, m_pViewModel.GetSize(), MemFormat::Hex);
241+
ra::services::ServiceLocator::Get<ra::services::IClipboard>().SetText(ra::Widen(sValue));
242+
}
243+
return true;
244+
245+
case 'V':
246+
if (bControlHeld)
247+
{
248+
auto nAddress = m_pViewModel.GetAddress();
249+
const auto& pEmulatorContext = ra::services::ServiceLocator::Get<ra::data::context::EmulatorContext>();
250+
std::wstring sClipboardText = ra::services::ServiceLocator::Get<ra::services::IClipboard>().GetText();
251+
auto n = m_pViewModel.GetSize();
252+
if (sClipboardText.empty())
253+
return false;
254+
// Check if the string is a valid hexadecimal value
255+
for (wchar_t ch : sClipboardText)
256+
if (!iswxdigit(ch)) return false;
257+
// Padding zeroes depending if shift is pressed (strict mode) or not (replace mode)
258+
if (bShiftHeld)
259+
{
260+
const auto nNibblesForSize = ra::data::MemSizeBytes(m_pViewModel.GetSize()) * 2;
261+
if (nNibblesForSize < sClipboardText.length())
262+
sClipboardText = sClipboardText.substr(sClipboardText.length() - nNibblesForSize);
263+
else
264+
{
265+
std::wstring sPadding(nNibblesForSize - sClipboardText.length(), L'0');
266+
sClipboardText = (sPadding + sClipboardText);
267+
}
268+
}else
269+
sClipboardText = sClipboardText.length() % 2 == 1 ? (L"0" + sClipboardText) : sClipboardText;
270+
// Writing every byte separately considerably improves stability and enables long sequences to be pasted
271+
for (int i = sClipboardText.length(); i != 0; i-=2)
272+
{
273+
std::wstring sValue = sClipboardText.substr(i - 2, 2);
274+
pEmulatorContext.WriteMemoryByte(nAddress++, std::stoi(sValue, 0, 16));
275+
}
276+
}
277+
return true;
278+
234279
default:
235280
return false;
236281
}
@@ -308,7 +353,9 @@ void MemoryViewerControlBinding::RenderMemViewer()
308353

309354
const auto& pRenderImage = m_pViewModel.GetRenderImage();
310355
const auto& pEditorTheme = ra::services::ServiceLocator::Get<ra::ui::EditorTheme>();
311-
HBRUSH hBackground = CreateSolidBrush(RGB(pEditorTheme.ColorBackground().Channel.R, pEditorTheme.ColorBackground().Channel.G, pEditorTheme.ColorBackground().Channel.B));
356+
HBRUSH hBackground = CreateSolidBrush(RGB(pEditorTheme.ColorBackground().Channel.R,
357+
pEditorTheme.ColorBackground().Channel.G,
358+
pEditorTheme.ColorBackground().Channel.B));
312359

313360
// left margin
314361
RECT rcFill{ rcClient.left, rcClient.top, rcClient.left + MEMVIEW_MARGIN, rcClient.bottom - 1 };

0 commit comments

Comments
 (0)