|
|
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.17! root 144: // 自前レイアウト。
! 145: SetMyLayout();
! 146:
1.1.1.11 root 147: // ウィンドウサイズを確定させる
1.1.1.13 root 148: FontChanged();
1.1.1.11 root 149:
1.1.1.13 root 150: // パネルに来るマウスイベントをこっちに回す
151: screen->Connect(wxEVT_MOUSEWHEEL,
152: wxMouseEventHandler(WXMemdumpWindow::OnMouseWheel), NULL, this);
153: screen->Connect(wxEVT_LEFT_DCLICK,
154: wxMouseEventHandler(WXMemdumpWindow::OnDClick), NULL, this);
155:
156: // メモリダンプオブジェクトを取得
157: auto mon = screen->GetMonitor();
1.1.1.15 root 158: memdump = dynamic_cast<MemdumpMonitor *>(mon->obj);
1.1.1.13 root 159: assert(memdump);
160:
161: // 初期値をコントロールに設定
162: auto fmt = memdump->GetFormat();
163: fmtctrl->SetSelection(Format2Selection(fmt));
164: DoFormat(fmt);
1.1.1.9 root 165: UpdateAddr();
1.1 root 166: }
167:
168: // デストラクタ
169: WXMemdumpWindow::~WXMemdumpWindow()
170: {
171: }
172:
1.1.1.13 root 173: void
174: WXMemdumpWindow::FontChanged()
175: {
176: for (auto *btn : buttons) {
1.1.1.16 root 177: // ボタンサイズを先に一旦リセット。
178: btn->SetMinSize(wxSize(1, 1));
179: btn->SetSize(wxSize(1, 1));
180:
181: // 各ボタンコントロールに伝搬。
1.1.1.13 root 182: btn->FontChanged();
1.1.1.16 root 183:
184: // ボタンを正方形に固定する (テキストは1文字か2文字と知っている)。
185: // 押しやすくするため、最小 24x24 にしてみる。
186: wxSize size = btn->GetSize();
187: if (size.y < 24) {
188: size.y = 24;
189: }
190: size.x = size.y;
191:
192: // 勝手にベストサイズに戻らないように最小サイズごと固定する。
193: btn->SetSize(size);
194: btn->SetMinSize(size);
1.1.1.13 root 195: }
1.1.1.16 root 196:
197: screen->FontChanged();
198:
199: Fit();
200: }
201:
202: bool
1.1.1.17! root 203: WXMemdumpWindow::GetMySizeHints(wxSize *newp, wxSize *minp, wxSize *maxp,
! 204: wxSize *incp)
1.1.1.16 root 205: {
206: // この後の Fit() でリサイズに使われる大きさを取得。
207: wxSize fitsize = GetSizer()->ComputeFittingClientSize(this);
208: wxSize ctrlsize = ctrlbox->ComputeFittingClientSize(this);
209:
210: // 高さの最小は (コントロールパネル分と) TextScreen 1行分にしておく。
211: int min_y = ctrlsize.y + screen->GetScreenHeight(1);
212: int new_y = ctrlsize.y + screen->GetSize().y;
1.1.1.17! root 213: wxSize newsize(fitsize.x, new_y);
1.1.1.16 root 214: wxSize minsize(fitsize.x, min_y);
215: wxSize maxsize(fitsize.x, GetMaxClientSize().y);
216: wxSize incsize(0, screen->GetFontHeight());
217:
1.1.1.17! root 218: if (newp) *newp = newsize;
! 219: if (minp) *minp = minsize;
! 220: if (maxp) *maxp = maxsize;
! 221: if (incp) *incp = incsize;
! 222: return true;
! 223: }
! 224:
! 225: bool
! 226: WXMemdumpWindow::Layout()
! 227: {
! 228: if (MyLayout() == false) {
! 229: // Sizer 使ってるのでその処理は(さらに親に)任せる。
! 230: BaseLayout();
! 231: }
! 232: return true;
1.1.1.13 root 233: }
234:
1.1 root 235: // テキスト入力イベント
236: void
237: WXMemdumpWindow::OnTextEnter(wxCommandEvent& event)
238: {
239: // 入力文字列(16進文字列)を数値に変換
1.1.1.5 root 240: const wxString& wstr = event.GetString();
1.1.1.6 root 241: uint32 val = strtoul((const char *)wstr.mb_str(), NULL, 16);
1.1 root 242:
1.1.1.9 root 243: // アドレスを更新
1.1.1.13 root 244: memdump->SetAddr(val);
1.1.1.9 root 245: UpdateAddr();
1.1 root 246: }
247:
1.1.1.13 root 248: // "<"(前行) ボタン押下イベント
1.1 root 249: void
1.1.1.13 root 250: WXMemdumpWindow::OnPrevLine(wxCommandEvent& event)
1.1 root 251: {
1.1.1.13 root 252: // 1行戻る
253: memdump->Offset(memdump->GetLineOffset(-1));
1.1.1.9 root 254:
1.1.1.13 root 255: UpdateAddr();
256: }
257:
258: // "<<"(前ページ) ボタン押下イベント
259: void
260: WXMemdumpWindow::OnPrevPage(wxCommandEvent& event)
261: {
262: // 1ページ戻る
263: memdump->Offset(memdump->GetPageOffset(-1));
1.1.1.9 root 264:
265: UpdateAddr();
1.1 root 266: }
267:
1.1.1.13 root 268: // ">"(次行) ボタン押下イベント
1.1 root 269: void
1.1.1.13 root 270: WXMemdumpWindow::OnNextLine(wxCommandEvent& event)
1.1 root 271: {
1.1.1.13 root 272: // 1行進む
273: memdump->Offset(memdump->GetLineOffset(1));
274:
275: UpdateAddr();
276: }
1.1.1.9 root 277:
1.1.1.13 root 278: // ">>"(次ページ) ボタン押下イベント
279: void
280: WXMemdumpWindow::OnNextPage(wxCommandEvent& event)
281: {
282: // 1ページ進む
283: memdump->Offset(memdump->GetPageOffset(1));
1.1.1.9 root 284:
285: UpdateAddr();
1.1 root 286: }
287:
1.1.1.9 root 288: // アドレス欄の表示を更新する
289: void
290: WXMemdumpWindow::UpdateAddr()
291: {
1.1.1.13 root 292: int width;
293: std::string title;
294: if (IS_MONITOR_XPMEMDUMP(monid)) {
295: width = 5;
296: title = _("XP Memory Dump");
297: } else {
298: width = 8;
299: title = _("Main Memory Dump");
300: }
1.1.1.9 root 301:
1.1.1.14 root 302: uint32 addr = memdump->GetAddr().Addr();
1.1.1.13 root 303: std::string addrstr = strhex(addr, width);
1.1.1.9 root 304:
305: // EVT_TEXT を起こさず変更する
1.1.1.13 root 306: addrctrl->ChangeValue(addrstr);
1.1.1.9 root 307:
308: // カーソルを末尾に
309: addrctrl->SetInsertionPointEnd();
310:
311: // タイトルを変更
1.1.1.13 root 312: title += string_format(" %d: $", myidx);
313: title += addrstr;
314: SetTitle(title);
315:
316: // 即更新
317: Refresh();
1.1.1.9 root 318: }
319:
1.1.1.13 root 320: // 表示フォーマット変更イベント
321: void
322: WXMemdumpWindow::OnFormat(wxCommandEvent& event)
1.1.1.9 root 323: {
1.1.1.13 root 324: int idx = event.GetSelection();
325: DoFormat(Selection2Format(idx));
1.1 root 326: }
1.1.1.9 root 327:
1.1.1.13 root 328: // 表示フォーマット変更処理
1.1.1.9 root 329: void
1.1.1.13 root 330: WXMemdumpWindow::DoFormat(Memdump::Format fmt)
1.1.1.9 root 331: {
1.1.1.13 root 332: memdump->SetFormat(fmt);
333:
334: // SetFormat() によってアドレスが切り捨てられる場合があるので
335: // アドレス欄の表示ごと更新。
336: UpdateAddr();
337: }
338:
339: // マウスホイールイベント
340: void
341: WXMemdumpWindow::OnMouseWheel(wxMouseEvent& event)
342: {
343: int delta = event.GetWheelRotation();
344:
345: // 1回の変化で +/-120 が来る。
346: // たいていのアプリケーションで3行ずつの移動に換算することが多いようだが
347: // ここはメモリダンプなので 4行ずつにする。
348:
349: if (delta != 0) {
350: memdump->Offset(memdump->GetLineOffset(-delta / 30));
351: UpdateAddr();
352: }
353: }
354:
355: // ダブルクリックイベント
356: void
357: WXMemdumpWindow::OnDClick(wxMouseEvent& event)
358: {
359: event.Skip();
360:
361: auto fmt = memdump->GetFormat();
362:
363: // テキストの桁数、行数にする
364: wxPoint tpos = screen->GetTextPosition(event.GetPosition());
365: int x = tpos.x;
366: int y = tpos.y;
367:
368: // ウィンドウサイズを変えた時に出来る下の空き地にはヒットさせない
369: if (y >= screen->GetRow()) {
370: return;
371: }
372:
373: // アドレス部分は常に除外でいいか
374: if (x < 19) {
375: return;
376: }
377:
378: // 現在のフォーマットでのクリック位置のアドレスを求める
379: int len = 0;
380: uint64 addr = -1;
381: switch (fmt) {
382: case Memdump::Byte:
383: len = 1;
384: addr = GetAddrAtHexdump(x, y, len);
385: break;
386: case Memdump::Word:
387: len = 2;
388: addr = GetAddrAtHexdump(x, y, len);
389: break;
390: case Memdump::Long:
391: len = 4;
392: addr = GetAddrAtHexdump(x, y, len);
393: break;
394: case Memdump::M68030PageShort:
395: case Memdump::M88200Page:
396: len = 4;
397: addr = GetAddrAtPageShort(x, y);
398: break;
399:
400: case Memdump::M68030PageLong:
401: PANIC("not supported");
402: break;
403:
1.1.1.15 root 404: case Memdump::M680x0Disasm:
1.1.1.13 root 405: len = 2;
406: addr = GetAddrAtDisasm(x, y, len);
407: break;
408:
409: case Memdump::M88100Disasm:
410: len = 4;
411: addr = GetAddrAtDisasm(x, y, len);
412: break;
413:
414: case Memdump::HD64180Disasm:
415: len = 1;
416: addr = GetAddrAtDisasm(x, y, len);
417: break;
418:
419: default:
420: break;
421: }
422: if ((int64)addr < 0) {
423: return;
424: }
425: addr &= ~(len - 1);
426:
427: // このアドレスが編集可能 (≒メモリ) か?
428: if (memdump->CanPoke(addr) == false) {
429: ::wxMessageBox(_("Can not edit here"), _("Memory Edit"),
430: wxICON_EXCLAMATION | wxOK | wxOK_DEFAULT, this);
431: return;
432: }
433:
434: // 出来ればここをハイライトとかしたい
435:
436: // 現在値を(再)取得。
437: uint32 val = memdump->Peek(addr, len);
438:
439: // sizestr は表示形式ではなく単なるサイズ。(DescShort なら Long)
440: std::string sizestr;
441: switch (len) {
442: case 1:
443: sizestr = Format2String(Memdump::Byte);
444: break;
445: case 2:
446: sizestr = Format2String(Memdump::Word);
447: break;
448: case 4:
449: sizestr = Format2String(Memdump::Long);
450: break;
451: default:
452: PANIC("corrupted len=%d", len);
453: }
454:
455: // 編集
456: auto dlg = new MemEditDialog(this, addr, val, len, sizestr);
457: if (dlg->ShowModal() == wxID_OK) {
458: uint32 data = dlg->GetData();
459:
460: // 更新
1.1.1.14 root 461: if (memdump->Poke(addr, data, len) == false) {
1.1.1.13 root 462: ::wxMessageBox(_("Could not edit"), _("Memory Edit"),
463: wxICON_EXCLAMATION | wxOK | wxOK_DEFAULT, this);
464: }
465: }
466: }
467:
468: // 16進ダンプ画面のテキスト座標 (x, y) に対応するアドレスを返す。
469: // 対応するアドレスがない場合は (uint64)-1 を返す。
470: uint64
471: WXMemdumpWindow::GetAddrAtHexdump(int x, int y, int len)
472: {
473: if (x < 68) {
474: // 16進ダンプ部分
475:
476: // 空白部分なら除外
477: x -= 19;
478: if (x % (len * 2 + 1) == len * 2) {
479: return (uint64)-1;
480: }
481: x = (x / (len * 2 + 1)) * len;
482: } else {
483: // 文字ダンプ部分
484: x -= 68;
485: }
486:
487: if (x > 15) {
488: return (uint64)-1;
489: }
490:
1.1.1.14 root 491: return memdump->GetAddr().Addr() + (y * memdump->GetStride()) + x;
1.1.1.9 root 492: }
493:
1.1.1.13 root 494: // 32bit ページテーブル画面のテキスト座標 (x, y) に対応するアドレスを返す。
495: // 対応するアドレスがない場合は (uint64)-1 を返す。
496: uint64
497: WXMemdumpWindow::GetAddrAtPageShort(int x, int y)
498: {
499: // 32bit ページテーブルなら1行で1ロングワード。
500: // 16進の場合との親和性のため、ダンプ値のところだけ反応。
501: if (x >= 19 + 8) {
502: return (uint64)-1;
503: }
1.1.1.14 root 504: return memdump->GetAddr().Addr() + y * 4;
1.1.1.13 root 505: }
506:
507: // 逆アセンブル画面のテキスト座標 (x, y) に対応するアドレスを返す。
508: // minlen は命令の最小バイト数。
509: // 対応するアドレスがない場合は (uint64)-1 を返す。
510: uint64
511: WXMemdumpWindow::GetAddrAtDisasm(int x, int y, int minlen)
512: {
513: // 先頭から y 行目のアドレス
514: uint32 yaddr = memdump->GetLineOffset(y);
515:
516: // y 行目の命令のバイト数
517: uint32 y1addr = memdump->GetLineOffset(y + 1);
518: uint32 bytes = y1addr - yaddr;
519:
520: // 空白部分なら除外
521: x -= 19;
522:
523: if (x % (minlen * 2 + 1) == minlen * 2) {
524: return (uint64)-1;
525: }
526: x = (x / (minlen * 2 + 1)) * minlen;
527:
528: if (x >= bytes) {
529: return (uint64)-1;
530: }
531:
1.1.1.14 root 532: return memdump->GetAddr().Addr() + yaddr + x;
1.1.1.13 root 533: }
534:
535: // セレクション番号からフォーマット番号への変換
536: Memdump::Format
537: WXMemdumpWindow::Selection2Format(int idx)
538: {
539: assert(idx < fmts.size());
540: return fmts[idx].first;
541: }
542:
543: // フォーマット番号からセレクション番号への変換
544: int
545: WXMemdumpWindow::Format2Selection(Memdump::Format fmt_)
546: {
547: for (int idx = 0, end = fmts.size(); idx < end; idx++) {
548: auto p = fmts[idx];
549: if (fmt_ == p.first) {
550: return idx;
551: }
552: }
553: // ?
554: return 0;
555: }
556:
557: // フォーマット番号から文字列への変換
558: wxString
559: WXMemdumpWindow::Format2String(Memdump::Format fmt_)
560: {
561: for (int idx = 0, end = fmts.size(); idx < end; idx++) {
562: auto p = fmts[idx];
563: if (fmt_ == p.first) {
564: return p.second;
565: }
566: }
567: // ?
568: return wxEmptyString;
569: }
570:
571:
572: //
573: // 編集ダイアログ
574: //
575:
576: wxBEGIN_EVENT_TABLE(MemEditDialog, inherited)
577: EVT_TEXT_ENTER(ID_EDIT, MemEditDialog::OnTextEnter)
578: wxEND_EVENT_TABLE()
579:
580: // コンストラクタ
581: MemEditDialog::MemEditDialog(wxWindow *parent, uint32 addr, uint32 oldval,
582: int len, const std::string& sizestr)
583: : inherited(parent, wxID_ANY, _("Edit memory"))
584: {
585: auto topsizer = new wxBoxSizer(wxVERTICAL);
586:
587: auto gridsizer = new wxFlexGridSizer(2);
588: topsizer->Add(gridsizer, 0, wxEXPAND | wxALL, 3);
589:
590: gridsizer->Add(new wxStaticText(this, wxID_ANY, _("Address:")),
591: 0, wxEXPAND);
592:
593: std::string addrstr = "$";
594: addrstr += strhex(addr);
595: auto addrctrl = new wxStaticText(this, wxID_ANY, addrstr,
596: wxDefaultPosition, wxDefaultSize, wxBORDER_SUNKEN);
597: gridsizer->Add(addrctrl, 0, wxEXPAND);
598:
599: gridsizer->Add(new wxStaticText(this, wxID_ANY, _("Size:")),
600: 0, wxEXPAND);
601: gridsizer->Add(new wxStaticText(this, wxID_ANY, sizestr),
602: 0, wxEXPAND);
603:
604: gridsizer->Add(new wxStaticText(this, wxID_ANY, _("Data:")),
605: 0, wxEXPAND);
606:
607: std::string oldstr = strhex(oldval, len * 2);
608: datactrl = new wxTextCtrl(this, ID_EDIT, oldstr,
609: wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER);
610: gridsizer->Add(datactrl, 0, wxEXPAND);
611:
612: topsizer->Add(CreateStdDialogButtonSizer(wxOK | wxCANCEL | wxNO_DEFAULT),
613: 0, wxEXPAND | wxALL, 3);
614:
615: SetSizer(topsizer);
616: wxSize sz = topsizer->Fit(this);
617: SetClientSize(sz);
618: SetMinClientSize(sz);
619: }
620:
621: // デストラクタ
622: MemEditDialog::~MemEditDialog()
623: {
624: }
625:
626: // テキスト入力
627: void
628: MemEditDialog::OnTextEnter(wxCommandEvent& event)
629: {
630: EndModal(wxID_OK);
631: }
632:
633: // テキストコントロールの値を返す。
634: // 変換できなければ (uint64)-1 を返す。
635: uint64
636: MemEditDialog::GetData() const
637: {
638: unsigned long int ul;
639: char *end;
640:
641: // wxString だと地味にめんどい
642: wxString wtext = datactrl->GetValue();
643: std::string text((const char *)wtext.mb_str());
644:
645: errno = 0;
646: ul = strtoul(&text[0], &end, 16);
647: if (end == &text[0] || *end != '\0' || errno != 0) {
648: return (uint64)-1;
649: }
650: return (uint32)ul;
651: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.