@@ -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 ;
0 commit comments