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