|
|
1.1 root 1: //
2: // nono
1.1.1.4 root 3: // Copyright (C) 2020 nono project
4: // Licensed under nono-license.txt
1.1 root 5: //
6:
1.1.1.11 root 7: //
8: // メモリダンプウィンドウ
9: //
10:
1.1 root 11: #include "wxdumpmonitor.h"
1.1.1.13 root 12: #include "mainapp.h"
13: #include "mainbus.h"
1.1.1.15 root 14: #include "monitor.h"
15: #include "mpu680x0.h"
1.1 root 16:
17: enum {
1.1.1.11 root 18: ID_TEXT = IDGROUP_MEMDUMP,
1.1.1.13 root 19: ID_PREVLINE,
20: ID_PREVPAGE,
21: ID_NEXTLINE,
22: ID_NEXTPAGE,
23: ID_FORMAT,
24:
25: ID_EDIT,
1.1.1.11 root 26:
27: ID_local_end, // 最後に置く (チェック用)
1.1 root 28: };
1.1.1.12 root 29: static_assert(ID_local_end - 1 <= (int)IDGROUP_MEMDUMP_END, "ID exceeded");
1.1 root 30:
31: // イベントテーブル
32: wxBEGIN_EVENT_TABLE(WXMemdumpWindow, inherited)
33: EVT_TEXT_ENTER(ID_TEXT, WXMemdumpWindow::OnTextEnter)
1.1.1.13 root 34: EVT_COMMAND(ID_PREVLINE, NONO_EVT_BUTTON, WXMemdumpWindow::OnPrevLine)
35: EVT_COMMAND(ID_PREVPAGE, NONO_EVT_BUTTON, WXMemdumpWindow::OnPrevPage)
36: EVT_COMMAND(ID_NEXTLINE, NONO_EVT_BUTTON, WXMemdumpWindow::OnNextLine)
37: EVT_COMMAND(ID_NEXTPAGE, NONO_EVT_BUTTON, WXMemdumpWindow::OnNextPage)
38: EVT_CHOICE(ID_FORMAT, WXMemdumpWindow::OnFormat)
1.1 root 39: wxEND_EVENT_TABLE()
40:
41: // コンストラクタ
1.1.1.9 root 42: // (タイトルは UpdateAddr() でセットする)
1.1.1.13 root 43: WXMemdumpWindow::WXMemdumpWindow(wxWindow *parent, int monid_)
1.1.1.12 root 44: : inherited(parent, wxID_ANY, wxEmptyString,
45: DEFAULT_STYLE | wxRESIZE_BORDER)
1.1 root 46: {
1.1.1.13 root 47: monid = monid_;
48: if (IS_MONITOR_XPMEMDUMP(monid)) {
49: myidx = monid - ID_MONITOR_XPMEMDUMP0;
50: } else {
51: myidx = monid - ID_MONITOR_MEMDUMP0;
52: }
53:
54: // ↓ topsizer
55: // +--------------------------------------------+
56: // |上枠 → |
57: // |+-----+------+-----+----------+-----+------+|
58: // ||余白 | "<<" | "<" | アドレス | ">" | ">>" ||
59: // |+-----+------+-----+----------+-----+------+|
60: // +--------------------------------------------+
61: // | TextScreen |
62: // +--------------------------------------------+
1.1.1.11 root 63:
64: auto *topsizer = new wxBoxSizer(wxVERTICAL);
1.1.1.5 root 65:
1.1.1.9 root 66: // 上枠用の下敷きパネル
1.1.1.13 root 67: auto *ctrlpanel = new wxPanel(this);
1.1.1.15 root 68: ctrlpanel->SetName("WXMemdumpWindow.CtrlPanel");
1.1.1.11 root 69: topsizer->Add(ctrlpanel, 0, wxEXPAND);
1.1.1.9 root 70:
1.1.1.5 root 71: // 上枠用の横 sizer
72: ctrlbox = new wxBoxSizer(wxHORIZONTAL);
1.1 root 73:
74: // アドレスコントロール
1.1.1.13 root 75: addrctrl = new wxTextCtrl(ctrlpanel, ID_TEXT,
1.1 root 76: wxEmptyString, wxDefaultPosition, wxDefaultSize,
77: wxTE_PROCESS_ENTER);
1.1.1.13 root 78: buttons[0] = new WXButton(ctrlpanel, ID_PREVPAGE, wxDefaultSize, "<<");
79: buttons[1] = new WXButton(ctrlpanel, ID_PREVLINE, wxDefaultSize, "<");
80: buttons[2] = new WXButton(ctrlpanel, ID_NEXTLINE, wxDefaultSize, ">");
81: buttons[3] = new WXButton(ctrlpanel, ID_NEXTPAGE, wxDefaultSize, ">>");
82:
83: ctrlbox->AddSpacer(3);
84: ctrlbox->Add(buttons[0], 0, wxALIGN_CENTER);
85: ctrlbox->Add(buttons[1], 0, wxALIGN_CENTER);
86: ctrlbox->AddSpacer(3);
87: ctrlbox->Add(addrctrl, 0, wxALIGN_CENTER);
88: ctrlbox->AddSpacer(3);
89: ctrlbox->Add(buttons[2], 0, wxALIGN_CENTER);
90: ctrlbox->Add(buttons[3], 0, wxALIGN_CENTER);
91: ctrlbox->AddSpacer(3);
92:
93: // 表示形式 (機種によって選択肢と名前が異なる)
94: if (gMainApp.Has(VMCap::M68K)) {
1.1.1.15 root 95: auto mpu680x0 = GetMPU680x0Device(GetMPUDevice());
1.1.1.13 root 96: fmts.emplace_back(Memdump::Byte, _("Byte"));
97: fmts.emplace_back(Memdump::Word, _("Word"));
98: fmts.emplace_back(Memdump::Long, _("Long Word"));
1.1.1.15 root 99: switch (mpu680x0->GetMPUType()) {
100: case m680x0MPUType::M68030:
101: fmts.emplace_back(Memdump::M68030PageShort,
102: _("MMU Descriptor (Short Format)"));
103: break;
104: case m680x0MPUType::M68040:
105: fmts.emplace_back(Memdump::M68040TableDesc,
106: _("MMU Table Descriptor"));
107: fmts.emplace_back(Memdump::M68040PageDesc,
108: _("MMU Page Descriptor"));
109: break;
110: default:
111: break;
112: }
113: fmts.emplace_back(Memdump::M680x0Disasm, _("680x0 Disassemble"));
1.1.1.13 root 114: } else {
115: fmts.emplace_back(Memdump::Byte, _("Byte"));
116: fmts.emplace_back(Memdump::Word, _("Half Word"));
117: fmts.emplace_back(Memdump::Long, _("Word"));
118: fmts.emplace_back(Memdump::M88200Page, _("88200 Descriptor"));
119: fmts.emplace_back(Memdump::M88100Disasm, _("88100 Disassemble"));
120: }
121: if (gMainApp.Has(VMCap::LUNA)) {
122: fmts.emplace_back(Memdump::HD64180Disasm, _("HD64180 Disassemble"));
123: }
124:
125: // fmts から名前だけの配列を作る
126: std::vector<wxString> fmt_choice;
127: for (auto p : fmts) {
128: fmt_choice.push_back(p.second);
129: }
130: fmtctrl = new wxChoice(ctrlpanel, ID_FORMAT,
131: wxDefaultPosition, wxDefaultSize,
132: fmt_choice.size(), &fmt_choice[0]);
133: ctrlbox->Add(fmtctrl, 0, wxALIGN_CENTER);
1.1 root 134:
1.1.1.9 root 135: // 上枠の sizer と下敷きを紐付ける
136: ctrlpanel->SetSizer(ctrlbox);
137: ctrlbox->SetSizeHints(ctrlpanel);
138:
1.1.1.13 root 139: screen = new WXMonitorPanel(this, gMonitorManager->Get(monid));
1.1.1.11 root 140: topsizer->Add(screen, 1, wxEXPAND);
1.1 root 141:
1.1.1.4 root 142: SetSizer(topsizer);
1.1 root 143:
1.1.1.11 root 144: // ウィンドウサイズを確定させる
1.1.1.13 root 145: FontChanged();
1.1.1.11 root 146:
1.1.1.13 root 147: // パネルに来るマウスイベントをこっちに回す
148: screen->Connect(wxEVT_MOUSEWHEEL,
149: wxMouseEventHandler(WXMemdumpWindow::OnMouseWheel), NULL, this);
150: screen->Connect(wxEVT_LEFT_DCLICK,
151: wxMouseEventHandler(WXMemdumpWindow::OnDClick), NULL, this);
152:
153: // メモリダンプオブジェクトを取得
154: auto mon = screen->GetMonitor();
1.1.1.15 root 155: memdump = dynamic_cast<MemdumpMonitor *>(mon->obj);
1.1.1.13 root 156: assert(memdump);
157:
158: // 初期値をコントロールに設定
159: auto fmt = memdump->GetFormat();
160: fmtctrl->SetSelection(Format2Selection(fmt));
161: DoFormat(fmt);
1.1.1.9 root 162: UpdateAddr();
1.1 root 163: }
164:
165: // デストラクタ
166: WXMemdumpWindow::~WXMemdumpWindow()
167: {
168: }
169:
1.1.1.13 root 170: void
171: WXMemdumpWindow::FontChanged()
172: {
173: for (auto *btn : buttons) {
1.1.1.16! root 174: // ボタンサイズを先に一旦リセット。
! 175: btn->SetMinSize(wxSize(1, 1));
! 176: btn->SetSize(wxSize(1, 1));
! 177:
! 178: // 各ボタンコントロールに伝搬。
1.1.1.13 root 179: btn->FontChanged();
1.1.1.16! root 180:
! 181: // ボタンを正方形に固定する (テキストは1文字か2文字と知っている)。
! 182: // 押しやすくするため、最小 24x24 にしてみる。
! 183: wxSize size = btn->GetSize();
! 184: if (size.y < 24) {
! 185: size.y = 24;
! 186: }
! 187: size.x = size.y;
! 188:
! 189: // 勝手にベストサイズに戻らないように最小サイズごと固定する。
! 190: btn->SetSize(size);
! 191: btn->SetMinSize(size);
1.1.1.13 root 192: }
1.1.1.16! root 193:
! 194: screen->FontChanged();
! 195:
! 196: Fit();
! 197: }
! 198:
! 199: void
! 200: WXMemdumpWindow::Fit()
! 201: {
! 202: // inherited::Fit() は呼ばずに自力で行う。
! 203:
! 204: wxSize newsize = DoSizeHints();
! 205: SetClientSize(newsize);
! 206: }
! 207:
! 208: bool
! 209: WXMemdumpWindow::Layout()
! 210: {
! 211: // wxmonitor.cpp の WXScrollMonitorWindow::Layout() のコメント参照。
! 212: wxSize client = GetClientSize();
! 213: const wxSize win = GetSize();
! 214: const wxSize margin = win - client;
! 215: const wxSize ctrlsize = ctrlbox->GetSize();
! 216: const wxSize monsize = screen->GetSize();
! 217:
! 218: if (oldmargin != margin) {
! 219: layout_pass2 = true;
! 220: oldmargin = margin;
! 221: CallAfter([this]() {
! 222: DoSizeHints();
! 223: });
! 224: return true;
! 225: } else if (layout_pass2) {
! 226: layout_pass2 = false;
! 227: client.y = ctrlsize.y + monsize.y;
! 228: SetClientSize(client);
! 229: Hide();
! 230: Show();
! 231: return true;
! 232: }
! 233:
! 234: // Sizer 使ってるのでその処理は任せる。
! 235: return inherited::Layout();
! 236: }
! 237:
! 238: // クライアントサイズと最大/最小サイズを計算する。
! 239: // SetSizeHints() を実行し、設定すべきクライアントサイズを返す。
! 240: wxSize
! 241: WXMemdumpWindow::DoSizeHints()
! 242: {
! 243: // この後の Fit() でリサイズに使われる大きさを取得。
! 244: wxSize fitsize = GetSizer()->ComputeFittingClientSize(this);
! 245: wxSize ctrlsize = ctrlbox->ComputeFittingClientSize(this);
! 246:
! 247: // 高さの最小は (コントロールパネル分と) TextScreen 1行分にしておく。
! 248: int min_y = ctrlsize.y + screen->GetScreenHeight(1);
! 249: int new_y = ctrlsize.y + screen->GetSize().y;
! 250: wxSize minsize(fitsize.x, min_y);
! 251: wxSize maxsize(fitsize.x, GetMaxClientSize().y);
! 252: wxSize incsize(0, screen->GetFontHeight());
! 253: SetSizeHints(ClientToWindowSize(minsize), ClientToWindowSize(maxsize),
! 254: incsize);
! 255:
! 256: return wxSize(fitsize.x, new_y);
1.1.1.13 root 257: }
258:
1.1 root 259: // テキスト入力イベント
260: void
261: WXMemdumpWindow::OnTextEnter(wxCommandEvent& event)
262: {
263: // 入力文字列(16進文字列)を数値に変換
1.1.1.5 root 264: const wxString& wstr = event.GetString();
1.1.1.6 root 265: uint32 val = strtoul((const char *)wstr.mb_str(), NULL, 16);
1.1 root 266:
1.1.1.9 root 267: // アドレスを更新
1.1.1.13 root 268: memdump->SetAddr(val);
1.1.1.9 root 269: UpdateAddr();
1.1 root 270: }
271:
1.1.1.13 root 272: // "<"(前行) ボタン押下イベント
1.1 root 273: void
1.1.1.13 root 274: WXMemdumpWindow::OnPrevLine(wxCommandEvent& event)
1.1 root 275: {
1.1.1.13 root 276: // 1行戻る
277: memdump->Offset(memdump->GetLineOffset(-1));
1.1.1.9 root 278:
1.1.1.13 root 279: UpdateAddr();
280: }
281:
282: // "<<"(前ページ) ボタン押下イベント
283: void
284: WXMemdumpWindow::OnPrevPage(wxCommandEvent& event)
285: {
286: // 1ページ戻る
287: memdump->Offset(memdump->GetPageOffset(-1));
1.1.1.9 root 288:
289: UpdateAddr();
1.1 root 290: }
291:
1.1.1.13 root 292: // ">"(次行) ボタン押下イベント
1.1 root 293: void
1.1.1.13 root 294: WXMemdumpWindow::OnNextLine(wxCommandEvent& event)
1.1 root 295: {
1.1.1.13 root 296: // 1行進む
297: memdump->Offset(memdump->GetLineOffset(1));
298:
299: UpdateAddr();
300: }
1.1.1.9 root 301:
1.1.1.13 root 302: // ">>"(次ページ) ボタン押下イベント
303: void
304: WXMemdumpWindow::OnNextPage(wxCommandEvent& event)
305: {
306: // 1ページ進む
307: memdump->Offset(memdump->GetPageOffset(1));
1.1.1.9 root 308:
309: UpdateAddr();
1.1 root 310: }
311:
1.1.1.9 root 312: // アドレス欄の表示を更新する
313: void
314: WXMemdumpWindow::UpdateAddr()
315: {
1.1.1.13 root 316: int width;
317: std::string title;
318: if (IS_MONITOR_XPMEMDUMP(monid)) {
319: width = 5;
320: title = _("XP Memory Dump");
321: } else {
322: width = 8;
323: title = _("Main Memory Dump");
324: }
1.1.1.9 root 325:
1.1.1.14 root 326: uint32 addr = memdump->GetAddr().Addr();
1.1.1.13 root 327: std::string addrstr = strhex(addr, width);
1.1.1.9 root 328:
329: // EVT_TEXT を起こさず変更する
1.1.1.13 root 330: addrctrl->ChangeValue(addrstr);
1.1.1.9 root 331:
332: // カーソルを末尾に
333: addrctrl->SetInsertionPointEnd();
334:
335: // タイトルを変更
1.1.1.13 root 336: title += string_format(" %d: $", myidx);
337: title += addrstr;
338: SetTitle(title);
339:
340: // 即更新
341: Refresh();
1.1.1.9 root 342: }
343:
1.1.1.13 root 344: // 表示フォーマット変更イベント
345: void
346: WXMemdumpWindow::OnFormat(wxCommandEvent& event)
1.1.1.9 root 347: {
1.1.1.13 root 348: int idx = event.GetSelection();
349: DoFormat(Selection2Format(idx));
1.1 root 350: }
1.1.1.9 root 351:
1.1.1.13 root 352: // 表示フォーマット変更処理
1.1.1.9 root 353: void
1.1.1.13 root 354: WXMemdumpWindow::DoFormat(Memdump::Format fmt)
1.1.1.9 root 355: {
1.1.1.13 root 356: memdump->SetFormat(fmt);
357:
358: // SetFormat() によってアドレスが切り捨てられる場合があるので
359: // アドレス欄の表示ごと更新。
360: UpdateAddr();
361: }
362:
363: // マウスホイールイベント
364: void
365: WXMemdumpWindow::OnMouseWheel(wxMouseEvent& event)
366: {
367: int delta = event.GetWheelRotation();
368:
369: // 1回の変化で +/-120 が来る。
370: // たいていのアプリケーションで3行ずつの移動に換算することが多いようだが
371: // ここはメモリダンプなので 4行ずつにする。
372:
373: if (delta != 0) {
374: memdump->Offset(memdump->GetLineOffset(-delta / 30));
375: UpdateAddr();
376: }
377: }
378:
379: // ダブルクリックイベント
380: void
381: WXMemdumpWindow::OnDClick(wxMouseEvent& event)
382: {
383: event.Skip();
384:
385: auto fmt = memdump->GetFormat();
386:
387: // テキストの桁数、行数にする
388: wxPoint tpos = screen->GetTextPosition(event.GetPosition());
389: int x = tpos.x;
390: int y = tpos.y;
391:
392: // ウィンドウサイズを変えた時に出来る下の空き地にはヒットさせない
393: if (y >= screen->GetRow()) {
394: return;
395: }
396:
397: // アドレス部分は常に除外でいいか
398: if (x < 19) {
399: return;
400: }
401:
402: // 現在のフォーマットでのクリック位置のアドレスを求める
403: int len = 0;
404: uint64 addr = -1;
405: switch (fmt) {
406: case Memdump::Byte:
407: len = 1;
408: addr = GetAddrAtHexdump(x, y, len);
409: break;
410: case Memdump::Word:
411: len = 2;
412: addr = GetAddrAtHexdump(x, y, len);
413: break;
414: case Memdump::Long:
415: len = 4;
416: addr = GetAddrAtHexdump(x, y, len);
417: break;
418: case Memdump::M68030PageShort:
419: case Memdump::M88200Page:
420: len = 4;
421: addr = GetAddrAtPageShort(x, y);
422: break;
423:
424: case Memdump::M68030PageLong:
425: PANIC("not supported");
426: break;
427:
1.1.1.15 root 428: case Memdump::M680x0Disasm:
1.1.1.13 root 429: len = 2;
430: addr = GetAddrAtDisasm(x, y, len);
431: break;
432:
433: case Memdump::M88100Disasm:
434: len = 4;
435: addr = GetAddrAtDisasm(x, y, len);
436: break;
437:
438: case Memdump::HD64180Disasm:
439: len = 1;
440: addr = GetAddrAtDisasm(x, y, len);
441: break;
442:
443: default:
444: break;
445: }
446: if ((int64)addr < 0) {
447: return;
448: }
449: addr &= ~(len - 1);
450:
451: // このアドレスが編集可能 (≒メモリ) か?
452: if (memdump->CanPoke(addr) == false) {
453: ::wxMessageBox(_("Can not edit here"), _("Memory Edit"),
454: wxICON_EXCLAMATION | wxOK | wxOK_DEFAULT, this);
455: return;
456: }
457:
458: // 出来ればここをハイライトとかしたい
459:
460: // 現在値を(再)取得。
461: uint32 val = memdump->Peek(addr, len);
462:
463: // sizestr は表示形式ではなく単なるサイズ。(DescShort なら Long)
464: std::string sizestr;
465: switch (len) {
466: case 1:
467: sizestr = Format2String(Memdump::Byte);
468: break;
469: case 2:
470: sizestr = Format2String(Memdump::Word);
471: break;
472: case 4:
473: sizestr = Format2String(Memdump::Long);
474: break;
475: default:
476: PANIC("corrupted len=%d", len);
477: }
478:
479: // 編集
480: auto dlg = new MemEditDialog(this, addr, val, len, sizestr);
481: if (dlg->ShowModal() == wxID_OK) {
482: uint32 data = dlg->GetData();
483:
484: // 更新
1.1.1.14 root 485: if (memdump->Poke(addr, data, len) == false) {
1.1.1.13 root 486: ::wxMessageBox(_("Could not edit"), _("Memory Edit"),
487: wxICON_EXCLAMATION | wxOK | wxOK_DEFAULT, this);
488: }
489: }
490: }
491:
492: // 16進ダンプ画面のテキスト座標 (x, y) に対応するアドレスを返す。
493: // 対応するアドレスがない場合は (uint64)-1 を返す。
494: uint64
495: WXMemdumpWindow::GetAddrAtHexdump(int x, int y, int len)
496: {
497: if (x < 68) {
498: // 16進ダンプ部分
499:
500: // 空白部分なら除外
501: x -= 19;
502: if (x % (len * 2 + 1) == len * 2) {
503: return (uint64)-1;
504: }
505: x = (x / (len * 2 + 1)) * len;
506: } else {
507: // 文字ダンプ部分
508: x -= 68;
509: }
510:
511: if (x > 15) {
512: return (uint64)-1;
513: }
514:
1.1.1.14 root 515: return memdump->GetAddr().Addr() + (y * memdump->GetStride()) + x;
1.1.1.9 root 516: }
517:
1.1.1.13 root 518: // 32bit ページテーブル画面のテキスト座標 (x, y) に対応するアドレスを返す。
519: // 対応するアドレスがない場合は (uint64)-1 を返す。
520: uint64
521: WXMemdumpWindow::GetAddrAtPageShort(int x, int y)
522: {
523: // 32bit ページテーブルなら1行で1ロングワード。
524: // 16進の場合との親和性のため、ダンプ値のところだけ反応。
525: if (x >= 19 + 8) {
526: return (uint64)-1;
527: }
1.1.1.14 root 528: return memdump->GetAddr().Addr() + y * 4;
1.1.1.13 root 529: }
530:
531: // 逆アセンブル画面のテキスト座標 (x, y) に対応するアドレスを返す。
532: // minlen は命令の最小バイト数。
533: // 対応するアドレスがない場合は (uint64)-1 を返す。
534: uint64
535: WXMemdumpWindow::GetAddrAtDisasm(int x, int y, int minlen)
536: {
537: // 先頭から y 行目のアドレス
538: uint32 yaddr = memdump->GetLineOffset(y);
539:
540: // y 行目の命令のバイト数
541: uint32 y1addr = memdump->GetLineOffset(y + 1);
542: uint32 bytes = y1addr - yaddr;
543:
544: // 空白部分なら除外
545: x -= 19;
546:
547: if (x % (minlen * 2 + 1) == minlen * 2) {
548: return (uint64)-1;
549: }
550: x = (x / (minlen * 2 + 1)) * minlen;
551:
552: if (x >= bytes) {
553: return (uint64)-1;
554: }
555:
1.1.1.14 root 556: return memdump->GetAddr().Addr() + yaddr + x;
1.1.1.13 root 557: }
558:
559: // セレクション番号からフォーマット番号への変換
560: Memdump::Format
561: WXMemdumpWindow::Selection2Format(int idx)
562: {
563: assert(idx < fmts.size());
564: return fmts[idx].first;
565: }
566:
567: // フォーマット番号からセレクション番号への変換
568: int
569: WXMemdumpWindow::Format2Selection(Memdump::Format fmt_)
570: {
571: for (int idx = 0, end = fmts.size(); idx < end; idx++) {
572: auto p = fmts[idx];
573: if (fmt_ == p.first) {
574: return idx;
575: }
576: }
577: // ?
578: return 0;
579: }
580:
581: // フォーマット番号から文字列への変換
582: wxString
583: WXMemdumpWindow::Format2String(Memdump::Format fmt_)
584: {
585: for (int idx = 0, end = fmts.size(); idx < end; idx++) {
586: auto p = fmts[idx];
587: if (fmt_ == p.first) {
588: return p.second;
589: }
590: }
591: // ?
592: return wxEmptyString;
593: }
594:
595:
596: //
597: // 編集ダイアログ
598: //
599:
600: wxBEGIN_EVENT_TABLE(MemEditDialog, inherited)
601: EVT_TEXT_ENTER(ID_EDIT, MemEditDialog::OnTextEnter)
602: wxEND_EVENT_TABLE()
603:
604: // コンストラクタ
605: MemEditDialog::MemEditDialog(wxWindow *parent, uint32 addr, uint32 oldval,
606: int len, const std::string& sizestr)
607: : inherited(parent, wxID_ANY, _("Edit memory"))
608: {
609: auto topsizer = new wxBoxSizer(wxVERTICAL);
610:
611: auto gridsizer = new wxFlexGridSizer(2);
612: topsizer->Add(gridsizer, 0, wxEXPAND | wxALL, 3);
613:
614: gridsizer->Add(new wxStaticText(this, wxID_ANY, _("Address:")),
615: 0, wxEXPAND);
616:
617: std::string addrstr = "$";
618: addrstr += strhex(addr);
619: auto addrctrl = new wxStaticText(this, wxID_ANY, addrstr,
620: wxDefaultPosition, wxDefaultSize, wxBORDER_SUNKEN);
621: gridsizer->Add(addrctrl, 0, wxEXPAND);
622:
623: gridsizer->Add(new wxStaticText(this, wxID_ANY, _("Size:")),
624: 0, wxEXPAND);
625: gridsizer->Add(new wxStaticText(this, wxID_ANY, sizestr),
626: 0, wxEXPAND);
627:
628: gridsizer->Add(new wxStaticText(this, wxID_ANY, _("Data:")),
629: 0, wxEXPAND);
630:
631: std::string oldstr = strhex(oldval, len * 2);
632: datactrl = new wxTextCtrl(this, ID_EDIT, oldstr,
633: wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER);
634: gridsizer->Add(datactrl, 0, wxEXPAND);
635:
636: topsizer->Add(CreateStdDialogButtonSizer(wxOK | wxCANCEL | wxNO_DEFAULT),
637: 0, wxEXPAND | wxALL, 3);
638:
639: SetSizer(topsizer);
640: wxSize sz = topsizer->Fit(this);
641: SetClientSize(sz);
642: SetMinClientSize(sz);
643: }
644:
645: // デストラクタ
646: MemEditDialog::~MemEditDialog()
647: {
648: }
649:
650: // テキスト入力
651: void
652: MemEditDialog::OnTextEnter(wxCommandEvent& event)
653: {
654: EndModal(wxID_OK);
655: }
656:
657: // テキストコントロールの値を返す。
658: // 変換できなければ (uint64)-1 を返す。
659: uint64
660: MemEditDialog::GetData() const
661: {
662: unsigned long int ul;
663: char *end;
664:
665: // wxString だと地味にめんどい
666: wxString wtext = datactrl->GetValue();
667: std::string text((const char *)wtext.mb_str());
668:
669: errno = 0;
670: ul = strtoul(&text[0], &end, 16);
671: if (end == &text[0] || *end != '\0' || errno != 0) {
672: return (uint64)-1;
673: }
674: return (uint32)ul;
675: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.