Annotation of nono/wx/wxdumpmonitor.cpp, revision 1.1.1.13

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.