Mercurial > vba-clojure
comparison src/win32/MemoryViewer.cpp @ 1:f9f4f1b99eed
importing src directory
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 03 Mar 2012 10:31:27 -0600 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
0:8ced16adf2e1 | 1:f9f4f1b99eed |
---|---|
1 // MemoryViewer.cpp : implementation file | |
2 // | |
3 | |
4 #include "stdafx.h" | |
5 #include "resource.h" | |
6 #include "MemoryViewer.h" | |
7 | |
8 extern int emulating; | |
9 | |
10 ///////////////////////////////////////////////////////////////////////////// | |
11 // MemoryViewer | |
12 | |
13 bool MemoryViewer::isRegistered = false; | |
14 | |
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 } | |
32 | |
33 MemoryViewer::~MemoryViewer() | |
34 {} | |
35 | |
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_MAP | |
47 ON_MESSAGE(WM_CHAR, OnWMChar) | |
48 END_MESSAGE_MAP() | |
49 | |
50 ///////////////////////////////////////////////////////////////////////////// | |
51 // MemoryViewer message handlers | |
52 | |
53 void MemoryViewer::setDialog(IMemoryViewerDlg *d) | |
54 { | |
55 dlg = d; | |
56 } | |
57 | |
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 else | |
72 { | |
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 } | |
84 | |
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 else | |
93 maxNibble = 7; | |
94 | |
95 InvalidateRect(NULL, TRUE); | |
96 } | |
97 | |
98 void MemoryViewer::setDecimal(bool decimalDisplayMode) | |
99 { | |
100 decimalDisplay = decimalDisplayMode; | |
101 InvalidateRect(NULL, TRUE); | |
102 } | |
103 | |
104 BOOL MemoryViewer::OnEraseBkgnd(CDC*pDC) | |
105 { | |
106 return TRUE; | |
107 } | |
108 | |
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 else | |
123 { | |
124 si.nMax = 0xa000000 / page; | |
125 si.nPage = page; | |
126 } | |
127 | |
128 si.nPos = address / page; | |
129 SetScrollInfo(SB_VERT, | |
130 &si, | |
131 TRUE); | |
132 } | |
133 | |
134 void MemoryViewer::OnPaint() | |
135 { | |
136 CPaintDC dc(this); // device context for painting | |
137 | |
138 RECT rect; | |
139 GetClientRect(&rect); | |
140 int w = rect.right - rect.left; | |
141 int h = rect.bottom - rect.top - 6; | |
142 | |
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); | |
148 | |
149 memDC.FillRect(&rect, CBrush::FromHandle((HBRUSH)GetStockObject(WHITE_BRUSH))); | |
150 memDC.DrawEdge(&rect, EDGE_ETCHED, BF_RECT); | |
151 | |
152 CFont *oldFont = memDC.SelectObject(CFont::FromHandle(font)); | |
153 | |
154 fontSize = memDC.GetTextExtent("0", 1); | |
155 | |
156 int lines = h / fontSize.cy; | |
157 | |
158 displayedLines = lines; | |
159 | |
160 updateScrollInfo(lines); | |
161 | |
162 u32 addr = address; | |
163 | |
164 memDC.SetTextColor(RGB(0, 0, 0)); | |
165 | |
166 u8 data[32]; | |
167 | |
168 RECT r; | |
169 r.top = 3; | |
170 r.left = 3; | |
171 r.bottom = r.top+fontSize.cy; | |
172 r.right = rect.right-3; | |
173 | |
174 int line = 0; | |
175 | |
176 for (int i = 0; i < lines; i++) | |
177 { | |
178 CString buffer; | |
179 if (addressSize) | |
180 buffer.Format("%04X", addr); | |
181 else | |
182 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); | |
187 | |
188 int j; | |
189 | |
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 else | |
198 { | |
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 else | |
205 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 else | |
219 { | |
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 else | |
226 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 else | |
239 { | |
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 else | |
244 buffer.Format(""); | |
245 } | |
246 memDC.DrawText(buffer, &r, DT_TOP | DT_LEFT | DT_NOPREFIX); | |
247 r.left += 9*fontSize.cx; | |
248 } | |
249 } | |
250 | |
251 line = r.left; | |
252 | |
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 else | |
264 buffer += '.'; | |
265 } | |
266 | |
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); | |
278 | |
279 memDC.MoveTo(3+fontSize.cx*9, 3); | |
280 memDC.LineTo(3+fontSize.cx*9, 3+displayedLines*fontSize.cy); | |
281 | |
282 memDC.MoveTo(line, 3); | |
283 memDC.LineTo(line, 3+displayedLines*fontSize.cy); | |
284 | |
285 memDC.SelectObject(old); | |
286 pen.DeleteObject(); | |
287 | |
288 memDC.SelectObject(oldFont); | |
289 | |
290 dc.BitBlt(0, 0, w, rect.bottom - rect.top, &memDC, 0, 0, SRCCOPY); | |
291 | |
292 memDC.SelectObject(pOldBitmap); | |
293 memDC.DeleteDC(); | |
294 bitmap.DeleteObject(); | |
295 } | |
296 | |
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 } | |
334 | |
335 UINT MemoryViewer::OnGetDlgCode() | |
336 { | |
337 return DLGC_WANTALLKEYS; | |
338 } | |
339 | |
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 } | |
350 | |
351 void MemoryViewer::destroyEditCaret() | |
352 { | |
353 hasCaret = false; | |
354 DestroyCaret(); | |
355 } | |
356 | |
357 void MemoryViewer::setCaretPos() | |
358 { | |
359 if (GetFocus() != this) | |
360 { | |
361 destroyEditCaret(); | |
362 return; | |
363 } | |
364 | |
365 if (dlg) | |
366 dlg->setCurrentAddress(editAddress); | |
367 | |
368 if (editAddress < address || editAddress > (address -1 + (displayedLines<<4))) | |
369 { | |
370 destroyEditCaret(); | |
371 return; | |
372 } | |
373 | |
374 int subAddress = (editAddress - address); | |
375 | |
376 int x = 3+10*fontSize.cx+editNibble*fontSize.cx; | |
377 int y = 3+fontSize.cy*((editAddress-address)>>4); | |
378 | |
379 if (editAscii) | |
380 { | |
381 x = beginAscii + fontSize.cx*(subAddress&15); | |
382 } | |
383 else | |
384 { | |
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 } | |
398 | |
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 } | |
414 | |
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 } | |
439 | |
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 else | |
451 { | |
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 else | |
467 { | |
468 return; | |
469 } | |
470 | |
471 if (editNibble > maxNibble) | |
472 editNibble = maxNibble; | |
473 SetFocus(); | |
474 setCaretPos(); | |
475 } | |
476 | |
477 void MemoryViewer::OnSetFocus(CWnd*pOldWnd) | |
478 { | |
479 setCaretPos(); | |
480 InvalidateRect(NULL, TRUE); | |
481 } | |
482 | |
483 void MemoryViewer::OnKillFocus(CWnd*pNewWnd) | |
484 { | |
485 destroyEditCaret(); | |
486 InvalidateRect(NULL, TRUE); | |
487 } | |
488 | |
489 void MemoryViewer::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) | |
490 { | |
491 bool isShift = (GetKeyState(VK_SHIFT) & 0x80000000) == 0x80000000; | |
492 | |
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 else | |
501 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 else | |
509 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 } | |
522 | |
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 else | |
545 { | |
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 else | |
563 { | |
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 else | |
582 setAddress(address+offset); | |
583 } | |
584 else if (editAddress > (address - 1 + (displayedLines<<4))) | |
585 { | |
586 if (offset & 15) | |
587 setAddress((address+offset+16) & ~15); | |
588 else | |
589 setAddress(address+offset); | |
590 } | |
591 } | |
592 | |
593 setCaretPos(); | |
594 } | |
595 | |
596 LRESULT MemoryViewer::OnWMChar(WPARAM wParam, LPARAM LPARAM) | |
597 { | |
598 if (OnEditInput(wParam)) | |
599 return 0; | |
600 return 1; | |
601 } | |
602 | |
603 bool MemoryViewer::OnEditInput(UINT c) | |
604 { | |
605 if (c > 255 || !emulating) | |
606 { | |
607 beep(); | |
608 return false; | |
609 } | |
610 | |
611 if (!editAscii) | |
612 c = tolower(c); | |
613 | |
614 u32 value = 256; | |
615 | |
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 else | |
627 { | |
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 } | |
650 | |
651 void MemoryViewer::beep() | |
652 { | |
653 MessageBeep((UINT)-1); | |
654 } | |
655 | |
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 } | |
673 | |
674 void MemoryViewer::setAddressSize(int s) | |
675 { | |
676 addressSize = s; | |
677 } | |
678 | |
679 u32 MemoryViewer::getCurrentAddress() | |
680 { | |
681 return editAddress; | |
682 } | |
683 | |
684 int MemoryViewer::getSize() | |
685 { | |
686 return dataSize; | |
687 } | |
688 |