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

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.14! root      249:        uint32 addr = memdump->GetAddr().Addr();
1.1.1.13  root      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:                // 更新
1.1.1.14! root      408:                if (memdump->Poke(addr, data, len) == false) {
1.1.1.13  root      409:                        ::wxMessageBox(_("Could not edit"), _("Memory Edit"),
                    410:                                wxICON_EXCLAMATION | wxOK | wxOK_DEFAULT, this);
                    411:                }
                    412:        }
                    413: }
                    414: 
                    415: // 16進ダンプ画面のテキスト座標 (x, y) に対応するアドレスを返す。
                    416: // 対応するアドレスがない場合は (uint64)-1 を返す。
                    417: uint64
                    418: WXMemdumpWindow::GetAddrAtHexdump(int x, int y, int len)
                    419: {
                    420:        if (x < 68) {
                    421:                // 16進ダンプ部分
                    422: 
                    423:                // 空白部分なら除外
                    424:                x -= 19;
                    425:                if (x % (len * 2 + 1) == len * 2) {
                    426:                        return (uint64)-1;
                    427:                }
                    428:                x = (x / (len * 2 + 1)) * len;
                    429:        } else {
                    430:                // 文字ダンプ部分
                    431:                x -= 68;
                    432:        }
                    433: 
                    434:        if (x > 15) {
                    435:                return (uint64)-1;
                    436:        }
                    437: 
1.1.1.14! root      438:        return memdump->GetAddr().Addr() + (y * memdump->GetStride()) + x;
1.1.1.9   root      439: }
                    440: 
1.1.1.13  root      441: // 32bit ページテーブル画面のテキスト座標 (x, y) に対応するアドレスを返す。
                    442: // 対応するアドレスがない場合は (uint64)-1 を返す。
                    443: uint64
                    444: WXMemdumpWindow::GetAddrAtPageShort(int x, int y)
                    445: {
                    446:        // 32bit ページテーブルなら1行で1ロングワード。
                    447:        // 16進の場合との親和性のため、ダンプ値のところだけ反応。
                    448:        if (x >= 19 + 8) {
                    449:                return (uint64)-1;
                    450:        }
1.1.1.14! root      451:        return memdump->GetAddr().Addr() + y * 4;
1.1.1.13  root      452: }
                    453: 
                    454: // 逆アセンブル画面のテキスト座標 (x, y) に対応するアドレスを返す。
                    455: // minlen は命令の最小バイト数。
                    456: // 対応するアドレスがない場合は (uint64)-1 を返す。
                    457: uint64
                    458: WXMemdumpWindow::GetAddrAtDisasm(int x, int y, int minlen)
                    459: {
                    460:        // 先頭から y 行目のアドレス
                    461:        uint32 yaddr = memdump->GetLineOffset(y);
                    462: 
                    463:        // y 行目の命令のバイト数
                    464:        uint32 y1addr = memdump->GetLineOffset(y + 1);
                    465:        uint32 bytes = y1addr - yaddr;
                    466: 
                    467:        // 空白部分なら除外
                    468:        x -= 19;
                    469: 
                    470:        if (x % (minlen * 2 + 1) == minlen * 2) {
                    471:                return (uint64)-1;
                    472:        }
                    473:        x = (x / (minlen * 2 + 1)) * minlen;
                    474: 
                    475:        if (x >= bytes) {
                    476:                return (uint64)-1;
                    477:        }
                    478: 
1.1.1.14! root      479:        return memdump->GetAddr().Addr() + yaddr + x;
1.1.1.13  root      480: }
                    481: 
                    482: // セレクション番号からフォーマット番号への変換
                    483: Memdump::Format
                    484: WXMemdumpWindow::Selection2Format(int idx)
                    485: {
                    486:        assert(idx < fmts.size());
                    487:        return fmts[idx].first;
                    488: }
                    489: 
                    490: // フォーマット番号からセレクション番号への変換
                    491: int
                    492: WXMemdumpWindow::Format2Selection(Memdump::Format fmt_)
                    493: {
                    494:        for (int idx = 0, end = fmts.size(); idx < end; idx++) {
                    495:                auto p = fmts[idx];
                    496:                if (fmt_ == p.first) {
                    497:                        return idx;
                    498:                }
                    499:        }
                    500:        // ?
                    501:        return 0;
                    502: }
                    503: 
                    504: // フォーマット番号から文字列への変換
                    505: wxString
                    506: WXMemdumpWindow::Format2String(Memdump::Format fmt_)
                    507: {
                    508:        for (int idx = 0, end = fmts.size(); idx < end; idx++) {
                    509:                auto p = fmts[idx];
                    510:                if (fmt_ == p.first) {
                    511:                        return p.second;
                    512:                }
                    513:        }
                    514:        // ?
                    515:        return wxEmptyString;
                    516: }
                    517: 
                    518: 
                    519: //
                    520: // 編集ダイアログ
                    521: //
                    522: 
                    523: wxBEGIN_EVENT_TABLE(MemEditDialog, inherited)
                    524:        EVT_TEXT_ENTER(ID_EDIT, MemEditDialog::OnTextEnter)
                    525: wxEND_EVENT_TABLE()
                    526: 
                    527: // コンストラクタ
                    528: MemEditDialog::MemEditDialog(wxWindow *parent, uint32 addr, uint32 oldval,
                    529:        int len, const std::string& sizestr)
                    530:        : inherited(parent, wxID_ANY, _("Edit memory"))
                    531: {
                    532:        auto topsizer = new wxBoxSizer(wxVERTICAL);
                    533: 
                    534:        auto gridsizer = new wxFlexGridSizer(2);
                    535:        topsizer->Add(gridsizer, 0, wxEXPAND | wxALL, 3);
                    536: 
                    537:        gridsizer->Add(new wxStaticText(this, wxID_ANY, _("Address:")),
                    538:                0, wxEXPAND);
                    539: 
                    540:        std::string addrstr = "$";
                    541:        addrstr += strhex(addr);
                    542:        auto addrctrl = new wxStaticText(this, wxID_ANY, addrstr,
                    543:                wxDefaultPosition, wxDefaultSize, wxBORDER_SUNKEN);
                    544:        gridsizer->Add(addrctrl, 0, wxEXPAND);
                    545: 
                    546:        gridsizer->Add(new wxStaticText(this, wxID_ANY, _("Size:")),
                    547:                0, wxEXPAND);
                    548:        gridsizer->Add(new wxStaticText(this, wxID_ANY, sizestr),
                    549:                0, wxEXPAND);
                    550: 
                    551:        gridsizer->Add(new wxStaticText(this, wxID_ANY, _("Data:")),
                    552:                0, wxEXPAND);
                    553: 
                    554:        std::string oldstr = strhex(oldval, len * 2);
                    555:        datactrl = new wxTextCtrl(this, ID_EDIT, oldstr,
                    556:                wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER);
                    557:        gridsizer->Add(datactrl, 0, wxEXPAND);
                    558: 
                    559:        topsizer->Add(CreateStdDialogButtonSizer(wxOK | wxCANCEL | wxNO_DEFAULT),
                    560:                0, wxEXPAND | wxALL, 3);
                    561: 
                    562:        SetSizer(topsizer);
                    563:        wxSize sz = topsizer->Fit(this);
                    564:        SetClientSize(sz);
                    565:        SetMinClientSize(sz);
                    566: }
                    567: 
                    568: // デストラクタ
                    569: MemEditDialog::~MemEditDialog()
                    570: {
                    571: }
                    572: 
                    573: // テキスト入力
                    574: void
                    575: MemEditDialog::OnTextEnter(wxCommandEvent& event)
                    576: {
                    577:        EndModal(wxID_OK);
                    578: }
                    579: 
                    580: // テキストコントロールの値を返す。
                    581: // 変換できなければ (uint64)-1 を返す。
                    582: uint64
                    583: MemEditDialog::GetData() const
                    584: {
                    585:        unsigned long int ul;
                    586:        char *end;
                    587: 
                    588:        // wxString だと地味にめんどい
                    589:        wxString wtext = datactrl->GetValue();
                    590:        std::string text((const char *)wtext.mb_str());
                    591: 
                    592:        errno = 0;
                    593:        ul = strtoul(&text[0], &end, 16);
                    594:        if (end == &text[0] || *end != '\0' || errno != 0) {
                    595:                return (uint64)-1;
                    596:        }
                    597:        return (uint32)ul;
                    598: }

unix.superglobalmegacorp.com

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