Skip to content

Commit 3983514

Browse files
committed
Refactor copy/paste feature following review
- New HandleShortcut function implemented to ViewModel - Improve code to match repository naming convention - Prevent from using paste feature in the pointer finder - Using of ParseHex instead of iswxdigit and refactoring logic based on this change
1 parent b81580b commit 3983514

File tree

3 files changed

+42
-23
lines changed

3 files changed

+42
-23
lines changed

src/ui/viewmodels/MemoryViewerViewModel.hh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,9 @@ public:
160160
/// </summary>
161161
void SetSize(MemSize value) { SetValue(SizeProperty, ra::etoi(value)); }
162162

163+
bool IsReadOnly() const noexcept { return m_bReadOnly; }
164+
void SetReadOnly(bool value) noexcept { m_bReadOnly = value; }
165+
163166
void OnClick(int nX, int nY);
164167
void OnResized(int nWidth, int nHeight);
165168
bool OnChar(char c);

src/ui/win32/bindings/MemoryViewerControlBinding.cpp

Lines changed: 37 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,8 @@ bool MemoryViewerControlBinding::OnKeyDown(UINT nChar)
140140

141141
if (!m_pViewModel.IsAddressFixed())
142142
bHandled = HandleNavigation(nChar);
143+
if (!bHandled)
144+
bHandled = HandleShortcut(nChar);
143145

144146
m_bSuppressMemoryViewerInvalidate = false;
145147

@@ -232,52 +234,64 @@ bool MemoryViewerControlBinding::HandleNavigation(UINT nChar)
232234
}
233235
return true;
234236

237+
default:
238+
return false;
239+
}
240+
}
241+
242+
bool MemoryViewerControlBinding::HandleShortcut(UINT nChar)
243+
{
244+
const bool bShiftHeld = (GetKeyState(VK_SHIFT) < 0);
245+
const bool bControlHeld = (GetKeyState(VK_CONTROL) < 0);
246+
247+
switch (nChar)
248+
{
235249
case 'C':
236250
if (bControlHeld)
237251
{
238252
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);
253+
const auto nValue = pEmulatorContext.ReadMemory(m_pViewModel.GetAddress(), m_pViewModel.GetSize());
254+
std::wstring sValue = ra::data::MemSizeFormat(nValue, m_pViewModel.GetSize(), MemFormat::Hex);
241255

242256
ra::services::ServiceLocator::Get<ra::services::IClipboard>().SetText(ra::Widen(sValue));
243257
}
244258
return true;
245259

246260
case 'V':
247-
if (bControlHeld)
261+
if (bControlHeld and !m_pViewModel.IsReadOnly())
248262
{
249263
auto nAddress = m_pViewModel.GetAddress();
250264
const auto& pEmulatorContext = ra::services::ServiceLocator::Get<ra::data::context::EmulatorContext>();
251265
std::wstring sClipboardText = ra::services::ServiceLocator::Get<ra::services::IClipboard>().GetText();
252-
auto n = m_pViewModel.GetSize();
266+
const auto nNibblesForSize = ra::data::MemSizeBytes(m_pViewModel.GetSize());
267+
std::vector<std::uint32_t> v_nValues;
268+
std::wstring sError;
253269

254270
if (sClipboardText.empty())
255271
return false;
256272

257-
// Check if the string is a valid hexadecimal value
258-
for (wchar_t ch : sClipboardText)
259-
if (!iswxdigit(ch)) return false;
260-
261-
// Padding zeroes depending if shift is pressed (strict mode) or not (replace mode)
262-
if (bShiftHeld)
273+
// Split the clipboard value into substrings matching the current size and check if they're valid hexadecimal values
274+
for (size_t i = 0; i < sClipboardText.size(); i += nNibblesForSize * 2)
263275
{
264-
const auto nNibblesForSize = ra::data::MemSizeBytes(m_pViewModel.GetSize()) * 2;
265-
266-
if (nNibblesForSize < sClipboardText.length())
267-
sClipboardText = sClipboardText.substr(sClipboardText.length() - nNibblesForSize);
268-
else
276+
std::wstring sSubString = sClipboardText.substr(i, nNibblesForSize * 2);
277+
unsigned int nValue;
278+
279+
if (!ra::ParseHex(sSubString, 0xFFFFFFFF, nValue, sError))
269280
{
270-
std::wstring sPadding(nNibblesForSize - sClipboardText.length(), L'0');
271-
sClipboardText = (sPadding + sClipboardText);
281+
ra::ui::viewmodels::MessageBoxViewModel::ShowWarningMessage(L"Paste value failed", sError);
282+
return false;
272283
}
273-
}else
274-
sClipboardText = sClipboardText.length() % 2 == 1 ? (L"0" + sClipboardText) : sClipboardText;
275284

276-
// Writing every byte separately considerably improves stability and enables long sequences to be pasted
277-
for (int i = sClipboardText.length(); i != 0; i-=2)
285+
v_nValues.push_back(nValue);
286+
}
287+
288+
for (auto nValue : v_nValues)
278289
{
279-
std::wstring sValue = sClipboardText.substr(i - 2, 2);
280-
pEmulatorContext.WriteMemoryByte(nAddress++, std::stoi(sValue, 0, 16));
290+
//Single mode writes only the first value, multi mode (shift) writes every values
291+
pEmulatorContext.WriteMemory(nAddress, m_pViewModel.GetSize(), nValue);
292+
if (!bShiftHeld)
293+
break;
294+
nAddress += nNibblesForSize;
281295
}
282296
}
283297
return true;

src/ui/win32/bindings/MemoryViewerControlBinding.hh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "ControlBinding.hh"
66

77
#include "ui/viewmodels/MemoryViewerViewModel.hh"
8+
#include "ui\viewmodels\MessageBoxViewModel.hh"
89

910
namespace ra {
1011
namespace ui {
@@ -63,6 +64,7 @@ protected:
6364

6465
private:
6566
bool HandleNavigation(UINT nChar);
67+
bool HandleShortcut(UINT nChar);
6668
bool m_bSuppressMemoryViewerInvalidate = false;
6769

6870
ra::ui::viewmodels::MemoryViewerViewModel& m_pViewModel;

0 commit comments

Comments
 (0)