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

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: }

unix.superglobalmegacorp.com

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