Mercurial > vba-clojure
view src/win32/MemoryViewer.cpp @ 7:c0a590a394c3
ignore generated files
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 03 Mar 2012 10:50:33 -0600 |
parents | f9f4f1b99eed |
children |
line wrap: on
line source
1 // MemoryViewer.cpp : implementation file2 //4 #include "stdafx.h"5 #include "resource.h"6 #include "MemoryViewer.h"8 extern int emulating;10 /////////////////////////////////////////////////////////////////////////////11 // MemoryViewer13 bool MemoryViewer::isRegistered = false;15 MemoryViewer::MemoryViewer()16 {17 address = 0;18 addressSize = 0;19 dataSize = 0;20 editAddress = 0;21 editNibble = 0;22 displayedLines = 0;23 hasCaret = false;24 maxNibble = 0;25 font = (HFONT)GetStockObject(SYSTEM_FIXED_FONT);26 fontSize.cx = fontSize.cy = 0;27 beginAscii = 0;28 beginHex = 0;29 dlg = NULL;30 registerClass();31 }33 MemoryViewer::~MemoryViewer()34 {}36 BEGIN_MESSAGE_MAP(MemoryViewer, CWnd)37 //{{AFX_MSG_MAP(MemoryViewer)38 ON_WM_ERASEBKGND()39 ON_WM_PAINT()40 ON_WM_VSCROLL()41 ON_WM_GETDLGCODE()42 ON_WM_LBUTTONDOWN()43 ON_WM_SETFOCUS()44 ON_WM_KILLFOCUS()45 ON_WM_KEYDOWN()46 //}}AFX_MSG_MAP47 ON_MESSAGE(WM_CHAR, OnWMChar)48 END_MESSAGE_MAP()50 /////////////////////////////////////////////////////////////////////////////51 // MemoryViewer message handlers53 void MemoryViewer::setDialog(IMemoryViewerDlg *d)54 {55 dlg = d;56 }58 void MemoryViewer::setAddress(u32 a)59 {60 address = a;61 if (displayedLines)62 {63 if (addressSize)64 {65 u16 addr = address;66 if ((u16)((addr+(displayedLines<<4)) & 0xFFFF) < addr)67 {68 address = 0xffff - (displayedLines<<4) + 1;69 }70 }71 else72 {73 if ((address+(displayedLines<<4)) < address)74 {75 address = 0xffffffff - (displayedLines<<4) + 1;76 }77 }78 }79 if (addressSize)80 address &= 0xffff;81 setCaretPos();82 InvalidateRect(NULL, TRUE);83 }85 void MemoryViewer::setSize(int s)86 {87 dataSize = s;88 if (s == 0)89 maxNibble = 1;90 else if (s == 1)91 maxNibble = 3;92 else93 maxNibble = 7;95 InvalidateRect(NULL, TRUE);96 }98 void MemoryViewer::setDecimal(bool decimalDisplayMode)99 {100 decimalDisplay = decimalDisplayMode;101 InvalidateRect(NULL, TRUE);102 }104 BOOL MemoryViewer::OnEraseBkgnd(CDC*pDC)105 {106 return TRUE;107 }109 void MemoryViewer::updateScrollInfo(int lines)110 {111 int page = lines * 16;112 SCROLLINFO si;113 ZeroMemory(&si, sizeof(si));114 si.cbSize = sizeof(si);115 si.fMask = SIF_PAGE | SIF_RANGE | SIF_DISABLENOSCROLL | SIF_POS;116 si.nMin = 0;117 if (addressSize)118 {119 si.nMax = 0x10000/page;120 si.nPage = 1;121 }122 else123 {124 si.nMax = 0xa000000 / page;125 si.nPage = page;126 }128 si.nPos = address / page;129 SetScrollInfo(SB_VERT,130 &si,131 TRUE);132 }134 void MemoryViewer::OnPaint()135 {136 CPaintDC dc(this); // device context for painting138 RECT rect;139 GetClientRect(&rect);140 int w = rect.right - rect.left;141 int h = rect.bottom - rect.top - 6;143 CDC memDC;144 memDC.CreateCompatibleDC(&dc);145 CBitmap bitmap, *pOldBitmap;146 bitmap.CreateCompatibleBitmap(&dc, w, rect.bottom - rect.top);147 pOldBitmap = memDC.SelectObject(&bitmap);149 memDC.FillRect(&rect, CBrush::FromHandle((HBRUSH)GetStockObject(WHITE_BRUSH)));150 memDC.DrawEdge(&rect, EDGE_ETCHED, BF_RECT);152 CFont *oldFont = memDC.SelectObject(CFont::FromHandle(font));154 fontSize = memDC.GetTextExtent("0", 1);156 int lines = h / fontSize.cy;158 displayedLines = lines;160 updateScrollInfo(lines);162 u32 addr = address;164 memDC.SetTextColor(RGB(0, 0, 0));166 u8 data[32];168 RECT r;169 r.top = 3;170 r.left = 3;171 r.bottom = r.top+fontSize.cy;172 r.right = rect.right-3;174 int line = 0;176 for (int i = 0; i < lines; i++)177 {178 CString buffer;179 if (addressSize)180 buffer.Format("%04X", addr);181 else182 buffer.Format("%08X", addr);183 memDC.DrawText(buffer, &r, DT_TOP | DT_LEFT | DT_NOPREFIX);184 r.left += 10*fontSize.cx;185 beginHex = r.left;186 readData(addr, 16, data);188 int j;190 if (dataSize == 0)191 {192 for (j = 0; j < 16; j++)193 {194 const int nextRLeft = r.left + 3*fontSize.cx;195 if (!decimalDisplay)196 buffer.Format("%02X", data[j]);197 else198 {199 const signed char num = data[j];200 if (num < -9 || num > 99)201 r.left -= fontSize.cx;202 if (num >= -99 && num <= 99)203 buffer.Format("%2d", num);204 else205 buffer.Format("");206 }207 memDC.DrawText(buffer, &r, DT_TOP | DT_LEFT | DT_NOPREFIX);208 r.left = nextRLeft;209 }210 }211 if (dataSize == 1)212 {213 for (j = 0; j < 16; j += 2)214 {215 const int nextRLeft = r.left + 5*fontSize.cx;216 if (!decimalDisplay)217 buffer.Format("%04X", data[j] | data[j+1]<<8);218 else219 {220 const signed short num = data[j] | data[j+1]<<8;221 if (num < -999 || num > 9999)222 r.left -= fontSize.cx;223 if (num >= -9999 && num <= 9999)224 buffer.Format("%4d", num);225 else226 buffer.Format("");227 }228 memDC.DrawText(buffer, &r, DT_TOP | DT_LEFT | DT_NOPREFIX);229 r.left = nextRLeft;230 }231 }232 if (dataSize == 2)233 {234 for (j = 0; j < 16; j += 4)235 {236 if (!decimalDisplay)237 buffer.Format("%08X", data[j] | data[j+1]<<8 | data[j+2] << 16 | data[j+3] << 24);238 else239 {240 const signed long num = data[j] | data[j+1]<<8 | data[j+2] << 16 | data[j+3] << 24;241 if (num >= -9999999 && num <= 99999999)242 buffer.Format("%8d", num);243 else244 buffer.Format("");245 }246 memDC.DrawText(buffer, &r, DT_TOP | DT_LEFT | DT_NOPREFIX);247 r.left += 9*fontSize.cx;248 }249 }251 line = r.left;253 r.left += fontSize.cx;254 beginAscii = r.left;255 buffer.Empty();256 for (j = 0; j < 16; j++)257 {258 char c = data[j];259 if (c >= 32 && c <= 127)260 {261 buffer += c;262 }263 else264 buffer += '.';265 }267 memDC.DrawText(buffer, &r, DT_TOP | DT_LEFT | DT_NOPREFIX);268 addr += 16;269 if (addressSize)270 addr &= 0xffff;271 r.top += fontSize.cy;272 r.bottom += fontSize.cy;273 r.left = 3;274 }275 CPen pen;276 pen.CreatePen(PS_SOLID, 1, RGB(0, 0, 0));277 CPen *old = memDC.SelectObject(&pen);279 memDC.MoveTo(3+fontSize.cx*9, 3);280 memDC.LineTo(3+fontSize.cx*9, 3+displayedLines*fontSize.cy);282 memDC.MoveTo(line, 3);283 memDC.LineTo(line, 3+displayedLines*fontSize.cy);285 memDC.SelectObject(old);286 pen.DeleteObject();288 memDC.SelectObject(oldFont);290 dc.BitBlt(0, 0, w, rect.bottom - rect.top, &memDC, 0, 0, SRCCOPY);292 memDC.SelectObject(pOldBitmap);293 memDC.DeleteDC();294 bitmap.DeleteObject();295 }297 void MemoryViewer::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar*pScrollBar)298 {299 int address = this->address;300 switch (nSBCode)301 {302 case SB_BOTTOM:303 address = 0xffffff00;304 break;305 case SB_LINEDOWN:306 address += 0x10;307 break;308 case SB_LINEUP:309 address -= 0x10;310 break;311 case SB_PAGEDOWN:312 address += (displayedLines<<4);313 break;314 case SB_PAGEUP:315 address -= (displayedLines<<4);316 break;317 case SB_TOP:318 address = 0;319 break;320 case SB_THUMBTRACK:321 {322 int page = displayedLines * 16;323 SCROLLINFO si;324 ZeroMemory(&si, sizeof(si));325 si.cbSize = sizeof(si);326 si.fMask = SIF_TRACKPOS;327 GetScrollInfo(SB_VERT, &si);328 address = page * si.nTrackPos;329 break;330 }331 }332 setAddress(address);333 }335 UINT MemoryViewer::OnGetDlgCode()336 {337 return DLGC_WANTALLKEYS;338 }340 void MemoryViewer::createEditCaret(int w, int h)341 {342 if (!hasCaret || caretWidth != w || caretHeight != h)343 {344 hasCaret = true;345 caretWidth = w;346 caretHeight = h;347 ::CreateCaret(m_hWnd, (HBITMAP)0, w, h);348 }349 }351 void MemoryViewer::destroyEditCaret()352 {353 hasCaret = false;354 DestroyCaret();355 }357 void MemoryViewer::setCaretPos()358 {359 if (GetFocus() != this)360 {361 destroyEditCaret();362 return;363 }365 if (dlg)366 dlg->setCurrentAddress(editAddress);368 if (editAddress < address || editAddress > (address -1 + (displayedLines<<4)))369 {370 destroyEditCaret();371 return;372 }374 int subAddress = (editAddress - address);376 int x = 3+10*fontSize.cx+editNibble*fontSize.cx;377 int y = 3+fontSize.cy*((editAddress-address)>>4);379 if (editAscii)380 {381 x = beginAscii + fontSize.cx*(subAddress&15);382 }383 else384 {385 switch (dataSize)386 {387 case 0:388 x += 3*fontSize.cx*(subAddress & 15);389 break;390 case 1:391 x += 5*fontSize.cx*((subAddress>>1) & 7);392 break;393 case 2:394 x += 9*fontSize.cx*((subAddress>>2) & 3);395 break;396 }397 }399 RECT r;400 GetClientRect(&r);401 r.right -= 3;402 if (x >= r.right)403 {404 destroyEditCaret();405 return;406 }407 int w = fontSize.cx;408 if ((x+fontSize.cx) >= r.right)409 w = r.right - x;410 createEditCaret(w, fontSize.cy);411 ::SetCaretPos(x, y);412 ShowCaret();413 }415 void MemoryViewer::OnLButtonDown(UINT nFlags, CPoint point)416 {417 int x = point.x;418 int y = point.y;419 int line = (y-3)/fontSize.cy;420 int beforeAscii = beginHex;421 int inc = 1;422 int sub = 3*fontSize.cx;423 switch (dataSize)424 {425 case 0:426 beforeAscii += 47*fontSize.cx;427 break;428 case 1:429 beforeAscii += 39*fontSize.cx;430 inc = 2;431 sub = 5*fontSize.cx;432 break;433 case 2:434 beforeAscii += 35*fontSize.cx;435 inc = 4;436 sub = 9*fontSize.cx;437 break;438 }440 editAddress = address + (line<<4);441 if (x >= beginHex && x < beforeAscii)442 {443 x -= beginHex;444 editNibble = 0;445 while (x > 0)446 {447 x -= sub;448 if (x >= 0)449 editAddress += inc;450 else451 {452 editNibble = (x + sub)/fontSize.cx;453 }454 }455 editAscii = false;456 }457 else if (x >= beginAscii)458 {459 int afterAscii = beginAscii+16*fontSize.cx;460 if (x >= afterAscii)461 x = afterAscii-1;462 editAddress += (x-beginAscii)/fontSize.cx;463 editNibble = 0;464 editAscii = true;465 }466 else467 {468 return;469 }471 if (editNibble > maxNibble)472 editNibble = maxNibble;473 SetFocus();474 setCaretPos();475 }477 void MemoryViewer::OnSetFocus(CWnd*pOldWnd)478 {479 setCaretPos();480 InvalidateRect(NULL, TRUE);481 }483 void MemoryViewer::OnKillFocus(CWnd*pNewWnd)484 {485 destroyEditCaret();486 InvalidateRect(NULL, TRUE);487 }489 void MemoryViewer::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)490 {491 bool isShift = (GetKeyState(VK_SHIFT) & 0x80000000) == 0x80000000;493 switch (nChar)494 {495 case VK_RIGHT:496 if (editAscii)497 moveAddress(1, 0);498 else if (isShift)499 moveAddress((maxNibble+1)>>1, 0);500 else501 moveAddress(0, 1);502 break;503 case VK_LEFT:504 if (editAscii)505 moveAddress(-1, 0);506 else if (isShift)507 moveAddress(-((maxNibble+1)>>1), 0);508 else509 moveAddress(0, -1);510 break;511 case VK_DOWN:512 moveAddress(16, 0);513 break;514 case VK_UP:515 moveAddress(-16, 0);516 break;517 case VK_TAB:518 GetNextDlgTabItem(GetParent(), isShift)->SetFocus();519 break;520 }521 }523 void MemoryViewer::moveAddress(s32 offset, int nibbleOff)524 {525 if (offset == 0)526 {527 if (nibbleOff == -1)528 {529 editNibble--;530 if (editNibble == -1)531 {532 editAddress -= (maxNibble + 1) >> 1;533 editNibble = maxNibble;534 }535 if (address == 0 && (editAddress >= (u32)(displayedLines<<4)))536 {537 editAddress = 0;538 editNibble = 0;539 beep();540 }541 if (editAddress < address)542 setAddress(address - 16);543 }544 else545 {546 editNibble++;547 if (editNibble > maxNibble)548 {549 editNibble = 0;550 editAddress += (maxNibble + 1) >> 1;551 }552 if (editAddress < address)553 {554 editAddress -= (maxNibble + 1) >> 1;555 editNibble = maxNibble;556 beep();557 }558 if (editAddress >= (address+(displayedLines<<4)))559 setAddress(address+16);560 }561 }562 else563 {564 editAddress += offset;565 if (offset < 0 && editAddress > (address-1+(displayedLines<<4)))566 {567 editAddress -= offset;568 beep();569 return;570 }571 if (offset > 0 && (editAddress < address))572 {573 editAddress -= offset;574 beep();575 return;576 }577 if (editAddress < address)578 {579 if (offset & 15)580 setAddress((address+offset-16) & ~15);581 else582 setAddress(address+offset);583 }584 else if (editAddress > (address - 1 + (displayedLines<<4)))585 {586 if (offset & 15)587 setAddress((address+offset+16) & ~15);588 else589 setAddress(address+offset);590 }591 }593 setCaretPos();594 }596 LRESULT MemoryViewer::OnWMChar(WPARAM wParam, LPARAM LPARAM)597 {598 if (OnEditInput(wParam))599 return 0;600 return 1;601 }603 bool MemoryViewer::OnEditInput(UINT c)604 {605 if (c > 255 || !emulating)606 {607 beep();608 return false;609 }611 if (!editAscii)612 c = tolower(c);614 u32 value = 256;616 if (c >= 'a' && c <= 'f')617 value = 10 + (c - 'a');618 else if (c >= '0' && c <= '9')619 value = (c - '0');620 if (editAscii)621 {622 editData(editAddress, 8, 0, c);623 moveAddress(1, 0);624 InvalidateRect(NULL, TRUE);625 }626 else627 {628 if (value != 256)629 {630 value <<= 4*(maxNibble-editNibble);631 u32 mask = ~(15 << 4*(maxNibble - editNibble));632 switch (dataSize)633 {634 case 0:635 editData(editAddress, 8, mask, value);636 break;637 case 1:638 editData(editAddress, 16, mask, value);639 break;640 case 2:641 editData(editAddress, 32, mask, value);642 break;643 }644 moveAddress(0, 1);645 InvalidateRect(NULL, TRUE);646 }647 }648 return true;649 }651 void MemoryViewer::beep()652 {653 MessageBeep((UINT)-1);654 }656 void MemoryViewer::registerClass()657 {658 if (!isRegistered)659 {660 WNDCLASS wc;661 ZeroMemory(&wc, sizeof(wc));662 wc.style = CS_PARENTDC | CS_HREDRAW | CS_VREDRAW | CS_GLOBALCLASS;663 wc.lpfnWndProc = (WNDPROC) ::DefWindowProc;664 wc.hInstance = AfxGetInstanceHandle();665 wc.hCursor = LoadCursor(NULL, IDC_ARROW);666 wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);667 wc.lpszMenuName = NULL;668 wc.lpszClassName = "VbaMemoryViewer";669 AfxRegisterClass(&wc);670 isRegistered = true;671 }672 }674 void MemoryViewer::setAddressSize(int s)675 {676 addressSize = s;677 }679 u32 MemoryViewer::getCurrentAddress()680 {681 return editAddress;682 }684 int MemoryViewer::getSize()685 {686 return dataSize;687 }