Annotation of nono/wx/wxmainframe.cpp, revision 1.1.1.25

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.13  root        7: //
                      8: // メインウィンドウ
                      9: //
                     10: 
1.1.1.4   root       11: #include "wxmainframe.h"
1.1.1.13  root       12: #include "fontmanager.h"
1.1.1.18  root       13: #include "wxaccstatmonitor.h"
1.1.1.15  root       14: #include "wxdipswwindow.h"
1.1.1.4   root       15: #include "wxdumpmonitor.h"
1.1.1.23  root       16: #include "wxgvrammonitor.h"
1.1.1.5   root       17: #include "wxlcdwindow.h"
1.1.1.4   root       18: #include "wxlogmonitor.h"
1.1.1.13  root       19: #include "wxlogsetting.h"
1.1.1.4   root       20: #include "wxmainview.h"
                     21: #include "wxmonitor.h"
                     22: #include "wxmpumonitor.h"
1.1.1.25! root       23: #include "wxpagetablemonitor.h"
1.1.1.15  root       24: #include "wxpalettemonitor.h"
1.1.1.14  root       25: #include "wxromwindow.h"
1.1.1.4   root       26: #include "wxsoftkey.h"
1.1.1.9   root       27: #include "wxstatuspanel.h"
1.1.1.24  root       28: #include "wxthreadmonitor.h"
1.1.1.23  root       29: #include "wxtvrammonitor.h"
1.1.1.11  root       30: #include "wxuimessage.h"
1.1.1.4   root       31: #include "wxversion.h"
1.1.1.13  root       32: #include "config.h"
1.1.1.14  root       33: #include "fdc.h"
                     34: #include "fdd.h"
1.1.1.22  root       35: #include "hostcom.h"
                     36: #include "hostnet.h"
1.1.1.24  root       37: #include "hostsound.h"
1.1.1.3   root       38: #include "mainapp.h"
1.1.1.17  root       39: #include "mpu.h"
1.1.1.22  root       40: #include "netdriver_slirp.h"
1.1.1.13  root       41: #include "nmi.h"
                     42: #include "power.h"
1.1.1.18  root       43: #include "scsidev.h"
1.1.1.21  root       44: #include "scsidomain.h"
1.1.1.15  root       45: #include "syncer.h"
                     46: #include <algorithm>
1.1       root       47: 
1.1.1.23  root       48: // ID は 1 から (wxID_LOWEST = 5000 未満まで) 使えるっぽい
                     49: // (wxGTK は 0 から使用可能だが wxOSX は 0 が不可)。
1.1.1.13  root       50: // メニュー ID のうちウィンドウのオープン状態を維持する必要があるものは
1.1.1.23  root       51: // 0 (付近) から割り当てて 0 から始まる配列で管理してしまうのが手っ取り早い。
1.1.1.13  root       52: // ウィンドウに割り当てるウィンドウ ID とメニューイベントで飛んでくる
                     53: // メニュー ID は互いに干渉しないはずなので、同じ値を使うことでメニューと
                     54: // ウィンドウの紐付けをする。
                     55: //
                     56: // ウィンドウ(サブウィンドウ)は細かくは以下のように4つに分類できるが、
                     57: // 処理上区別が必要なのは A. (デバッガの show コマンドとも共用できる
                     58: // サブウィンドウ) とそれ以外のサブウィンドウだけ。
                     59: //
                     60: // -----------+------------+----
                     61: // モニター   | テキスト   | A. 単純なテキストモニタウィンドウ
                     62: // ウィンドウ | モニター   |    (SPC, MFP などのデバイスのモニター)
                     63: //            | ウィンドウ +----
                     64: //            |            | B. それ以外のテキストモニターウィンドウ
                     65: //            |            |    (ログ、メモリのように表示位置があるもの、
                     66: //            |            |     CMMU のように構造があるもの)
                     67: //            +------------+----
                     68: //            | それ以外の | C. ビデオモニターウィンドウなど
                     69: //            | モニター   |    (ビットマッププレーン、TVRAM など)
                     70: //            | ウィンドウ |
                     71: // -----------+------------+----
                     72: // それ以外のウィンドウ    | D. ソフトウェアキーボードウィンドウなど
                     73: // ------------------------+----
                     74: enum {
                     75:        ID_SUBWIN_END_DUMMY = ID_SUBWIN_END,
                     76: 
                     77:        // ここから (ウィンドウでない)メニュー ID
1.1.1.15  root       78:        ID_EXIT,
1.1.1.13  root       79:        ID_RESTART_VM,
1.1.1.17  root       80:        ID_POWER_BUTTON,
                     81:        ID_SOFTRESET,
                     82:        ID_RESET_BUTTON,
                     83:        ID_NMI_BUTTON,
                     84: 
1.1.1.13  root       85:        ID_FULL_SPEED,
                     86: 
                     87:        ID_INPUT_START,
                     88:        ID_INPUT_CHAR,
                     89:        ID_INPUT_JP,
                     90:        ID_INPUT_END,
                     91: 
1.1.1.22  root       92:        ID_HOSTNET0_START,
                     93:        ID_HOSTNET0_USERMODE,
                     94:        ID_HOSTNET0_TAP,
                     95:        ID_HOSTNET0_BPF,
                     96:        ID_HOSTNET0_AFPACKET,
                     97:        ID_HOSTNET0_NONE,       // 最後に置くこと
                     98: 
                     99:        ID_HOSTNET1_START,
                    100:        ID_HOSTNET1_USERMODE,
                    101:        ID_HOSTNET1_TAP,
                    102:        ID_HOSTNET1_BPF,
                    103:        ID_HOSTNET1_AFPACKET,
                    104:        ID_HOSTNET1_NONE,       // 最後に置くこと
                    105: 
                    106:        ID_HOSTCOM0_START,
                    107:        ID_HOSTCOM0_TCP,
                    108:        ID_HOSTCOM0_STDIO,
                    109:        ID_HOSTCOM0_CONSOLE,
                    110:        ID_HOSTCOM0_NONE,       // 最後に置くこと
                    111: 
                    112:        ID_HOSTCOM1_START,
                    113:        ID_HOSTCOM1_TCP,
                    114:        ID_HOSTCOM1_STDIO,
                    115:        ID_HOSTCOM1_CONSOLE,
                    116:        ID_HOSTCOM1_NONE,       // 最後に置くこと
                    117: 
                    118:        ID_HOSTCOM2_START,
                    119:        ID_HOSTCOM2_TCP,
                    120:        ID_HOSTCOM2_STDIO,
                    121:        ID_HOSTCOM2_CONSOLE,
                    122:        ID_HOSTCOM2_NONE,       // 最後に置くこと
                    123: 
                    124:        ID_HOSTCOM_DBG_START,
                    125:        ID_HOSTCOM_DBG_TCP,
                    126:        ID_HOSTCOM_DBG_STDIO,
                    127:        ID_HOSTCOM_DBG_CONSOLE, // 存在しないけど HOSTCOMn と揃える必要がある。
                    128:        ID_HOSTCOM_DBG_NONE,    // 最後に置くこと。
                    129: 
1.1.1.24  root      130:        ID_HOSTSOUND_START,
                    131:        ID_HOSTSOUND_NETBSD,
                    132:        ID_HOSTSOUND_SNDIO,
                    133:        ID_HOSTSOUND_ALSA,
                    134:        ID_HOSTSOUND_WAV,
                    135:        ID_HOSTSOUND_NONE,      // 最後に置くこと
                    136: 
1.1.1.13  root      137:        ID_SCALE_START,
1.1.1.15  root      138:        ID_SCALE_END = ID_SCALE_START + 6,
1.1.1.13  root      139: 
                    140:        ID_FONTSIZE_START, // START 以降は fontsize_t と同じ順に並べること
                    141:        ID_FONTSIZE_12,
                    142:        ID_FONTSIZE_16,
1.1.1.15  root      143:        ID_FONTSIZE_24,
1.1.1.13  root      144:        ID_FONTSIZE_END,
                    145: 
1.1.1.21  root      146:        ID_DEVICE_EMPTY,
                    147: 
1.1.1.13  root      148:        ID_MONRATE_START,
1.1.1.15  root      149:        ID_MONRATE_END = ID_MONRATE_START + 4,
1.1.1.13  root      150: 
                    151:        ID_SHOW_STATPANEL,
                    152: 
1.1.1.14  root      153:        // FD
                    154:        ID_FD_INSERT_0,
                    155:        ID_FD_INSERT_1,
                    156:        ID_FD_INSERT_2,
                    157:        ID_FD_INSERT_3,
                    158:        ID_FD_MISINSERT_0,
                    159:        ID_FD_MISINSERT_1,
                    160:        ID_FD_MISINSERT_2,
                    161:        ID_FD_MISINSERT_3,
                    162:        ID_FD_EJECT_0,
                    163:        ID_FD_EJECT_1,
                    164:        ID_FD_EJECT_2,
                    165:        ID_FD_EJECT_3,
                    166:        ID_FD_FORCE_0,
                    167:        ID_FD_FORCE_1,
                    168:        ID_FD_FORCE_2,
                    169:        ID_FD_FORCE_3,
                    170: 
1.1.1.13  root      171:        // CD/MO (リムーバブルデバイス)
                    172:        ID_CD_INSERT_0,
                    173:        ID_CD_INSERT_1,
                    174:        ID_CD_INSERT_2,
                    175:        ID_CD_INSERT_3,
                    176:        ID_CD_INSERT_4,
                    177:        ID_CD_INSERT_5,
                    178:        ID_CD_INSERT_6,
                    179:        ID_CD_INSERT_7,
                    180:        ID_CD_EJECT_0,
                    181:        ID_CD_EJECT_1,
                    182:        ID_CD_EJECT_2,
                    183:        ID_CD_EJECT_3,
                    184:        ID_CD_EJECT_4,
                    185:        ID_CD_EJECT_5,
                    186:        ID_CD_EJECT_6,
                    187:        ID_CD_EJECT_7,
                    188:        ID_CD_FORCE_0,
                    189:        ID_CD_FORCE_1,
                    190:        ID_CD_FORCE_2,
                    191:        ID_CD_FORCE_3,
                    192:        ID_CD_FORCE_4,
                    193:        ID_CD_FORCE_5,
                    194:        ID_CD_FORCE_6,
                    195:        ID_CD_FORCE_7,
                    196: 
                    197:        ID_MOUSEMODE,
                    198:        ID_KEYBOARD_CONNECT,
                    199: 
                    200:        ID_local_end,   // 最後に置く (チェック用)
                    201: };
1.1.1.14  root      202: static_assert(ID_local_end - 1 <= (int)IDGROUP_MAINFRAME_END, "ID exceeded");
1.1.1.13  root      203: 
1.1.1.14  root      204: #define ID_FD_INSERT(id)       (ID_FD_INSERT_0 + (id))
                    205: #define ID_FD_MISINSERT(id)    (ID_FD_MISINSERT_0 + (id))
                    206: #define ID_FD_EJECT(id)                (ID_FD_EJECT_0 + (id))
                    207: #define ID_FD_FORCE(id)                (ID_FD_FORCE_0 + (id))
1.1.1.13  root      208: #define ID_CD_INSERT(id)       (ID_CD_INSERT_0 + (id))
                    209: #define ID_CD_EJECT(id)        (ID_CD_EJECT_0 + (id))
                    210: #define ID_CD_FORCE(id)        (ID_CD_FORCE_0 + (id))
                    211: 
1.1       root      212: wxBEGIN_EVENT_TABLE(WXMainFrame, inherited)
1.1.1.3   root      213:        EVT_CLOSE(WXMainFrame::OnClose)
1.1.1.15  root      214:        EVT_MENU(ID_EXIT, WXMainFrame::OnExit)
1.1       root      215: 
1.1.1.17  root      216:        EVT_MENU(ID_POWER_BUTTON, WXMainFrame::OnPowerButton)
                    217:        EVT_UPDATE_UI(ID_POWER_BUTTON, WXMainFrame::OnPowerButtonUI)
                    218:        EVT_MENU(ID_SOFTRESET, WXMainFrame::OnSoftReset)
                    219:        EVT_MENU(ID_RESET_BUTTON, WXMainFrame::OnResetButton)
                    220:        EVT_MENU(ID_NMI_BUTTON, WXMainFrame::OnNMIButton)
1.1.1.12  root      221:        EVT_MENU(ID_RESTART_VM, WXMainFrame::OnRestartVM)
1.1.1.17  root      222: 
1.1       root      223:        EVT_MENU(ID_FULL_SPEED, WXMainFrame::OnFullSpeed)
                    224:        EVT_UPDATE_UI(ID_FULL_SPEED, WXMainFrame::OnFullSpeedUI)
1.1.1.12  root      225:        EVT_MENU_RANGE(ID_INPUT_START + 1, ID_INPUT_END - 1,
                    226:                WXMainFrame::OnMenuInput)
                    227:        EVT_UPDATE_UI_RANGE(ID_INPUT_START + 1, ID_INPUT_END -1,
                    228:                WXMainFrame::OnMenuInputUI)
1.1.1.22  root      229: 
                    230:        EVT_MENU_RANGE(ID_HOSTNET0_START + 1, ID_HOSTNET1_NONE,
                    231:                WXMainFrame::OnMenuHostNet)
                    232:        EVT_UPDATE_UI_RANGE(ID_HOSTNET0_START + 1, ID_HOSTNET1_NONE,
                    233:                WXMainFrame::OnMenuHostNetUI)
                    234:        EVT_MENU_RANGE(ID_HOSTCOM0_START + 1, ID_HOSTCOM2_NONE,
                    235:                WXMainFrame::OnMenuHostCom)
                    236:        EVT_UPDATE_UI_RANGE(ID_HOSTCOM0_START + 1, ID_HOSTCOM2_NONE,
                    237:                WXMainFrame::OnMenuHostComUI)
1.1.1.24  root      238:        EVT_MENU_RANGE(ID_HOSTSOUND_START + 1, ID_HOSTSOUND_NONE,
                    239:                WXMainFrame::OnMenuHostSound)
                    240:        EVT_UPDATE_UI_RANGE(ID_HOSTSOUND_START + 1, ID_HOSTSOUND_NONE,
                    241:                WXMainFrame::OnMenuHostSoundUI)
1.1.1.22  root      242: 
1.1.1.15  root      243:        EVT_MENU_RANGE(ID_SCALE_START, ID_SCALE_END,
1.1       root      244:                WXMainFrame::OnMenuScale)
1.1.1.15  root      245:        EVT_UPDATE_UI_RANGE(ID_SCALE_START, ID_SCALE_END,
1.1       root      246:                WXMainFrame::OnMenuScaleUI)
                    247:        EVT_MENU_RANGE(ID_FONTSIZE_START + 1, ID_FONTSIZE_END - 1,
                    248:                WXMainFrame::OnMenuFontSize)
                    249:        EVT_UPDATE_UI_RANGE(ID_FONTSIZE_START + 1, ID_FONTSIZE_END - 1,
                    250:                WXMainFrame::OnMenuFontSizeUI)
1.1.1.15  root      251:        EVT_MENU_RANGE(ID_MONRATE_START, ID_MONRATE_END,
1.1.1.5   root      252:                WXMainFrame::OnMenuMonRate)
1.1.1.15  root      253:        EVT_UPDATE_UI_RANGE(ID_MONRATE_START, ID_MONRATE_END,
1.1.1.5   root      254:                WXMainFrame::OnMenuMonRateUI)
1.1.1.9   root      255:        EVT_MENU(ID_SHOW_STATPANEL, WXMainFrame::OnShowStatusPanel)
                    256:        EVT_UPDATE_UI(ID_SHOW_STATPANEL, WXMainFrame::OnShowStatusPanelUI)
1.1.1.14  root      257:        EVT_MENU_RANGE(ID_FD_INSERT_0, ID_FD_INSERT_3,
                    258:                WXMainFrame::OnFDInsert)
                    259:        EVT_UPDATE_UI_RANGE(ID_FD_INSERT_0, ID_FD_INSERT_3,
                    260:                WXMainFrame::OnFDInsertUI)
                    261:        EVT_MENU_RANGE(ID_FD_EJECT_0, ID_FD_EJECT_3,
                    262:                WXMainFrame::OnFDEject)
                    263:        EVT_UPDATE_UI_RANGE(ID_FD_EJECT_0, ID_FD_EJECT_3,
                    264:                WXMainFrame::OnFDEjectUI)
                    265:        EVT_MENU_RANGE(ID_FD_FORCE_0, ID_FD_FORCE_3,
                    266:                WXMainFrame::OnFDForce)
                    267:        EVT_UPDATE_UI_RANGE(ID_FD_FORCE_0, ID_FD_FORCE_3,
                    268:                WXMainFrame::OnFDForceUI)
1.1.1.11  root      269:        EVT_MENU_RANGE(ID_CD_INSERT_0, ID_CD_INSERT_7,
                    270:                WXMainFrame::OnCDInsert)
                    271:        EVT_UPDATE_UI_RANGE(ID_CD_INSERT_0, ID_CD_INSERT_7,
                    272:                WXMainFrame::OnCDInsertUI)
                    273:        EVT_MENU_RANGE(ID_CD_EJECT_0, ID_CD_EJECT_7,
                    274:                WXMainFrame::OnCDEject)
                    275:        EVT_UPDATE_UI_RANGE(ID_CD_EJECT_0, ID_CD_EJECT_7,
                    276:                WXMainFrame::OnCDEjectUI)
                    277:        EVT_MENU_RANGE(ID_CD_FORCE_0, ID_CD_FORCE_7,
                    278:                WXMainFrame::OnCDForce)
                    279:        EVT_UPDATE_UI_RANGE(ID_CD_FORCE_0, ID_CD_FORCE_7,
                    280:                WXMainFrame::OnCDForceUI)
1.1.1.2   root      281:        EVT_MENU(ID_MOUSEMODE, WXMainFrame::OnMouseMode)
                    282:        EVT_UPDATE_UI(ID_MOUSEMODE, WXMainFrame::OnMouseModeUI)
1.1.1.13  root      283:        EVT_MENU(ID_KEYBOARD_CONNECT, WXMainFrame::OnKeyboardConnect)
                    284:        EVT_UPDATE_UI(ID_KEYBOARD_CONNECT, WXMainFrame::OnKeyboardConnectUI)
1.1.1.10  root      285:        EVT_MENU_RANGE(0, ID_SUBWIN_END, WXMainFrame::OnWindow)
                    286:        EVT_UPDATE_UI_RANGE(0, ID_SUBWIN_END, WXMainFrame::OnWindowUI)
1.1.1.22  root      287: 
                    288:        EVT_MENU_RANGE(ID_HOSTCOM_DBG_START + 1, ID_HOSTCOM_DBG_NONE,
                    289:                WXMainFrame::OnMenuHostCom)
                    290:        EVT_UPDATE_UI_RANGE(ID_HOSTCOM_DBG_START + 1, ID_HOSTCOM_DBG_NONE,
                    291:                WXMainFrame::OnMenuHostComUI)
                    292: 
1.1.1.4   root      293:        EVT_MENU(wxID_ABOUT, WXMainFrame::OnAbout)
1.1       root      294: wxEND_EVENT_TABLE()
                    295: 
                    296: WXMainFrame::WXMainFrame(wxWindow *parent)
1.1.1.10  root      297:        : inherited(parent, wxID_ANY, "nono", wxDefaultPosition, wxDefaultSize,
1.1.1.6   root      298:                wxDEFAULT_FRAME_STYLE & ~wxMAXIMIZE_BOX & ~wxRESIZE_BORDER)
1.1       root      299: {
1.1.1.15  root      300:        // デバイスを取得
                    301:        power = GetPowerDevice();
                    302:        syncer = GetSyncer();
                    303:        // デバイスを取得。こっちはあるかどうかを調べる
                    304:        keyboard = gMainApp.FindObject<Keyboard>(OBJ_KEYBOARD);
1.1.1.22  root      305:        for (uint i = 0; i < hostnet.size(); i++) {
                    306:                hostnet[i] = gMainApp.FindObject<HostNetDevice>(OBJ_HOSTNET(i));
                    307:        }
                    308:        for (uint i = 0; i < hostcom.size(); i++) {
                    309:                hostcom[i] = gMainApp.FindObject<HostCOMDevice>(OBJ_HOSTCOM(i));
                    310:        }
                    311:        hostcom_dbg = gMainApp.FindObject<HostCOMDevice>(OBJ_HOSTCOM_DBG);
1.1.1.24  root      312:        hostsound = gMainApp.FindObject<HostSoundDevice>(OBJ_HOSTSOUND);
1.1.1.15  root      313: 
1.1.1.18  root      314:        // メイン MPU 名を取得。メニューとタイトルによく出てくるので。
                    315:        // "88xx0" とか "88200" は別処理。
                    316:        mpuname = GetMPUDevice()->GetMPUName();
                    317: 
1.1.1.12  root      318:        // メニュー
1.1       root      319:        wxMenuBar *menubar = new wxMenuBar();
1.1.1.17  root      320:        // メニュー > VM
                    321:        wxMenu *menuVM = new wxMenu();
                    322:        wxItemKind power_button_kind;
                    323:        if (gMainApp.Has(VMCap::LUNA)) {
                    324:                power_button_kind = wxITEM_NORMAL;
                    325:        } else {
                    326:                power_button_kind = wxITEM_CHECK;
                    327:        }
                    328:        menuVM->Append(ID_POWER_BUTTON, _("Push &Power button"),
                    329:                "", power_button_kind);
                    330:        if (gMainApp.IsX68030()) {
                    331:                menuVM->Append(ID_SOFTRESET, _("Send &CTRL+OPT.1+DEL"));
                    332:        }
                    333:        menuVM->Append(ID_RESET_BUTTON, _("Push &Reset button"));
                    334:        if (gMainApp.Has(VMCap::LUNA)) {
                    335:                menuVM->Append(ID_NMI_BUTTON, _("Push &ABORT button"));
                    336:        } else if (gMainApp.Has(VMCap::X68030)) {
                    337:                menuVM->Append(ID_NMI_BUTTON, _("Push &Interrupt button"));
1.1.1.16  root      338:        }
1.1.1.17  root      339:        menuVM->AppendSeparator();
1.1.1.22  root      340:        menuVM->Append(ID_RESTART_VM, _("Re&start VM (For developers)"), "");
1.1.1.17  root      341:        menuVM->AppendSeparator();
                    342:        menuVM->Append(ID_EXIT, _("E&xit"));
                    343:        menubar->Append(menuVM, _("&VM"));
1.1       root      344: 
1.1.1.12  root      345:        // メニュー > 設定
                    346:        wxMenu *menuSet = new wxMenu();
1.1.1.16  root      347:        menuSet->AppendCheckItem(ID_FULL_SPEED, _("Full &Speed Mode"));
1.1.1.15  root      348:        if (keyboard) {
                    349:                wxMenu *menuSetInput = new wxMenu();
                    350:                menuSetInput->AppendRadioItem(ID_INPUT_CHAR, _("By &Character"));
                    351:                menuSetInput->AppendRadioItem(ID_INPUT_JP, _("&JP Keyboard"));
                    352:                menuSet->AppendSubMenu(menuSetInput, _("&Key Input"));
                    353:        }
1.1.1.22  root      354:        for (uint i = 0; i < hostnet.size(); i++) {
                    355:                CreateHostNetMenu(menuSet, i);
                    356:        }
                    357:        for (uint i = 0; i < hostcom.size(); i++) {
                    358:                CreateHostComMenu(menuSet, i);
                    359:        }
1.1.1.24  root      360:        CreateHostSoundMenu(menuSet);
1.1.1.12  root      361:        menubar->Append(menuSet, _("&Setting"));
                    362: 
                    363:        // メニュー > 表示
1.1       root      364:        wxMenu *menuDisplay = new wxMenu();
                    365:        wxMenu *menuViewScale = new wxMenu();
1.1.1.15  root      366:        int user_idx = CreateMainviewScaleTable();
                    367:        for (int i = 0, end = view_scales.size(); i < end; i++) {
                    368:                std::string text;
                    369:                if (i == user_idx) {
                    370:                        // ユーザ指定値は極力指定されたまま表示。
                    371:                        text = string_format("x%g", view_scales[i]);
                    372:                } else {
                    373:                        // プリセットの数値は "0.5", "0.75", "1.0" と都合よく整形したい。
                    374:                        text = string_format("x%.2f", view_scales[i]);
                    375:                        if (text.size() == 5 && text[4] == '0') {
                    376:                                text.pop_back();
                    377:                        }
                    378:                }
                    379:                menuViewScale->AppendRadioItem(ID_SCALE_START + i, text);
                    380:        }
1.1.1.4   root      381:        menuDisplay->AppendSubMenu(menuViewScale, _("&Scale"));
1.1       root      382:        wxMenu *menuFontSize = new wxMenu();
1.1.1.4   root      383:        menuFontSize->AppendRadioItem(ID_FONTSIZE_12, "1&2");
                    384:        menuFontSize->AppendRadioItem(ID_FONTSIZE_16, "1&6");
1.1.1.15  root      385:        menuFontSize->AppendRadioItem(ID_FONTSIZE_24, "2&4");
1.1.1.4   root      386:        menuDisplay->AppendSubMenu(menuFontSize, _("&Font Size"));
1.1.1.5   root      387:        wxMenu *menuMonRate = new wxMenu();
1.1.1.21  root      388:        CreateMonRateTable();
1.1.1.15  root      389:        for (int i = 0, end = monrates.size(); i < end; i++) {
                    390:                std::string text;
                    391:                switch (monrates[i]) {
                    392:                 case 20:       text = _("High (&20Hz)");       break;
                    393:                 case  5:       text = _("Middle (&5Hz)");      break;
                    394:                 case  1:       text = _("Low (&1Hz)");         break;
                    395:                 default:
                    396:                        text = _("User specified") + string_format(" (%dHz)", monrates[i]);
                    397:                        break;
                    398:                }
                    399:                menuMonRate->AppendRadioItem(ID_MONRATE_START + i, text);
                    400:        }
1.1.1.5   root      401:        menuDisplay->AppendSubMenu(menuMonRate, _("&Monitor Speed"));
1.1.1.16  root      402:        menuDisplay->AppendCheckItem(ID_SHOW_STATPANEL, _("Show Status &Panel"));
1.1.1.17  root      403:        menubar->Append(menuDisplay, _("V&iew"));
1.1       root      404: 
1.1.1.12  root      405:        // メニュー > デバイス
1.1       root      406:        wxMenu *menuDevice = new wxMenu();
1.1.1.11  root      407:        CreateRemovableMenu(menuDevice);
1.1.1.15  root      408:        if (keyboard) {
1.1.1.16  root      409:                menuDevice->AppendCheckItem(ID_SUBWIN_SOFTKEY, _("Software &Keyboard"));
                    410:                menuDevice->AppendCheckItem(ID_MOUSEMODE, _("&Mouse Mode\tCTRL+F12"));
1.1.1.15  root      411:        }
1.1.1.16  root      412:        if (gMainApp.FindObject(OBJ_LCD)) {
                    413:                menuDevice->AppendCheckItem(ID_SUBWIN_LCDPANEL, _("Front &LCD"));
1.1.1.5   root      414:        }
1.1.1.16  root      415:        if (gMainApp.FindObject(OBJ_DIPSW)) {
                    416:                menuDevice->AppendCheckItem(ID_SUBWIN_DIPSW, "&DIPSW");
1.1.1.15  root      417:        }
1.1.1.17  root      418:        // 今はこれしかないので
1.1.1.15  root      419:        if (keyboard) {
1.1.1.17  root      420:                wxMenu *menuOper = new wxMenu();
1.1.1.16  root      421:                menuOper->AppendCheckItem(ID_KEYBOARD_CONNECT, _("Connect &Keyboard"));
1.1.1.17  root      422:                menuDevice->AppendSubMenu(menuOper, _("&Operation"));
1.1.1.15  root      423:        }
1.1.1.21  root      424:        // アイテムが何もなければ本当はメニューバーのアイテムを無効にしたいが、
                    425:        // それは出来ないっぽい。何かアイテムを置かないと変なパネルが出たりする。
                    426:        if (menuDevice->GetMenuItems().IsEmpty()) {
                    427:                // TRANSLATORS: This is "Device > Nothing" in the menubar.
                    428:                menuDevice->Append(ID_DEVICE_EMPTY, _("Nothing"));
                    429:                menuDevice->Enable(ID_DEVICE_EMPTY, false);
                    430:        }
1.1.1.4   root      431:        menubar->Append(menuDevice, _("&Device"));
                    432: 
1.1.1.14  root      433: #define AppendIfSeparator(menu, vmcap_)        do { \
                    434:        if (gMainApp.Has(vmcap_)) { \
1.1.1.10  root      435:                (menu)->AppendSeparator(); \
1.1.1.4   root      436:        } \
                    437: } while (0)
1.1       root      438: 
1.1.1.12  root      439:        // メニュー > モニター
1.1       root      440:        wxMenu *menuMonitor = new wxMenu();
1.1.1.10  root      441:        AppendIf(menuMonitor, ID_MONITOR_SCHEDULER,     _("&Scheduler"));
1.1.1.5   root      442: 
1.1.1.4   root      443:        wxMenu *menuMPU = new wxMenu();
1.1.1.22  root      444:        AppendIf(menuMPU, ID_MONITOR_MPUREG,            _("&Registers"));
1.1.1.10  root      445:        AppendIf(menuMPU, ID_MONITOR_MPUATC,              "&ATC");
1.1.1.25! root      446:        AppendIf(menuMPU, ID_SUBWIN_MPUPT,                      _("&Page Table"));
1.1.1.22  root      447:        AppendIf(menuMPU, ID_MONITOR_MPUCACHE,          _("&Caches"));
                    448:        AppendIf(menuMPU, ID_MONITOR_INTERRUPT,         _("&Interrupts"));
1.1.1.14  root      449:        AppendIfSeparator(menuMPU, VMCap::M88K);
1.1.1.22  root      450:        AppendIf(menuMPU, ID_MONITOR_CMMU7,
                    451:                                                                "CMMU#7" + _("(Inst)") + " " + _("Registers"));
1.1.1.10  root      452:        AppendIf(menuMPU, ID_MONITOR_ATC7,                        "ATC#7");
                    453:        AppendIf(menuMPU, ID_SUBWIN_CACHE7,                     _("Cache") + "#7");
1.1.1.14  root      454:        AppendIfSeparator(menuMPU, VMCap::M88K);
1.1.1.22  root      455:        AppendIf(menuMPU, ID_MONITOR_CMMU6,
                    456:                                                                "CMMU#6" + _("(Data)") + " " + _("Registers"));
1.1.1.10  root      457:        AppendIf(menuMPU, ID_MONITOR_ATC6,                        "ATC#6");
                    458:        AppendIf(menuMPU, ID_SUBWIN_CACHE6,                     _("Cache") + "#6");
1.1.1.15  root      459:        menuMPU->AppendSeparator();
                    460:        // MEMDUMPn のラベルは UpdateUI で書き直すのでここでは適当に
                    461:        // 埋めておく。(empty だと怒られる)
1.1.1.18  root      462:        for (uint i = 0; i < MAX_MEMDUMP_MONITOR; i++) {
1.1.1.15  root      463:                AppendIf(menuMPU, ID_MONITOR_MEMDUMP(i), "memdump");
                    464:        }
                    465:        menuMPU->AppendSeparator();
                    466:        AppendIf(menuMPU, ID_SUBWIN_BRHIST,                     _("Branch &History"));
                    467:        AppendIf(menuMPU, ID_SUBWIN_EXHIST,                     _("&Exception History"));
                    468:        AppendIf(menuMPU, ID_SUBWIN_VECTOR,                     _("&Vector Table"));
1.1.1.19  root      469:        wxString mpulabel;
                    470:        if (gMainApp.Has(VMCap::M68K)) {
                    471:                mpulabel = "&MPU(" + mpuname + ")";
1.1.1.22  root      472:        } else if (gMainApp.Has(VMCap::M88K)) {
1.1.1.19  root      473:                mpulabel = "&MPU(MC88xx0)";
1.1.1.22  root      474:        } else {
                    475:                mpulabel = "&MPU";
1.1.1.19  root      476:        }
                    477:        menuMonitor->AppendSubMenu(menuMPU, mpulabel);
1.1.1.15  root      478: 
                    479:        if (gMainApp.Has(VMCap::LUNA)) {
                    480:                wxMenu *menuXP = new wxMenu();
1.1.1.22  root      481:                AppendIf(menuXP, ID_MONITOR_XPREG,              _("&Registers"));
                    482:                AppendIf(menuXP, ID_MONITOR_XPINTR,             _("&Interrupts"));
1.1.1.15  root      483:                AppendIf(menuXP, ID_MONITOR_XPIO,               _("Internal &Devices"));
1.1.1.22  root      484:                AppendIf(menuXP, ID_MONITOR_XPASCI,               "&ASCI");
1.1.1.15  root      485:                menuXP->AppendSeparator();
1.1.1.18  root      486:                for (uint i = 0; i < MAX_XPMEMDUMP_MONITOR; i++) {
1.1.1.15  root      487:                        AppendIf(menuXP, ID_MONITOR_XPMEMDUMP(i), "memdump");
                    488:                }
                    489:                menuXP->AppendSeparator();
                    490:                AppendIf(menuXP, ID_SUBWIN_XPBRHIST,    _("Branch &History"));
                    491:                AppendIf(menuXP, ID_SUBWIN_XPEXHIST,    _("&Exception History"));
                    492:                menuMonitor->AppendSubMenu(menuXP, "XP(HD647180)");
                    493:        }
1.1.1.10  root      494: 
                    495:        // MONITOR_RTC は X68k の RTC、LUNA では MONITOR_MK48T02 だが今の所
                    496:        // NVRAM 側のことは表示してないのでラベルも RTC にしてある。
1.1.1.15  root      497:        wxMenu *menuDev = new wxMenu();
1.1.1.16  root      498:        // X68030 は基本が 24bit のほうなので区別しておく。
                    499:        if (gMainApp.IsX68030()) {
                    500:                AppendIf(menuDev, ID_MONITOR_MAINBUS,   _("Device Map (32bit space)"));
                    501:                AppendIf(menuDev, ID_SUBWIN_X68KIO,             _("Device Map (24bit space)"));
                    502:        } else {
                    503:                AppendIf(menuDev, ID_MONITOR_MAINBUS,   _("Device Map"));
                    504:        }
1.1.1.17  root      505:        AppendIf(menuDev, ID_SUBWIN_NEWSIO,                     _("Device Map (NEWS)"));
                    506:        AppendIf(menuDev, ID_MONITOR_ACCSTAT,           _("Access Status"));
1.1.1.16  root      507:        menuDev->AppendSeparator();
1.1.1.15  root      508:        AppendIf(menuDev, ID_MONITOR_SPC,                         "SPC");
                    509:        AppendIf(menuDev, ID_MONITOR_SCSIDEVS,          _("SCSI Devices"));
                    510:        AppendIf(menuDev, ID_MONITOR_RTC,                         "RTC");
                    511:        AppendIf(menuDev, ID_MONITOR_MK48T02,             "RTC");
                    512:        AppendIf(menuDev, ID_MONITOR_DMAC,                        "DMAC");
                    513:        AppendIf(menuDev, ID_MONITOR_MFP,                         "MFP");
                    514:        AppendIf(menuDev, ID_MONITOR_FDC,                         "FDC");
                    515:        AppendIf(menuDev, ID_MONITOR_SCC,                         "SCC");
                    516:        AppendIf(menuDev, ID_MONITOR_SIO,                         "SIO");
                    517:        AppendIf(menuDev, ID_MONITOR_PIO,                         "PIO0/PIO1");
                    518:        AppendIf(menuDev, ID_MONITOR_KEYBOARD,          _("Keyboard/Mouse"));
                    519:        AppendIf(menuDev, ID_MONITOR_LANCE,                       "Lance");
1.1.1.16  root      520:        AppendIf(menuDev, ID_MONITOR_NEREID,              "Nereid");
1.1.1.22  root      521:        for (uint i = 0; i < hostnet.size(); i++) {
1.1.1.18  root      522:                uint id = ID_MONITOR_RTL8019AS(i);
1.1.1.22  root      523:                wxString name = string_format("Nereid#%u (RTL8019AS)", i);
1.1.1.17  root      524:                AppendIf(menuDev, id, name);
1.1.1.16  root      525:        }
1.1.1.17  root      526:        AppendIf(menuDev, ID_MONITOR_SYSPORT,           _("System Port"));
                    527:        AppendIf(menuDev, ID_MONITOR_AREASET,           _("Areaset"));
1.1.1.15  root      528:        AppendIf(menuDev, ID_MONITOR_LCD,                         "LCD");
                    529:        AppendIf(menuDev, ID_MONITOR_SYSCLK,            _("System Clock"));
1.1.1.18  root      530:        for (uint i = 0; i < 8; i++) {
                    531:                uint id = ID_MONITOR_VIRTIO_BLOCK(i);
                    532:                wxString name = _("VirtIO Block") + string_format(" #%u", i);
1.1.1.17  root      533:                AppendIf(menuDev, id, name);
                    534:        }
                    535:        AppendIf(menuDev, ID_MONITOR_VIRTIO_NET,        _("VirtIO Network"));
1.1.1.21  root      536:        AppendIf(menuDev, ID_MONITOR_VIRTIO_SCSI,         "VirtIO SCSI");
1.1.1.18  root      537:        AppendIf(menuDev, ID_MONITOR_VIRTIO_ENTROPY,_("VirtIO Entropy"));
1.1.1.23  root      538:        AppendIf(menuDev, ID_MONITOR_CRTC,                      _("CRTC and Video Controller"));
1.1.1.15  root      539:        AppendIf(menuDev, ID_MONITOR_LUNAVC,            _("Video Control"));
                    540:        AppendIf(menuDev, ID_MONITOR_BT45x,                       "Bt454/458");
                    541:        AppendIf(menuDev, ID_SUBWIN_PALETTE,            _("Palette Colormap"));
                    542:        AppendIf(menuDev, ID_MONITOR_RENDERER,          _("Renderer"));
                    543:        AppendIf(menuDev, ID_SUBWIN_LUNAFB,                     _("Bitmap Plane"));
1.1.1.23  root      544:        AppendIf(menuDev, ID_SUBWIN_TVRAM,                      _("Text Screen"));
                    545:        AppendIf(menuDev, ID_SUBWIN_GVRAM,                      _("Graphic Screen"));
1.1.1.24  root      546:        AppendIf(menuDev, ID_MONITOR_SOUND,                     _("Sound"));
1.1.1.18  root      547:        AppendIf(menuDev, ID_MONITOR_SSG,                         "SSG");
1.1.1.24  root      548:        AppendIf(menuDev, ID_MONITOR_ADPCM,                       "ADPCM");
1.1.1.15  root      549:        AppendIf(menuDev, ID_MONITOR_ROMCONS,           _("ROM Console (provisional)"));
                    550:        AppendIf(menuDev, ID_SUBWIN_ROM,                          "ROM");
1.1.1.16  root      551:        // LUNA はバスが複数あるので Mainbus Device とする。
                    552:        // 他の機種ではメインて言われても困るので Device とする。
                    553:        if (gMainApp.Has(VMCap::LUNA)) {
1.1.1.22  root      554:                menuMonitor->AppendSubMenu(menuDev, _("Mainbus De&vices"));
1.1.1.16  root      555:        } else {
1.1.1.22  root      556:                menuMonitor->AppendSubMenu(menuDev, _("De&vices"));
1.1.1.16  root      557:        }
1.1.1.5   root      558: 
                    559:        wxMenu *menuHost = new wxMenu();
1.1.1.10  root      560:        AppendIf(menuHost, ID_MONITOR_WXHOSTINFO,       _("Host &Information"));
1.1.1.24  root      561:        AppendIf(menuHost, ID_SUBWIN_THREADS,           _("Thread Status"));
1.1.1.22  root      562:        for (uint i = 0; i < hostnet.size(); i++) {
                    563:                uint id = ID_MONITOR_HOSTNET(i);
                    564:                if (gMonitorManager->Find(id)) {
                    565:                        menuHost->AppendCheckItem(id, GetHostNetLabel(i));
1.1.1.16  root      566:                }
                    567:        }
1.1.1.20  root      568:        AppendIf(menuHost, ID_MONITOR_SLIRP,            _("SLIRP Internal States"));
1.1.1.22  root      569:        for (uint i = 0; i < hostcom.size(); i++) {
                    570:                uint id = ID_MONITOR_HOSTCOM(i);
                    571:                if (gMonitorManager->Find(id)) {
                    572:                        menuHost->AppendCheckItem(id, GetHostComLabel(i));
                    573:                }
                    574:        }
1.1.1.24  root      575:        AppendIf(menuHost, ID_MONITOR_HOSTSOUND,        _("Host Sound"));
1.1.1.5   root      576:        menuMonitor->AppendSubMenu(menuHost, _("&Host"));
                    577: 
1.1.1.15  root      578:        wxMenu *menuDebug = new wxMenu();
1.1.1.23  root      579:        AppendIf(menuDebug, ID_MONITOR_LOG,                     _("&Log"));
1.1.1.22  root      580:        AppendIf(menuDebug, ID_MONITOR_BREAKPOINT,      _("&Breakpoints"));
1.1.1.15  root      581:        menuDebug->AppendSeparator();
                    582:        AppendIf(menuDebug, ID_SUBWIN_LOGSETTING,       _("Log Level &Setting"));
1.1.1.22  root      583:        CreateHostComMenu(menuDebug, -1);
1.1.1.15  root      584:        menuMonitor->AppendSubMenu(menuDebug, _("&Debug"));
                    585: 
1.1.1.4   root      586:        menubar->Append(menuMonitor, _("&Monitor"));
                    587: 
1.1.1.12  root      588:        // メニュー > ヘルプ
1.1.1.4   root      589: #if defined(__WXOSX__)
                    590:        // OSX では wxID_ABOUT はリンゴメニューに入れるしきたりになっている。
                    591:        // Append() すると Quit より下に来てしまうので、Prepend() で上に追加。
                    592:        // 今のところヘルプメニューから About ダイアログを抜くとメニューが空に
                    593:        // なってしまうので、ヘルプメニューの追加ごと抑制する。
                    594:        menubar->OSXGetAppleMenu()->Prepend(wxID_ABOUT, _("About nono"));
                    595: #else
                    596:        wxMenu *menuHelp = new wxMenu();
                    597:        menuHelp->Append(wxID_ABOUT, _("About nono"));
                    598:        menubar->Append(menuHelp, _("&Help"));
                    599: #endif
                    600: 
1.1       root      601:        SetMenuBar(menubar);
                    602: 
1.1.1.18  root      603:        frame_title = wxString("nono");
1.1.1.17  root      604:        const char *vmname = gMainApp.GetVMName();
                    605:        if (vmname) {
1.1.1.18  root      606:                frame_title += '(';
                    607:                frame_title += wxString(vmname);
                    608:                frame_title += ')';
1.1       root      609:        }
1.1.1.22  root      610:        SetMyTitle(false);
1.1       root      611: 
                    612:        // UpdateUI イベントは Idle 時に時折チェックされるらしいが、
                    613:        // (メインビューとサブウィンドウを合わせた) タイマーイベントの粒度が
                    614:        // 小さいためか、秒間120回とかいうレベルで UpdateUIEvent が飛んでくる
                    615:        // っぽい (全タイマーをとめたら治る模様)。
                    616:        // さすがにそんなに来られても気持ち悪いのと、どうせメニュー開いた瞬間
                    617:        // 表示しようとする前には一度飛んでくるのだから、アイドル時のチェックは
                    618:        // いらない気がする。間隔広げておいても、ぱっと見副作用はなさそうだけど
                    619:        // 念のため事象が分かりやすいように 10秒くらいにしておく。
                    620:        wxUpdateUIEvent::SetUpdateInterval(10000);
                    621: 
1.1.1.15  root      622:        // WXStatusPanel コンストラクタが mainview を参照するので
                    623:        // mainview のほうを先に作成すること。
                    624:        mainview = new WXMainView(this);
                    625:        statuspanel = new WXStatusPanel(this);
1.1.1.22  root      626:        // 空き地用のパネル。
                    627:        spaceL = new WXBitmapPanel(this);
                    628:        spaceR = new WXBitmapPanel(this);
                    629:        spaceL->Hide();
                    630:        spaceR->Hide();
                    631: 
                    632:        // Sizer 使わず自前でレイアウトする。
                    633:        SetAutoLayout(true);
                    634:        // mainview のスケール、statuspanel のフォントサイズはいずれも
                    635:        // コンストラクタの時点で初期状態がセットされている。
1.1       root      636: 
1.1.1.9   root      637:        // SHOW イベントを最初にも一度起こしたいため
                    638:        // ステータスパネルを一旦非表示にする (これで SHOW(false) イベントが飛ぶ)
1.1.1.15  root      639:        statuspanel->Hide();
1.1.1.25! root      640:        if (gConfig->Find("show-statuspanel").AsBool()) {
1.1.1.9   root      641:                // 必要なら改めて表示 (これで SHOW(true) イベントが飛ぶ)
1.1.1.15  root      642:                statuspanel->Show();
1.1.1.9   root      643:        }
                    644: 
1.1.1.22  root      645:        Fit();
1.1       root      646: 
1.1.1.4   root      647:        // Activate イベントは、このトップレベルウィンドウにウィンドウフォーカスが
                    648:        // 来た or 外れたことを示すので、wxFrame (というかたぶん wxTopLevelWindow)
                    649:        // を継承している WXMainFrameに飛んでくるのだが、処理の都合上 WXMainView で
                    650:        // 扱いたいので、そちらに回す。
1.1.1.25! root      651:        Bind(wxEVT_ACTIVATE, &WXMainView::OnActivate, mainview);
1.1.1.4   root      652: 
1.1.1.11  root      653:        // ウィンドウ表示後に続きの処理をするための単発アイドルイベント。
1.1.1.25! root      654:        // こっちは Disconnect() するので Bind() は使えない。
1.1.1.11  root      655:        Connect(wxEVT_IDLE, wxIdleEventHandler(WXMainFrame::OnIdle));
                    656: 
                    657:        // VM からの通知を接続
1.1.1.13  root      658:        WXUIMessage::Connect(UIMessage::APPEXIT, this,
1.1.1.11  root      659:                wxCommandEventHandler(WXMainFrame::OnExit));
                    660:        WXUIMessage::Connect(UIMessage::SCSI_MEDIA_FAILED, this,
1.1.1.14  root      661:                wxCommandEventHandler(WXMainFrame::OnInsertFailed));
                    662:        WXUIMessage::Connect(UIMessage::FDD_MEDIA_FAILED, this,
                    663:                wxCommandEventHandler(WXMainFrame::OnInsertFailed));
1.1.1.22  root      664:        WXUIMessage::Connect(UIMessage::HOSTNET_FAILED, this,
                    665:                wxCommandEventHandler(WXMainFrame::OnHostNetFailed));
                    666:        WXUIMessage::Connect(UIMessage::HOSTCOM_FAILED, this,
                    667:                wxCommandEventHandler(WXMainFrame::OnHostComFailed));
1.1.1.24  root      668:        WXUIMessage::Connect(UIMessage::HOSTSOUND_FAILED, this,
                    669:                wxCommandEventHandler(WXMainFrame::OnHostSoundFailed));
1.1.1.15  root      670:        if (gMainApp.Has(VMCap::M68K)) {
1.1.1.11  root      671:                WXUIMessage::Connect(UIMessage::HALT, this,
                    672:                        wxCommandEventHandler(WXMainFrame::OnHaltNotify));
                    673:        }
1.1       root      674: }
                    675: 
                    676: WXMainFrame::~WXMainFrame()
                    677: {
1.1.1.15  root      678:        WXUIMessage::Disconnect(UIMessage::APPEXIT, this,
1.1.1.13  root      679:                wxCommandEventHandler(WXMainFrame::OnExit));
1.1.1.15  root      680:        WXUIMessage::Disconnect(UIMessage::SCSI_MEDIA_FAILED, this,
1.1.1.14  root      681:                wxCommandEventHandler(WXMainFrame::OnInsertFailed));
1.1.1.15  root      682:        WXUIMessage::Disconnect(UIMessage::FDD_MEDIA_FAILED, this,
1.1.1.14  root      683:                wxCommandEventHandler(WXMainFrame::OnInsertFailed));
1.1.1.22  root      684:        WXUIMessage::Disconnect(UIMessage::HOSTNET_FAILED, this,
                    685:                wxCommandEventHandler(WXMainFrame::OnHostNetFailed));
                    686:        WXUIMessage::Disconnect(UIMessage::HOSTCOM_FAILED, this,
                    687:                wxCommandEventHandler(WXMainFrame::OnHostComFailed));
1.1.1.24  root      688:        WXUIMessage::Disconnect(UIMessage::HOSTSOUND_FAILED, this,
                    689:                wxCommandEventHandler(WXMainFrame::OnHostSoundFailed));
1.1.1.15  root      690:        if (gMainApp.Has(VMCap::M68K)) {
                    691:                WXUIMessage::Disconnect(UIMessage::HALT, this,
1.1.1.13  root      692:                        wxCommandEventHandler(WXMainFrame::OnHaltNotify));
                    693:        }
1.1       root      694: }
                    695: 
1.1.1.17  root      696: // 指定のモニタ/サブウィンドウがあればメニューに追加する
                    697: void
                    698: WXMainFrame::AppendIf(wxMenu *menu, int id, const wxString& label)
                    699: {
                    700:        if (id >= ID_SUBWIN_START) {
                    701:                // サブウィンドウなら機種から判定する。機種情報は必ず持っているため。
                    702:                // 一方、サブウィンドウは必ずしもモニタと紐付いているわけではないので
                    703:                // モニタマネージャに問い合わせる方法は使えない。
                    704:                VMCap vmcap = gMonitorManager->GetVMCap(id);
                    705:                if (gMainApp.Has(vmcap)) {
                    706:                        menu->AppendCheckItem(id, label);
                    707:                }
                    708:        } else {
                    709:                // モニタならインスタンスの有無で判定する。
                    710:                // モニタは機種情報は持ってないが、存在すべきインスタンスはこの時点で
                    711:                // すべて出揃っているため。
                    712:                if (gMonitorManager->Find(id)) {
                    713:                        menu->AppendCheckItem(id, label);
                    714:                }
                    715:        }
                    716: }
                    717: 
1.1.1.22  root      718: // HostNet 用のメニューを作成して menuSet に追加する。
                    719: void
                    720: WXMainFrame::CreateHostNetMenu(wxMenu *menuSet, uint unit)
                    721: {
                    722:        if (hostnet[unit] == NULL) {
                    723:                return;
                    724:        }
                    725: 
                    726:        int offset;
                    727:        if (unit == 0) {
                    728:                offset = ID_HOSTNET0_START - ID_HOSTNET0_START;
                    729:        } else {
                    730:                offset = ID_HOSTNET1_START - ID_HOSTNET0_START;
                    731:        }
                    732: 
                    733:        wxMenu *menu = new wxMenu();
                    734: #if defined(HAVE_HOSTNET_SLIRP)
                    735:        menu->AppendRadioItem(offset + ID_HOSTNET0_USERMODE, "&usermode");
                    736: #endif
                    737: #if defined(HAVE_HOSTNET_TAP)
                    738:        menu->AppendRadioItem(offset + ID_HOSTNET0_TAP, "&tap");
                    739: #endif
                    740: #if defined(HAVE_HOSTNET_BPF)
                    741:        menu->AppendRadioItem(offset + ID_HOSTNET0_BPF, "&bpf");
                    742: #endif
                    743: #if defined(HAVE_HOSTNET_AFPACKET)
                    744:        menu->AppendRadioItem(offset + ID_HOSTNET0_AFPACKET, "&afpacket");
                    745: #endif
                    746:        menu->AppendRadioItem(offset + ID_HOSTNET0_NONE, "&none");
                    747:        menuSet->AppendSubMenu(menu, GetHostNetLabel(unit));
                    748: }
                    749: 
                    750: // HostCOM 用のメニューを作成して menuSet に追加する。
                    751: // 引数の n は COM<n>。ただし負数ならデバッガ用。
                    752: void
                    753: WXMainFrame::CreateHostComMenu(wxMenu *menuSet, int n)
                    754: {
                    755:        HostCOMDevice *host;
                    756: 
                    757:        // デバッガ用は配列では最後。
                    758:        if (n < 0) {
                    759:                host = hostcom_dbg;
                    760:        } else {
                    761:                host = hostcom[n];
                    762:        }
                    763: 
                    764:        if (host == NULL) {
                    765:                return;
                    766:        }
                    767: 
                    768:        int offset;
                    769:        if (n == 0) {
                    770:                offset = ID_HOSTCOM0_START - ID_HOSTCOM0_START;
                    771:        } else if (n == 1) {
                    772:                offset = ID_HOSTCOM1_START - ID_HOSTCOM0_START;
                    773:        } else if (n == 2) {
                    774:                offset = ID_HOSTCOM2_START - ID_HOSTCOM0_START;
                    775:        } else {
                    776:                offset = ID_HOSTCOM_DBG_START - ID_HOSTCOM0_START;
                    777:        }
                    778: 
                    779:        wxMenu *menu = new wxMenu();
                    780:        menu->AppendRadioItem(offset + ID_HOSTCOM0_TCP, "&tcp");
                    781:        menu->AppendRadioItem(offset + ID_HOSTCOM0_STDIO, "&stdio");
                    782:        if (n >= 0 && gMainApp.FindObject(OBJ_CONSOLE)) {
                    783:                menu->AppendRadioItem(offset + ID_HOSTCOM0_CONSOLE, "&console");
                    784:        }
                    785:        menu->AppendRadioItem(offset + ID_HOSTCOM0_NONE, "&none");
                    786:        wxString name;
                    787:        if (n >= 0) {
                    788:                name = GetHostComLabel(n);
                    789:        } else {
                    790:                name = _("&Debugger");
                    791:        }
                    792:        menuSet->AppendSubMenu(menu, name);
                    793: }
                    794: 
1.1.1.24  root      795: // HostSound 用のメニューを作成して menuSet に追加する。
                    796: void
                    797: WXMainFrame::CreateHostSoundMenu(wxMenu *menuSet)
                    798: {
                    799:        if (hostsound == NULL) {
                    800:                return;
                    801:        }
                    802: 
                    803:        wxMenu *menu = new wxMenu();
                    804: #if defined(HAVE_HOSTSOUND_NETBSD)
                    805:        menu->AppendRadioItem(ID_HOSTSOUND_NETBSD, "&netbsd");
                    806: #endif
                    807: #if defined(HAVE_HOSTSOUND_SNDIO)
                    808:        menu->AppendRadioItem(ID_HOSTSOUND_SNDIO, "&sndio");
                    809: #endif
                    810: #if defined(HAVE_HOSTSOUND_ALSA)
                    811:        menu->AppendRadioItem(ID_HOSTSOUND_ALSA, "&alsa");
                    812: #endif
                    813:        menu->AppendRadioItem(ID_HOSTSOUND_WAV, "&wav");
                    814:        menu->AppendRadioItem(ID_HOSTSOUND_NONE, "&none");
                    815:        menuSet->AppendSubMenu(menu, "HostSound");
                    816: }
                    817: 
1.1.1.11  root      818: // リムーバブルデバイス用のメニューを作成して menuDevice に追加する
                    819: void
                    820: WXMainFrame::CreateRemovableMenu(wxMenu *menuDevice)
                    821: {
                    822:        wxMenu *menu;
                    823:        bool added = false;
                    824: 
                    825:        // FD
1.1.1.15  root      826:        for (int unit = 0; unit < FDCDevice::MAX_DRIVE; unit++) {
                    827:                fdd_array[unit] = gMainApp.FindObject<FDDDevice>(OBJ_FDD(unit));
                    828:                if (fdd_array[unit]) {
1.1.1.14  root      829:                        menu = CreateFDMenu(unit);
                    830:                        std::string label = string_format("FD%d", unit);
                    831:                        menuDevice->AppendSubMenu(menu, label);
                    832:                        added = true;
                    833:                }
                    834:        }
1.1.1.11  root      835: 
                    836:        // CD, MO
1.1.1.21  root      837:        auto scsi = gMainApp.FindObject<SCSIDomain>(OBJ_SCSI);
1.1.1.18  root      838:        if (scsi) {
1.1.1.15  root      839:                for (int id = 0; id < 8; id++) {
1.1.1.18  root      840:                        scsidev[id] = scsi->GetTarget(id);
1.1.1.15  root      841:                        if (scsidev[id]) {
                    842:                                menu = CreateSCSIRemovableMenu(id);
                    843:                                if (menu) {
                    844:                                        std::string label = string_format("%s (ID%d)",
                    845:                                                SCSI::GetDevTypeName(scsidev[id]->GetDevType()), id);
                    846:                                        menuDevice->AppendSubMenu(menu, label);
                    847:                                        added = true;
                    848:                                }
1.1.1.11  root      849:                        }
                    850:                }
                    851:        }
                    852: 
                    853:        // 1つでも追加したらセパレータ
                    854:        if (added) {
                    855:                menuDevice->AppendSeparator();
                    856:        }
                    857: }
                    858: 
1.1.1.14  root      859: // FD 用のメニューを作成して返す。
                    860: wxMenu *
                    861: WXMainFrame::CreateFDMenu(int unit) const
                    862: {
                    863:        wxMenu *menu = new wxMenu();
                    864:        // Insert の実際のラベルは UpdateUI でセットする。
                    865:        // ただし何か入れておかないといけないので適当にセット。
                    866:        menu->Append(ID_FD_INSERT(unit), "Insert", "");
                    867:        // XXX 未実装
                    868:        //menu->Append(ID_FD_MISINSERT(unit), _("Insert incorrectly"), "");
                    869:        menu->Append(ID_FD_EJECT(unit), _("&Eject"), "");
                    870:        menu->Append(ID_FD_FORCE(unit), _("&Force Eject"), "");
                    871:        return menu;
                    872: }
                    873: 
1.1.1.11  root      874: // SCSI リムーバブルデバイス用のメニューを作成して返す。
                    875: // id はデバイスが接続されていること (リムーバブルデバイスであるかは問わない)。
                    876: // リムーバブルデバイスでなければ NULL を返す。
                    877: // メニューバーとポップアップメニュー共通。
                    878: wxMenu *
                    879: WXMainFrame::CreateSCSIRemovableMenu(uint id) const
                    880: {
                    881:        const auto *dev = scsidev[id];
                    882:        assert(dev);
                    883: 
                    884:        switch (dev->GetDevType()) {
                    885:         case SCSI::DevType::CD:
                    886:         case SCSI::DevType::MO:
                    887:         {
                    888:                wxMenu *menu = new wxMenu();
                    889:                // Insert の実際のラベルは UpdateUI でセットする。
                    890:                // ただし何か入れておかないといけないので適当にセット。
                    891:                menu->Append(ID_CD_INSERT(id), "Insert", "");
                    892:                menu->Append(ID_CD_EJECT(id), _("&Eject"), "");
                    893:                menu->Append(ID_CD_FORCE(id), _("&Force Eject"), "");
                    894:                return menu;
                    895:         }
                    896:         default:
                    897:                return NULL;
                    898:        }
                    899: }
                    900: 
1.1.1.12  root      901: // (設定反映などの) 初期化。
                    902: // 成功すれば true、失敗すれば false を返す。
                    903: bool
                    904: WXMainFrame::Init()
                    905: {
1.1.1.15  root      906:        if (!mainview->Init()) {
1.1.1.12  root      907:                return false;
                    908:        }
                    909: 
1.1.1.23  root      910:        statuspanel->Init();
                    911: 
1.1.1.12  root      912:        return true;
                    913: }
                    914: 
1.1.1.22  root      915: void
                    916: WXMainFrame::Fit()
1.1.1.13  root      917: {
1.1.1.22  root      918:        wxSize statsize(0, 0);
                    919:        if (statuspanel->IsShown()) {
                    920:                statsize = statuspanel->GetMinSize();
1.1.1.13  root      921:        }
1.1.1.22  root      922:        const wxSize& viewsize = mainview->GetSize();
1.1.1.13  root      923: 
1.1.1.22  root      924:        wxSize size(std::max(statsize.x, viewsize.x), statsize.y + viewsize.y);
                    925:        SetClientSize(size);
                    926: }
                    927: 
                    928: bool
                    929: WXMainFrame::Layout()
                    930: {
                    931:        const wxSize& client = GetClientSize();
1.1.1.13  root      932: 
1.1.1.22  root      933:        wxSize statsize(0, 0);
1.1.1.15  root      934:        if (statuspanel->IsShown()) {
1.1.1.22  root      935:                statsize = statuspanel->GetSize();
                    936:                statuspanel->SetSize(0, 0, client.x, statsize.y);
1.1.1.13  root      937:        }
                    938: 
1.1.1.22  root      939:        // メインビューの方が小さければ両側に空き地を入れてセンタリングする。
                    940:        wxSize viewsize = mainview->GetSize();
                    941:        if (viewsize.x < client.x) {
                    942:                int view_x = (client.x - viewsize.x) / 2;
                    943:                spaceL->SetSize(0, statsize.y, view_x, viewsize.y);
                    944:                spaceL->Show();
                    945:                mainview->SetSize(view_x, statsize.y, viewsize.x, viewsize.y);
                    946:                int x = view_x + viewsize.x;
                    947:                spaceR->SetSize(x, statsize.y, client.x - x, viewsize.y);
                    948:                spaceR->Show();
                    949:        } else {
                    950:                mainview->SetPosition(wxPoint(0, statsize.y));
                    951:                spaceL->Hide();
                    952:                spaceR->Hide();
1.1.1.13  root      953:        }
                    954: 
                    955:        return true;
                    956: }
                    957: 
1.1.1.11  root      958: // ウィンドウ作成イベント (を実現するためここではアイドルイベントを使う)
1.1.1.10  root      959: //
1.1.1.11  root      960: // 初期化(っぽい)もののうちコンストラクタでは早すぎるものは、コンストラクタ
                    961: // 直後に起こすこのイベント内で処理する。使えそうなイベントはいくつかあり、
                    962: // 自前の Create (今はもうない) -> WindowCreate -> Idle -> Paint の順で
                    963: // 起きるようだ。
                    964: // 自前の Create 時点では早すぎて、ここでサブウィンドウを作成するとサイズが 0
                    965: // みたいなウィンドウが一瞬出来てしまい GTK のワーニングが出る (その後サイズを
                    966: // 矯正すれば表示自体は出来る)。
1.1.1.10  root      967: // WindowCreate 時点ではその問題は起きないが、ここはまだメインウィンドウ表示
                    968: // 前なので、ここでサブウィンドウを表示した後メインウィンドウを表示すると
                    969: // (ウィンドウマネージャにもよるかもだが)、メインウィンドウがサブウィンドウを
                    970: // 隠してしまう。
1.1.1.11  root      971: // Idle イベント時点まで来ると上の2つの問題は回避できるようだ。
                    972: // Paint イベントの時点でもタイミング的には問題ないが、環境によっては(?)
                    973: // このイベント自体が飛んで来ないことがあるようだ。WXMainFrame の再描画は
1.1.1.13  root      974: // 子コントロールが行っており、そのため WXMainFrame 自身が再描画しなければ
                    975: // ならない領域は存在しないからかも知れないが詳細未調査。
1.1.1.11  root      976: void
                    977: WXMainFrame::OnIdle(wxIdleEvent& ev)
1.1       root      978: {
1.1.1.11  root      979:        // UIMessage の処理を開始する。
                    980:        // 少なくとも WXMainFrame のコンストラクタが完了した後のほうがいいはず。
1.1.1.23  root      981:        gMainApp.GetUIMessage()->StartUIMessage(&WXUIMessage::Process);
1.1.1.11  root      982: 
1.1       root      983:        // ウィンドウを表示
1.1.1.10  root      984:        for (int i = 0; i < subwindow_start.size(); i++) {
                    985:                if (subwindow_start[i]) {
1.1       root      986:                        DoWindow(i, true);
                    987:                }
                    988:        }
                    989: 
1.1.1.9   root      990:        // 電源投入
1.1.1.17  root      991:        power->PushPowerButton();
1.1.1.10  root      992: 
                    993:        // 一度処理したら、このイベントを外す
1.1.1.11  root      994:        Disconnect(wxEVT_IDLE, wxIdleEventHandler(WXMainFrame::OnIdle));
1.1       root      995: }
                    996: 
1.1.1.3   root      997: // ウィンドウクローズイベント
                    998: void
                    999: WXMainFrame::OnClose(wxCloseEvent& event)
                   1000: {
1.1.1.23  root     1001:        // UIMessage を停止
                   1002:        gMainApp.GetUIMessage()->StopUIMessage();
1.1.1.9   root     1003:        // ステータスパネルの更新を停止
1.1.1.15  root     1004:        statuspanel->Close();
1.1.1.13  root     1005:        // メインビューの描画を停止
1.1.1.15  root     1006:        mainview->Close();
1.1.1.9   root     1007: 
1.1.1.3   root     1008:        // サブウィンドウを全部閉じる
1.1.1.10  root     1009:        for (int i = 0; i < ID_SUBWIN_MAX; i++) {
1.1.1.4   root     1010:                if ((bool)windows[i]) {
1.1.1.3   root     1011:                        windows[i]->Close();
                   1012:                }
                   1013:        }
                   1014: 
                   1015:        // 後はデフォルト処理
                   1016:        event.Skip();
                   1017: }
                   1018: 
1.1.1.17  root     1019: // メニューの「VM > Push Power Button」イベント
                   1020: void
                   1021: WXMainFrame::OnPowerButton(wxCommandEvent& event)
                   1022: {
                   1023:        // LUNA はモーメンタリ動作、X68030 はオルタネート動作のスイッチ。
                   1024:        // この違いは VM 側で吸収するのでここはボタンを押したという動作だけ
                   1025:        // 通知する。
                   1026:        power->PushPowerButton();
                   1027: }
                   1028: 
                   1029: // メニューの「VM > Push Power Button」UI
                   1030: void
                   1031: WXMainFrame::OnPowerButtonUI(wxUpdateUIEvent& event)
                   1032: {
                   1033:        PowerButtonState state = power->GetPowerButtonState();
                   1034:        if (state == PowerButtonState::NoState) {
                   1035:                // LUNA など電源ボタンに電源オフを指示する機構がないので、
                   1036:                // メニューを無効にする。
                   1037:                event.Enable(false);
                   1038:        } else {
                   1039:                // オルタネートスイッチならチェックで状態を表す。(X68030)
                   1040:                event.Check((bool)state);
                   1041:        }
                   1042: }
                   1043: 
                   1044: // メニューの「VM > Send CTRL+OPT.1+DEL」イベント
                   1045: void
                   1046: WXMainFrame::OnSoftReset(wxCommandEvent& event)
                   1047: {
                   1048:        keyboard->MakeKey(KC_CTRL);
                   1049:        keyboard->MakeKey(KC_OPT1);
                   1050:        keyboard->MakeKey(KC_DEL);
                   1051:        keyboard->BreakKey(KC_DEL);
                   1052:        keyboard->BreakKey(KC_OPT1);
                   1053:        keyboard->BreakKey(KC_CTRL);
                   1054: }
                   1055: 
                   1056: // メニューの「VM > Push Reset Button」イベント
                   1057: // こっちは本体リセットボタンによるリセット
                   1058: void
                   1059: WXMainFrame::OnResetButton(wxCommandEvent& event)
                   1060: {
                   1061:        power->MakeResetHard();
                   1062: }
                   1063: 
                   1064: // メニューの「VM > Push ABORT(Interrupt) Button」イベント
                   1065: void
                   1066: WXMainFrame::OnNMIButton(wxCommandEvent& event)
                   1067: {
                   1068:        auto nmi = GetNMIDevice();
                   1069:        nmi->PressNMI();
                   1070: }
                   1071: 
                   1072: // メニューの「VM > Restart VM」イベント
1.1.1.12  root     1073: void
                   1074: WXMainFrame::OnRestartVM(wxCommandEvent& event)
                   1075: {
1.1.1.15  root     1076:        power->MakeRestart();
1.1.1.12  root     1077: }
                   1078: 
1.1.1.17  root     1079: // メニューの「VM > 終了」イベント
1.1.1.12  root     1080: void
                   1081: WXMainFrame::OnExit(wxCommandEvent& event)
                   1082: {
                   1083:        // ウィンドウを閉じる
                   1084:        Close();
                   1085: }
                   1086: 
1.1       root     1087: // メニューの「高速モード」イベント
                   1088: void
                   1089: WXMainFrame::OnFullSpeed(wxCommandEvent& event)
                   1090: {
                   1091:        if (event.IsChecked()) {
                   1092:                // チェックが入ったので、高速モードにする
1.1.1.24  root     1093:                syncer->NotifyFullSpeed(true);
1.1       root     1094:        } else {
                   1095:                // チェックが消えたので、通常モードにする
1.1.1.24  root     1096:                syncer->NotifyFullSpeed(false);
1.1       root     1097:        }
                   1098: }
                   1099: 
                   1100: // メニューの「高速モード」UI
                   1101: void
                   1102: WXMainFrame::OnFullSpeedUI(wxUpdateUIEvent& event)
                   1103: {
1.1.1.15  root     1104:        bool is_fullspeed = syncer->GetFullSpeed();
1.1       root     1105:        event.Check(is_fullspeed);
                   1106: }
                   1107: 
1.1.1.12  root     1108: // メニューの「設定 > 入力 > *」の共通イベント
1.1.1.6   root     1109: void
1.1.1.12  root     1110: WXMainFrame::OnMenuInput(wxCommandEvent& event)
1.1.1.6   root     1111: {
1.1.1.12  root     1112:        bool char_mode = (event.GetId() == ID_INPUT_CHAR);
                   1113: 
1.1.1.15  root     1114:        mainview->SetCharInputMode(char_mode);
1.1.1.6   root     1115: }
                   1116: 
1.1.1.12  root     1117: // メニューの「設定 > 入力 > *」の共通 UI
1.1       root     1118: void
1.1.1.12  root     1119: WXMainFrame::OnMenuInputUI(wxUpdateUIEvent& event)
1.1       root     1120: {
1.1.1.15  root     1121:        bool char_mode = mainview->GetCharInputMode();
1.1.1.12  root     1122: 
                   1123:        if (char_mode) {
                   1124:                event.Check(event.GetId() == ID_INPUT_CHAR);
                   1125:        } else {
                   1126:                event.Check(event.GetId() == ID_INPUT_JP);
                   1127:        }
1.1       root     1128: }
                   1129: 
1.1.1.22  root     1130: // メニューの「設定 > HostNet* > *」の選択肢イベント
                   1131: void
                   1132: WXMainFrame::OnMenuHostNet(wxCommandEvent& event)
                   1133: {
                   1134:        int id = event.GetId();
                   1135:        uint unit;
                   1136:        uint choice;
                   1137: 
                   1138:        if (id <= ID_HOSTNET0_NONE) {
                   1139:                unit = 0;
                   1140:                choice = id;
                   1141:        } else {
                   1142:                unit = 1;
                   1143:                choice = id - ID_HOSTNET1_START + ID_HOSTNET0_START;
                   1144:        }
                   1145: 
                   1146:        // SLIRP モニタウィンドウはあれば閉じておく必要がある。
                   1147:        if ((bool)windows[ID_MONITOR_SLIRP]) {
                   1148:                DoWindow(ID_MONITOR_SLIRP, false);
                   1149:        }
                   1150: 
                   1151:        // 設定を更新。
                   1152:        std::string line = hostnet[unit]->GetConfigKey() + "-driver=";
                   1153:        switch (choice) {
                   1154:         case ID_HOSTNET0_USERMODE:     line += "usermode";     break;
                   1155:         case ID_HOSTNET0_TAP:          line += "tap";          break;
                   1156:         case ID_HOSTNET0_BPF:          line += "bpf";          break;
                   1157:         case ID_HOSTNET0_AFPACKET:     line += "afpacket";     break;
                   1158:         case ID_HOSTNET0_NONE:         line += "none";         break;
                   1159:         default:
                   1160:                assert(false);
                   1161:        }
                   1162:        gConfig->UpdateRunning(line);
                   1163: 
                   1164:        // ホストスレッドに通知。
                   1165:        hostnet[unit]->NotifyReselectDriver();
                   1166: }
                   1167: 
                   1168: // メニューの「設定 > HostNet* > *」の UI
                   1169: void
                   1170: WXMainFrame::OnMenuHostNetUI(wxUpdateUIEvent& event)
                   1171: {
                   1172:        int id = event.GetId();
                   1173:        uint unit;
                   1174: 
                   1175:        if (id <= ID_HOSTNET0_NONE) {
                   1176:                unit = 0;
                   1177:        } else {
                   1178:                unit = 1;
                   1179:                id = id - ID_HOSTNET1_START + ID_HOSTNET0_START;
                   1180:        }
                   1181: 
                   1182:        const std::string driver = hostnet[unit]->GetDriverName();
                   1183:        uint selected;
                   1184:        if (driver == "usermode") {
                   1185:                selected = ID_HOSTNET0_USERMODE;
                   1186:        } else if (driver == "tap") {
                   1187:                selected = ID_HOSTNET0_TAP;
                   1188:        } else if (driver == "bpf") {
                   1189:                selected = ID_HOSTNET0_BPF;
                   1190:        } else if (driver == "afpacket") {
                   1191:                selected = ID_HOSTNET0_AFPACKET;
                   1192:        } else {
                   1193:                selected = ID_HOSTNET0_NONE;
                   1194:        }
                   1195: 
                   1196:        event.Check((id == selected));
                   1197: }
                   1198: 
                   1199: // メニューの「設定 > HostCom* > *」の選択肢イベント
                   1200: void
                   1201: WXMainFrame::OnMenuHostCom(wxCommandEvent& event)
                   1202: {
                   1203:        int id = event.GetId();
                   1204:        HostCOMDevice *host;
                   1205:        uint choice;
                   1206: 
                   1207:        if (id <= ID_HOSTCOM0_NONE) {
                   1208:                host = hostcom[0];
                   1209:                choice = id;
                   1210:        } else if (id <= ID_HOSTCOM1_NONE) {
                   1211:                host = hostcom[1];
                   1212:                choice = id - ID_HOSTCOM1_START + ID_HOSTCOM0_START;
                   1213:        } else if (id <= ID_HOSTCOM2_NONE) {
                   1214:                host = hostcom[2];
                   1215:                choice = id - ID_HOSTCOM2_START + ID_HOSTCOM0_START;
                   1216:        } else {
                   1217:                host = hostcom_dbg;
                   1218:                choice = id - ID_HOSTCOM_DBG_START + ID_HOSTCOM0_START;
                   1219:        }
                   1220: 
                   1221:        // 設定を更新。
                   1222:        std::string line = host->GetConfigKey() + "-driver=";
                   1223:        switch (choice) {
                   1224:         case ID_HOSTCOM0_TCP:          line += "tcp";          break;
                   1225:         case ID_HOSTCOM0_STDIO:        line += "stdio";        break;
                   1226:         case ID_HOSTCOM0_CONSOLE:      line += "console";      break;
                   1227:         case ID_HOSTCOM0_NONE:         line += "none";         break;
                   1228:         default:
                   1229:                assert(false);
                   1230:        }
                   1231:        gConfig->UpdateRunning(line);
                   1232: 
                   1233:        // ホストスレッドに通知。
                   1234:        host->NotifyReselectDriver();
                   1235: }
                   1236: 
                   1237: // メニューの「設定 > HostCom* > *」の UI
                   1238: void
                   1239: WXMainFrame::OnMenuHostComUI(wxUpdateUIEvent& event)
                   1240: {
                   1241:        int id = event.GetId();
                   1242:        HostCOMDevice *host;
                   1243: 
                   1244:        if (id <= ID_HOSTCOM0_NONE) {
                   1245:                host = hostcom[0];
                   1246:        } else if (id <= ID_HOSTCOM1_NONE) {
                   1247:                host = hostcom[1];
                   1248:                id = id - ID_HOSTCOM1_START + ID_HOSTCOM0_START;
                   1249:        } else if (id <= ID_HOSTCOM2_NONE) {
                   1250:                host = hostcom[2];
                   1251:                id = id - ID_HOSTCOM2_START + ID_HOSTCOM0_START;
                   1252:        } else {
                   1253:                host = hostcom_dbg;
                   1254:                id = id - ID_HOSTCOM_DBG_START + ID_HOSTCOM0_START;
                   1255:        }
                   1256: 
                   1257:        const std::string driver = host->GetDriverName();
                   1258:        uint selected;
                   1259:        if (driver == "tcp") {
                   1260:                selected = ID_HOSTCOM0_TCP;
                   1261:        } else if (driver == "stdio") {
                   1262:                selected = ID_HOSTCOM0_STDIO;
                   1263:        } else if (driver == "console") {
                   1264:                selected = ID_HOSTCOM0_CONSOLE;
                   1265:        } else {
                   1266:                selected = ID_HOSTCOM0_NONE;
                   1267:        }
                   1268: 
                   1269:        event.Check((id == selected));
                   1270: }
                   1271: 
1.1.1.24  root     1272: // メニューの「設定 > HostSound > *」の選択肢イベント
                   1273: void
                   1274: WXMainFrame::OnMenuHostSound(wxCommandEvent& event)
                   1275: {
                   1276:        // 設定を更新。
                   1277:        std::string line = "hostsound-driver=";
                   1278:        switch (event.GetId()) {
                   1279:         case ID_HOSTSOUND_NETBSD:      line += "netbsd";       break;
                   1280:         case ID_HOSTSOUND_SNDIO:       line += "sndio";        break;
                   1281:         case ID_HOSTSOUND_ALSA:        line += "alsa";         break;
                   1282:         case ID_HOSTSOUND_WAV:         line += "wav";          break;
                   1283:         case ID_HOSTSOUND_NONE:        line += "none";         break;
                   1284:         default:
                   1285:                assert(false);
                   1286:        }
                   1287:        gConfig->UpdateRunning(line);
                   1288: 
                   1289:        // ホストスレッドに通知。
                   1290:        hostsound->NotifyReselectDriver();
                   1291: }
                   1292: 
                   1293: // メニューの「設定 > HostSound > *」の UI
                   1294: void
                   1295: WXMainFrame::OnMenuHostSoundUI(wxUpdateUIEvent& event)
                   1296: {
                   1297:        int id = event.GetId();
                   1298:        const std::string driver = hostsound->GetDriverName();
                   1299:        int selected;
                   1300:        if (driver == "netbsd") {
                   1301:                selected = ID_HOSTSOUND_NETBSD;
                   1302:        } else if (driver == "sndio") {
                   1303:                selected = ID_HOSTSOUND_SNDIO;
                   1304:        } else if (driver == "alsa") {
                   1305:                selected = ID_HOSTSOUND_ALSA;
                   1306:        } else if (driver == "wav") {
                   1307:                selected = ID_HOSTSOUND_WAV;
                   1308:        } else {
                   1309:                selected = ID_HOSTSOUND_NONE;
                   1310:        }
                   1311: 
                   1312:        event.Check((id == selected));
                   1313: }
                   1314: 
1.1.1.22  root     1315: // hostnet ドライバ起動失敗のメッセージ。
                   1316: void
                   1317: WXMainFrame::OnHostNetFailed(wxCommandEvent& event)
                   1318: {
                   1319:        wxString hostdev;
                   1320:        wxString errmsg;
                   1321:        uint n = event.GetInt();
                   1322: 
                   1323:        hostdev.Printf("hostnet%u", n);
                   1324:        errmsg = hostnet[n]->GetErrmsg();
                   1325:        HostDriverFailed(hostdev, errmsg);
                   1326: }
                   1327: 
1.1.1.24  root     1328: // hostcom ドライバ起動失敗のメッセージ。
1.1.1.22  root     1329: void
                   1330: WXMainFrame::OnHostComFailed(wxCommandEvent& event)
                   1331: {
                   1332:        wxString hostdev;
                   1333:        wxString errmsg;
                   1334:        int n = event.GetInt();
                   1335: 
                   1336:        if (n >= 0) {
                   1337:                hostdev.Printf("hostcom%u", n);
                   1338:                errmsg = hostcom[n]->GetErrmsg();
                   1339:        } else {
                   1340:                hostdev = "debugger";
                   1341:                errmsg = hostcom_dbg->GetErrmsg();
                   1342:        }
                   1343:        HostDriverFailed(hostdev, errmsg);
                   1344: }
                   1345: 
1.1.1.24  root     1346: // hostsound ドライバ起動失敗のメッセージ
                   1347: void
                   1348: WXMainFrame::OnHostSoundFailed(wxCommandEvent& event)
                   1349: {
                   1350:        wxString errmsg;
                   1351: 
                   1352:        errmsg = hostsound->GetErrmsg();
                   1353:        HostDriverFailed("hostsound", errmsg);
                   1354: }
                   1355: 
1.1.1.22  root     1356: // ホストドライバ起動失敗のメッセージ。
                   1357: void
                   1358: WXMainFrame::HostDriverFailed(const wxString& hostdev, const wxString& errmsg)
                   1359: {
                   1360:        wxString msg;
                   1361: 
                   1362:        msg = hostdev;
                   1363:        msg += ": ";
                   1364:        msg += _("Failed to switch the driver.\n"
                   1365:                "(Using 'none' instead)");
                   1366:        if (!errmsg.empty()) {
                   1367:                msg += "\n\n";
                   1368:                msg += _("Error message:");
                   1369:                msg += ' ';
                   1370:                msg += errmsg;
                   1371:        }
                   1372:        ::wxMessageBox(msg);
                   1373: }
                   1374: 
1.1.1.15  root     1375: // スケール一覧
                   1376: /*static*/ std::vector<double>
                   1377: WXMainFrame::view_scales {
                   1378:        0.50,
                   1379:        0.75,
                   1380:        1.00,
                   1381:        1.50,
                   1382:        2.00,
                   1383: };
                   1384: 
                   1385: #define contains(v, key)       (std::find(v.begin(), v.end(), key) != v.end())
                   1386: 
                   1387: // 「表示 > スケール」のメニュー項目作成に必要な view_scale を作成し、
                   1388: // ユーザ指定値があれば view_scales[] 内でのインデックスを返す。
                   1389: // ユーザ指定値がなければ -1 を返す。
                   1390: int
                   1391: WXMainFrame::CreateMainviewScaleTable()
                   1392: {
                   1393:        // 設定ファイル mainview-scale で指定されたサイズを追加。
                   1394:        // 値はこの時点で WXMainView::screen_scale にセットされている。
                   1395:        double user_scale = WXMainView::screen_scale;
                   1396:        if (contains(view_scales, user_scale)) {
                   1397:                // プリセットと同じなら、このままでよい。
                   1398:        } else {
                   1399:                // 追加したらソート。
                   1400:                view_scales.push_back(user_scale);
                   1401:                std::sort(view_scales.begin(), view_scales.end());
                   1402: 
                   1403:                // ユーザ指定の値が何番目かを返す。指定されてなければ -1。
                   1404:                for (int i = 0, end = view_scales.size(); i < end; i++) {
                   1405:                        if (view_scales[i] == user_scale) {
                   1406:                                return i;
                   1407:                        }
                   1408:                }
                   1409:                // 見付からないことはないはずだが
                   1410:        }
                   1411:        return -1;
                   1412: }
                   1413: 
1.1       root     1414: // メニューの「表示 > スケール > *」の共通イベント
                   1415: void
                   1416: WXMainFrame::OnMenuScale(wxCommandEvent& event)
                   1417: {
1.1.1.15  root     1418:        int idx = event.GetId() - ID_SCALE_START;
                   1419:        mainview->DoResize(view_scales[idx]);
1.1       root     1420:        // 再レイアウト
1.1.1.22  root     1421:        Fit();
1.1       root     1422: }
                   1423: 
                   1424: // メニューの「表示 > スケール > *」の共通 UI
                   1425: void
                   1426: WXMainFrame::OnMenuScaleUI(wxUpdateUIEvent& event)
                   1427: {
1.1.1.15  root     1428:        int idx = event.GetId() - ID_SCALE_START;
                   1429:        double current_scale = mainview->GetScale();
1.1       root     1430: 
1.1.1.15  root     1431:        event.Check(view_scales[idx] == current_scale);
1.1       root     1432: }
                   1433: 
                   1434: // メニューの「表示 > フォントサイズ > *」の共通イベント
                   1435: void
                   1436: WXMainFrame::OnMenuFontSize(wxCommandEvent& event)
                   1437: {
1.1.1.5   root     1438:        FontId fontid;
1.1       root     1439: 
1.1.1.3   root     1440:        assertmsg(
1.1.1.15  root     1441:                ID_FONTSIZE_12 <= event.GetId() && event.GetId() <= ID_FONTSIZE_24,
1.1.1.3   root     1442:                "event.GetId()=%d", event.GetId());
1.1       root     1443:        switch (event.GetId()) {
                   1444:         case ID_FONTSIZE_12:
1.1.1.5   root     1445:                fontid = FontId::_6x12;
1.1       root     1446:                break;
                   1447:         case ID_FONTSIZE_16:
1.1.1.5   root     1448:                fontid = FontId::_8x16;
1.1       root     1449:                break;
1.1.1.15  root     1450:         case ID_FONTSIZE_24:
                   1451:                fontid = FontId::_12x24;
                   1452:                break;
1.1       root     1453:         default:
                   1454:                __unreachable();
                   1455:                break;
                   1456:        }
                   1457: 
1.1.1.13  root     1458:        if (fontid != gFontManager->GetFontId()) {
                   1459:                gFontManager->SetFont(fontid);
1.1       root     1460: 
1.1.1.13  root     1461:                // アクティブなサブウィンドウ全員にフォント変更通知
1.1.1.10  root     1462:                for (int i = 0; i < ID_SUBWIN_MAX; i++) {
1.1.1.4   root     1463:                        if ((bool)windows[i]) {
                   1464:                                WXSubWindow *subwin =
                   1465:                                        dynamic_cast<WXSubWindow *>(windows[i].get());
1.1.1.13  root     1466:                                subwin->FontChanged();
1.1       root     1467:                        }
                   1468:                }
1.1.1.13  root     1469:                // メインウィンドウはここで直接ステータスパネルに通知
1.1.1.15  root     1470:                statuspanel->FontChanged();
1.1.1.9   root     1471: 
                   1472:                // ステータスパネルの大きさが変わるので再レイアウト
1.1.1.22  root     1473:                Fit();
1.1       root     1474:        }
                   1475: }
                   1476: 
                   1477: // メニューの「表示 > フォントサイズ > *」共通 UI
                   1478: void
                   1479: WXMainFrame::OnMenuFontSizeUI(wxUpdateUIEvent& event)
                   1480: {
1.1.1.13  root     1481:        FontId current_size = gFontManager->GetFontId();
1.1.1.5   root     1482:        FontId event_size = (FontId)(event.GetId() - (ID_FONTSIZE_START+1));
1.1       root     1483: 
                   1484:        event.Check(current_size == event_size);
                   1485: }
                   1486: 
1.1.1.15  root     1487: // 更新頻度一覧
                   1488: /*static*/ std::vector<int>
                   1489: WXMainFrame::monrates {
                   1490:        20,
                   1491:        5,
                   1492:        1,
1.1.1.5   root     1493: };
                   1494: 
1.1.1.21  root     1495: // 「表示 > モニタ更新頻度」のメニュー項目作成に必要な monrates を作成する。
                   1496: void
1.1.1.15  root     1497: WXMainFrame::CreateMonRateTable()
                   1498: {
                   1499:        // 設定ファイル monitor-rate で指定された値を追加。
                   1500:        // 値はこの時点で monitor_rate にセットされている。
                   1501:        int user_rate = monitor_rate;
                   1502:        if (contains(monrates, user_rate)) {
                   1503:                // プリセットと同じなら、このままでよい。
                   1504:        } else {
                   1505:                // 追加したら降順にソート。
                   1506:                monrates.push_back(user_rate);
                   1507:                std::sort(monrates.begin(), monrates.end(),
                   1508:                        [](int a, int b) { return a > b; }
                   1509:                );
                   1510:        }
                   1511: }
                   1512: 
1.1.1.5   root     1513: // メニューの「表示 > モニタ更新頻度 > *」の共通イベント
                   1514: void
                   1515: WXMainFrame::OnMenuMonRate(wxCommandEvent& event)
                   1516: {
1.1.1.15  root     1517:        int idx = event.GetId() - ID_MONRATE_START;
                   1518:        monitor_rate = monrates[idx];
1.1.1.5   root     1519: 
1.1.1.23  root     1520:        // アクティブなサブウィンドウのモニタパネル全員に通知。
1.1.1.10  root     1521:        for (int i = 0; i < ID_SUBWIN_MAX; i++) {
1.1.1.5   root     1522:                if ((bool)windows[i]) {
                   1523:                        auto *subwin = dynamic_cast<WXSubWindow *>(windows[i].get());
                   1524:                        for (wxWindow *child : subwin->GetChildren()) {
1.1.1.14  root     1525:                                auto *panel = dynamic_cast<WXMonitorPanel*>(child);
1.1.1.5   root     1526:                                if (panel) {
                   1527:                                        panel->SetRate(monitor_rate);
                   1528:                                }
                   1529:                        }
                   1530:                }
                   1531:        }
                   1532: }
                   1533: 
                   1534: // メニューの「表示 > モニタ更新頻度 > *」共通 UI
                   1535: void
                   1536: WXMainFrame::OnMenuMonRateUI(wxUpdateUIEvent& event)
                   1537: {
1.1.1.15  root     1538:        int idx = event.GetId() - ID_MONRATE_START;
1.1.1.5   root     1539: 
1.1.1.15  root     1540:        event.Check(monrates[idx] == monitor_rate);
1.1.1.5   root     1541: }
                   1542: 
1.1.1.9   root     1543: // メニューの「表示 > ステータスパネルを表示」
                   1544: void
                   1545: WXMainFrame::OnShowStatusPanel(wxCommandEvent& event)
                   1546: {
                   1547:        // enable ならチェックを付けようとして呼ばれた
                   1548:        bool enable = event.IsChecked();
                   1549: 
1.1.1.15  root     1550:        statuspanel->Show(enable);
1.1.1.9   root     1551: 
                   1552:        // 再レイアウト
1.1.1.22  root     1553:        Fit();
1.1.1.9   root     1554: }
                   1555: 
                   1556: // メニューの「表示 > ステータスパネルを表示」UI
                   1557: void
                   1558: WXMainFrame::OnShowStatusPanelUI(wxUpdateUIEvent& event)
                   1559: {
1.1.1.15  root     1560:        event.Check(statuspanel->IsShown());
1.1.1.9   root     1561: }
                   1562: 
1.1.1.14  root     1563: // メニューの「デバイス > FD > 挿入」
                   1564: void
                   1565: WXMainFrame::OnFDInsert(wxCommandEvent& event)
                   1566: {
                   1567:        int unit = event.GetId() - ID_FD_INSERT_0;
                   1568:        const auto *fdd = fdd_array[unit];
                   1569:        assert(fdd);
                   1570: 
                   1571:        std::string title(_("Open a FD image"));
                   1572:        std::string wildcard("FD images (*.xdf;*.img;*.fs)"
                   1573:                "|*.xdf;*.XDF;*.img;*.IMG;*.fs;*.FS"
                   1574:                "|All files (*.*)|*.*");
                   1575: 
                   1576:        // ディレクトリは、まだ一度も使ってなければ VM ディレクトリにする
                   1577:        if (current_dir.empty()) {
                   1578:                current_dir = gMainApp.GetVMDir();
                   1579:        }
                   1580: 
                   1581:        wxFileDialog dialog(this, title, current_dir, "", wildcard,
                   1582:                wxFD_OPEN | wxFD_FILE_MUST_EXIST);
                   1583:        if (dialog.ShowModal() == wxID_CANCEL) {
                   1584:                return;
                   1585:        }
                   1586:        auto path = std::string(dialog.GetPath());
                   1587:        InsertFD(unit, path);
                   1588: }
                   1589: 
                   1590: // メニューの「デバイス > FD > 挿入」UI
                   1591: void
                   1592: WXMainFrame::OnFDInsertUI(wxUpdateUIEvent& event)
                   1593: {
                   1594:        int unit = event.GetId() - ID_FD_INSERT_0;
                   1595:        const auto *fdd = fdd_array[unit];
                   1596:        assert(fdd);
                   1597: 
                   1598:        if (fdd->IsMediumLoaded()) {
                   1599:                event.SetText(_("Ex&change"));
                   1600:        } else {
                   1601:                event.SetText(_("&Insert"));
                   1602:        }
                   1603: }
                   1604: 
                   1605: // メニューの「デバイス > FD > 取り出し」
                   1606: void
                   1607: WXMainFrame::OnFDEject(wxCommandEvent& event)
                   1608: {
                   1609:        int unit = event.GetId() - ID_FD_EJECT_0;
                   1610: 
                   1611:        EjectFD(unit, false);
                   1612: }
                   1613: 
                   1614: // メニューの「デバイス > FD > 取り出し」UI
                   1615: void
                   1616: WXMainFrame::OnFDEjectUI(wxUpdateUIEvent& event)
                   1617: {
                   1618:        int unit = event.GetId() - ID_FD_EJECT_0;
                   1619:        FDDDevice *fdd = fdd_array[unit];
                   1620:        assert(fdd);
                   1621: 
                   1622:        // 挿入されてて取り出し可能な時のみ有効
                   1623:        event.Enable(fdd->IsMediumLoaded() && fdd->IsEjectEnable());
                   1624: }
                   1625: 
                   1626: // メニューの「デバイス > FD > 強制取り出し」
                   1627: void
                   1628: WXMainFrame::OnFDForce(wxCommandEvent& event)
                   1629: {
                   1630:        int unit = event.GetId() - ID_FD_FORCE_0;
                   1631: 
                   1632:        EjectFD(unit, true);
                   1633: }
                   1634: 
                   1635: // メニューの「デバイス > FD > 強制取り出し」UI
                   1636: void
                   1637: WXMainFrame::OnFDForceUI(wxUpdateUIEvent& event)
                   1638: {
                   1639:        int unit = event.GetId() - ID_FD_FORCE_0;
                   1640:        FDDDevice *fdd = fdd_array[unit];
                   1641:        assert(fdd);
                   1642: 
                   1643:        // 挿入されてて取り出し禁止の時のみ有効
                   1644:        event.Enable(fdd->IsMediumLoaded() && fdd->IsEjectEnable() == false);
                   1645: }
                   1646: 
1.1.1.11  root     1647: // メニューの「デバイス > CD/MO > 挿入」
                   1648: void
                   1649: WXMainFrame::OnCDInsert(wxCommandEvent& event)
                   1650: {
                   1651:        std::string title;
                   1652:        std::string wildcard;
                   1653: 
                   1654:        int id = event.GetId() - ID_CD_INSERT_0;
                   1655:        const auto *dev = scsidev[id];
                   1656:        assert(dev);
                   1657: 
                   1658:        switch (dev->GetDevType()) {
                   1659:         case SCSI::DevType::CD:
                   1660:                title = _("Open a CD image");
                   1661:                wildcard = "ISO images (*.iso;*.img)|*.iso;*.img;*.ISO;*.IMG";
                   1662:                break;
                   1663:         case SCSI::DevType::MO:
                   1664:                title = _("Open an MO image");
                   1665:                wildcard = "MO images (*.img;*.mos)|*.img;*.mos;*.IMG;*.MOS";
                   1666:                break;
                   1667:         default:
1.1.1.15  root     1668:                break;
1.1.1.11  root     1669:        }
                   1670:        wildcard += "|All files (*.*)|*.*";
                   1671: 
                   1672:        // ディレクトリは、まだ一度も使ってなければ VM ディレクトリにする
                   1673:        if (current_dir.empty()) {
                   1674:                current_dir = gMainApp.GetVMDir();
                   1675:        }
                   1676: 
                   1677:        wxFileDialog dialog(this, title, current_dir, "", wildcard,
                   1678:                wxFD_OPEN | wxFD_FILE_MUST_EXIST);
                   1679:        if (dialog.ShowModal() == wxID_CANCEL) {
                   1680:                return;
                   1681:        }
                   1682:        auto path = std::string(dialog.GetPath());
                   1683:        InsertCD(id, path);
                   1684: }
                   1685: 
                   1686: // メニューの「デバイス > CD/MO > 挿入」UI
                   1687: void
                   1688: WXMainFrame::OnCDInsertUI(wxUpdateUIEvent& event)
                   1689: {
                   1690:        int id = event.GetId() - ID_CD_INSERT_0;
                   1691:        SCSIDisk *disk = dynamic_cast<SCSIDisk *>(scsidev[id]);
                   1692:        assert(disk);
                   1693: 
                   1694:        if (disk->IsMediumLoaded()) {
                   1695:                event.SetText(_("Ex&change"));
                   1696:        } else {
                   1697:                event.SetText(_("&Insert"));
                   1698:        }
                   1699: }
                   1700: 
                   1701: // メニューの「デバイス > CD/MO > 取り出し」
                   1702: void
                   1703: WXMainFrame::OnCDEject(wxCommandEvent& event)
                   1704: {
                   1705:        int id = event.GetId() - ID_CD_EJECT_0;
                   1706: 
                   1707:        EjectCD(id, false);
                   1708: }
                   1709: 
                   1710: // メニューの「デバイス > CD/MO > 取り出し」UI
                   1711: void
                   1712: WXMainFrame::OnCDEjectUI(wxUpdateUIEvent& event)
                   1713: {
                   1714:        int id = event.GetId() - ID_CD_EJECT_0;
                   1715:        SCSIDisk *disk = dynamic_cast<SCSIDisk *>(scsidev[id]);
                   1716:        assert(disk);
                   1717: 
                   1718:        // 挿入されてて取り出し可能な時のみ有効
                   1719:        event.Enable(disk->IsMediumLoaded() &&
                   1720:                     disk->IsMediumRemovalAllowed());
                   1721: }
                   1722: 
                   1723: // メニューの「デバイス > CD/MO > 強制取り出し」
                   1724: void
                   1725: WXMainFrame::OnCDForce(wxCommandEvent& event)
                   1726: {
                   1727:        int id = event.GetId() - ID_CD_FORCE_0;
                   1728: 
                   1729:        EjectCD(id, true);
                   1730: }
                   1731: 
                   1732: // メニューの「デバイス > CD/MO > 強制取り出し」UI
                   1733: void
                   1734: WXMainFrame::OnCDForceUI(wxUpdateUIEvent& event)
                   1735: {
                   1736:        int id = event.GetId() - ID_CD_FORCE_0;
                   1737:        SCSIDisk *disk = dynamic_cast<SCSIDisk *>(scsidev[id]);
                   1738:        assert(disk);
                   1739: 
                   1740:        // 挿入されてて取り出し禁止の時のみ有効
                   1741:        event.Enable(disk->IsMediumLoaded() &&
                   1742:                     disk->IsMediumRemovalPrevented());
                   1743: }
                   1744: 
1.1.1.2   root     1745: // メニューの「デバイス > マウスモード」
                   1746: void
                   1747: WXMainFrame::OnMouseMode(wxCommandEvent& event)
                   1748: {
                   1749:        // enable ならチェックを付けようとして呼ばれた
                   1750:        bool enable = event.IsChecked();
                   1751: 
                   1752:        // マウスモードを設定
1.1.1.15  root     1753:        wxCommandEvent newev(NONO_EVT_MOUSEMODE, GetId());
                   1754:        newev.SetEventObject(this);
                   1755:        newev.SetInt(enable);
                   1756:        ::wxPostEvent(mainview, newev);
1.1.1.2   root     1757: }
                   1758: 
                   1759: // メニューの「デバイス > マウスモード」UI
                   1760: void
                   1761: WXMainFrame::OnMouseModeUI(wxUpdateUIEvent& event)
                   1762: {
1.1.1.15  root     1763:        event.Check(mainview->GetMouseMode());
1.1.1.2   root     1764: }
                   1765: 
1.1.1.13  root     1766: // メニューの「デバイス > Operation > Keyboard Connect」イベント
                   1767: void
                   1768: WXMainFrame::OnKeyboardConnect(wxCommandEvent& event)
                   1769: {
                   1770:        // enable ならチェックを付けようとして呼ばれた
                   1771:        bool enable = event.IsChecked();
                   1772: 
                   1773:        // キーボード接続を設定
1.1.1.15  root     1774:        keyboard->Connect(enable);
1.1.1.13  root     1775: }
                   1776: 
                   1777: // メニューの「デバイス > Operation > Keyboard Connect」UI
                   1778: void
                   1779: WXMainFrame::OnKeyboardConnectUI(wxUpdateUIEvent& event)
                   1780: {
1.1.1.15  root     1781:        event.Check(keyboard->IsConnected());
1.1.1.9   root     1782: }
                   1783: 
1.1       root     1784: // メニューのウィンドウ ID 共通イベント
                   1785: // チェックが入る方なら、ウィンドウを作成して表示。
                   1786: // チェックが消える方なら、ウィンドウを削除。
                   1787: void
                   1788: WXMainFrame::OnWindow(wxCommandEvent& event)
                   1789: {
                   1790:        int id = event.GetId();
                   1791: 
                   1792:        DoWindow(id, event.IsChecked());
                   1793: }
                   1794: 
1.1.1.21  root     1795: #define SetMonitor(id, name)   do {    \
                   1796:        try {   \
                   1797:                windows[id].reset(new WXMonitorWindow(this, (name), \
                   1798:                        gMonitorManager->Get(id)));     \
                   1799:        } catch (...) { }       \
                   1800: } while (0)
                   1801: 
1.1       root     1802: void
                   1803: WXMainFrame::DoWindow(int id, bool enable)
                   1804: {
1.1.1.10  root     1805:        // モニタウィンドウを作成する共通部分。
                   1806:        // id はモニター ID であると同時に、windows[] 配列の添字、さらにこの
                   1807:        // モニタウィンドウの wxWindowID としても使っている
                   1808:        // (WXSubWindow::OnClose() 参照)。
1.1.1.4   root     1809: 
1.1       root     1810:        if (enable) {
                   1811:                // チェックが入ったのでウィンドウを作成
                   1812:                switch (id) {
1.1.1.17  root     1813:                 case ID_MONITOR_ACCSTAT:
1.1.1.18  root     1814:                        // こいつだけモニタ ID を持ちつつ上位互換のサブウィンドウがある。
1.1.1.21  root     1815:                        try {
                   1816:                                windows[id].reset(new
                   1817:                                        WXAccStatWindow(this, gMonitorManager->Get(id)));
                   1818:                        } catch (...) { }
1.1.1.17  root     1819:                        break;
                   1820: 
1.1.1.24  root     1821:                 case ID_MONITOR_ADPCM:
                   1822:                        SetMonitor(id, "ADPCM");
                   1823:                        break;
                   1824: 
1.1.1.17  root     1825:                 case ID_MONITOR_AREASET:
                   1826:                        SetMonitor(id, _("Areaset"));
                   1827:                        break;
                   1828: 
1.1.1.10  root     1829:                 case ID_MONITOR_ATC0:
                   1830:                 case ID_MONITOR_ATC1:
                   1831:                 case ID_MONITOR_ATC2:
                   1832:                 case ID_MONITOR_ATC3:
                   1833:                 case ID_MONITOR_ATC4:
                   1834:                 case ID_MONITOR_ATC5:
                   1835:                 case ID_MONITOR_ATC6:
                   1836:                 case ID_MONITOR_ATC7:
                   1837:                 {
1.1.1.18  root     1838:                        uint n = id - ID_MONITOR_ATC0;
                   1839:                        wxString name(string_format("ATC#%u", n));
1.1.1.10  root     1840:                        if ((n & 1) == 0) {
                   1841:                                name += _("(Data)");
                   1842:                        } else {
                   1843:                                name += _("(Inst)");
                   1844:                        }
                   1845:                        SetMonitor(id, name);
1.1.1.4   root     1846:                        break;
1.1.1.10  root     1847:                 }
                   1848: 
                   1849:                 case ID_MONITOR_BREAKPOINT:
1.1.1.22  root     1850:                        SetMonitor(id, _("Breakpoints"));
1.1.1.5   root     1851:                        break;
1.1.1.10  root     1852: 
1.1.1.15  root     1853:                 case ID_MONITOR_BT45x:
                   1854:                        SetMonitor(id, "Bt454/458");
                   1855:                        break;
                   1856: 
1.1.1.10  root     1857:                 case ID_MONITOR_CMMU0:
                   1858:                 case ID_MONITOR_CMMU1:
                   1859:                 case ID_MONITOR_CMMU2:
                   1860:                 case ID_MONITOR_CMMU3:
                   1861:                 case ID_MONITOR_CMMU4:
                   1862:                 case ID_MONITOR_CMMU5:
                   1863:                 case ID_MONITOR_CMMU6:
                   1864:                 case ID_MONITOR_CMMU7:
                   1865:                 {
1.1.1.18  root     1866:                        uint n = id - ID_MONITOR_CMMU0;
                   1867:                        wxString name(string_format("CMMU#%u", n));
1.1.1.10  root     1868:                        if ((n & 1) == 0) {
                   1869:                                name += _("(Data)");
                   1870:                        } else {
                   1871:                                name += _("(Inst)");
                   1872:                        }
1.1.1.22  root     1873:                        name += ' ';
                   1874:                        name += _("Registers");
1.1.1.10  root     1875:                        SetMonitor(id, name);
1.1.1.4   root     1876:                        break;
1.1.1.10  root     1877:                 }
                   1878: 
1.1.1.13  root     1879:                 case ID_MONITOR_CRTC:
1.1.1.23  root     1880:                        SetMonitor(id, _("CRTC and Video Controller"));
1.1.1.13  root     1881:                        break;
                   1882: 
1.1.1.10  root     1883:                 case ID_MONITOR_DMAC:
1.1.1.15  root     1884:                        SetMonitor(id, "DMAC (HD63450)");
1.1.1.5   root     1885:                        break;
1.1.1.10  root     1886: 
1.1.1.14  root     1887:                 case ID_MONITOR_FDC:
1.1.1.15  root     1888:                        SetMonitor(id, "FDC (uPD72065B)");
1.1.1.14  root     1889:                        break;
                   1890: 
1.1.1.22  root     1891:                 case ID_MONITOR_HOSTCOM0:
                   1892:                 case ID_MONITOR_HOSTCOM1:
                   1893:                 case ID_MONITOR_HOSTCOM2:
                   1894:                 {
                   1895:                        uint n = id - ID_MONITOR_HOSTCOM0;
                   1896:                        SetMonitor(id, GetHostComLabel(n));
1.1.1.13  root     1897:                        break;
1.1.1.22  root     1898:                 }
1.1.1.13  root     1899: 
1.1.1.16  root     1900:                 case ID_MONITOR_HOSTNET0:
                   1901:                 case ID_MONITOR_HOSTNET1:
1.1.1.17  root     1902:                 {
1.1.1.22  root     1903:                        uint n = id - ID_MONITOR_HOSTNET0;
                   1904:                        SetMonitor(id, GetHostNetLabel(n));
1.1.1.13  root     1905:                        break;
1.1.1.17  root     1906:                 }
1.1.1.13  root     1907: 
1.1.1.24  root     1908:                 case ID_MONITOR_HOSTSOUND:
                   1909:                        SetMonitor(id, _("Host Sound"));
                   1910:                        break;
                   1911: 
1.1.1.10  root     1912:                 case ID_MONITOR_INTERRUPT:
1.1.1.15  root     1913:                 {
                   1914:                        wxString name;
1.1.1.22  root     1915:                        if (gMainApp.Has(VMCap::M68K)) {
                   1916:                                name = MPUName() + " " + _("Interrupts");
1.1.1.15  root     1917:                        } else {
1.1.1.22  root     1918:                                // 実際はほぼシステムコントローラなのでややこしい。
                   1919:                                name = "MPU " + _("Interrupts");
1.1.1.15  root     1920:                        }
                   1921:                        SetMonitor(id, name);
1.1.1.5   root     1922:                        break;
1.1.1.15  root     1923:                 }
1.1.1.10  root     1924: 
                   1925:                 case ID_MONITOR_KEYBOARD:
                   1926:                        SetMonitor(id, _("Keyboard/Mouse"));
1.1.1.4   root     1927:                        break;
1.1.1.10  root     1928: 
                   1929:                 case ID_MONITOR_LANCE:
1.1.1.15  root     1930:                        SetMonitor(id, "LANCE (AM7990)");
1.1       root     1931:                        break;
1.1.1.10  root     1932: 
                   1933:                 case ID_MONITOR_LCD:
1.1.1.21  root     1934:                        try {
                   1935:                                windows[id].reset(new WXLCDMonitor(this));
                   1936:                        } catch (...) { }
1.1.1.4   root     1937:                        break;
1.1.1.10  root     1938: 
1.1.1.23  root     1939:                 case ID_MONITOR_LOG:
                   1940:                        try {
                   1941:                                windows[id].reset(new WXLogMonitor(this));
                   1942:                        } catch (...) { }
                   1943:                        break;
                   1944: 
1.1.1.13  root     1945:                 case ID_MONITOR_LUNAVC:
                   1946:                        SetMonitor(id, _("Video Control"));
1.1.1.4   root     1947:                        break;
1.1.1.10  root     1948: 
1.1.1.16  root     1949:                 case ID_MONITOR_MAINBUS:
                   1950:                 {
                   1951:                        wxString name;
                   1952:                        if (gMainApp.IsX68030()) {
                   1953:                                name = _("Device Map (32bit space)");
                   1954:                        } else {
                   1955:                                name = _("Device Map");
                   1956:                        }
                   1957:                        SetMonitor(id, name);
                   1958:                        break;
                   1959:                 }
                   1960: 
1.1.1.10  root     1961:                 case ID_MONITOR_MEMDUMP0 ...
1.1.1.15  root     1962:                      ID_MONITOR_MEMDUMP(MAX_MEMDUMP_MONITOR - 1):
                   1963:                 case ID_MONITOR_XPMEMDUMP0 ...
                   1964:                      ID_MONITOR_XPMEMDUMP(MAX_XPMEMDUMP_MONITOR - 1):
1.1.1.10  root     1965:                 {
1.1.1.21  root     1966:                        try {
                   1967:                                windows[id].reset(new WXMemdumpWindow(this, id));
                   1968:                        } catch (...) { }
1.1.1.4   root     1969:                        break;
1.1.1.10  root     1970:                 }
                   1971: 
                   1972:                 case ID_MONITOR_MFP:
1.1.1.15  root     1973:                        SetMonitor(id, "MFP (MC68901)");
1.1.1.4   root     1974:                        break;
1.1.1.10  root     1975: 
                   1976:                 case ID_MONITOR_MK48T02:
1.1.1.15  root     1977:                        SetMonitor(id, "RTC (MK48T02)");
1.1       root     1978:                        break;
1.1.1.10  root     1979: 
                   1980:                 case ID_MONITOR_MPUATC:
1.1.1.17  root     1981:                        SetMonitor(id, MPUName() + " ATC");
                   1982:                        break;
                   1983: 
                   1984:                 case ID_MONITOR_MPUCACHE:
1.1.1.22  root     1985:                        SetMonitor(id, MPUName() + " " + _("Caches"));
1.1       root     1986:                        break;
1.1.1.10  root     1987: 
                   1988:                 case ID_MONITOR_MPUREG:
1.1.1.22  root     1989:                        SetMonitor(id, MPUName() + " " + _("Registers"));
1.1.1.15  root     1990:                        break;
                   1991: 
1.1.1.16  root     1992:                 case ID_MONITOR_NEREID:
                   1993:                        SetMonitor(id, "Nereid");
                   1994:                        break;
                   1995: 
1.1.1.15  root     1996:                 case ID_MONITOR_ROMCONS:
                   1997:                        SetMonitor(id, _("ROM Console (provisional)"));
1.1.1.7   root     1998:                        break;
1.1.1.10  root     1999: 
1.1.1.15  root     2000:                 case ID_MONITOR_PIO:
                   2001:                        SetMonitor(id, "PIO0/PIO1");
1.1.1.3   root     2002:                        break;
1.1.1.10  root     2003: 
1.1.1.13  root     2004:                 case ID_MONITOR_RENDERER:
                   2005:                        SetMonitor(id, _("Renderer"));
                   2006:                        break;
                   2007: 
1.1.1.10  root     2008:                 case ID_MONITOR_RTC:
1.1.1.17  root     2009:                 {
                   2010:                        // X68k と virt68k が RTC のモニタ ID を共有している。
                   2011:                        // MK48T02 は NVRAM のモニタ ID を使っているのでここではない。
                   2012:                        wxString name;
                   2013:                        if (gMainApp.IsX68030()) {
                   2014:                                name = "RTC (RP5C15)";
                   2015:                        } else if (gMainApp.IsVIRT68K()) {
                   2016:                                name = "RTC (Goldfish RTC/Timer)";
                   2017:                        } else {
                   2018:                                name = "RTC";
                   2019:                        }
                   2020:                        SetMonitor(id, name);
1.1.1.3   root     2021:                        break;
1.1.1.17  root     2022:                 }
1.1.1.10  root     2023: 
1.1.1.16  root     2024:                 case ID_MONITOR_RTL8019AS0:
                   2025:                 case ID_MONITOR_RTL8019AS1:
                   2026:                 {
1.1.1.18  root     2027:                        uint n = id - ID_MONITOR_RTL8019AS0;
1.1.1.22  root     2028:                        wxString name = string_format("Nereid#%u (RTL8019AS)", n);
1.1.1.16  root     2029:                        SetMonitor(id, name);
                   2030:                        break;
                   2031:                 }
                   2032: 
1.1.1.10  root     2033:                 case ID_MONITOR_SCC:
1.1.1.15  root     2034:                        SetMonitor(id, "SCC (Z8530)");
1.1.1.3   root     2035:                        break;
1.1.1.10  root     2036: 
                   2037:                 case ID_MONITOR_SCHEDULER:
                   2038:                        SetMonitor(id, _("Scheduler"));
1.1       root     2039:                        break;
1.1.1.10  root     2040: 
1.1.1.11  root     2041:                 case ID_MONITOR_SCSIDEVS:
                   2042:                        SetMonitor(id, _("SCSI Devices"));
                   2043:                        break;
                   2044: 
1.1.1.10  root     2045:                 case ID_MONITOR_SIO:
1.1.1.15  root     2046:                        SetMonitor(id, "SIO (uPD7201)");
1.1.1.4   root     2047:                        break;
1.1.1.10  root     2048: 
1.1.1.20  root     2049:                 case ID_MONITOR_SLIRP:
                   2050:                        SetMonitor(id, _("SLIRP Internal States"));
                   2051:                        break;
                   2052: 
1.1.1.24  root     2053:                 case ID_MONITOR_SOUND:
                   2054:                        SetMonitor(id, _("Sound"));
                   2055:                        break;
                   2056: 
1.1.1.10  root     2057:                 case ID_MONITOR_SPC:
1.1.1.15  root     2058:                        SetMonitor(id, "SPC (MB89352)");
1.1.1.2   root     2059:                        break;
1.1.1.10  root     2060: 
1.1.1.18  root     2061:                 case ID_MONITOR_SSG:
                   2062:                        SetMonitor(id, "SSG (YM2149)");
                   2063:                        break;
                   2064: 
1.1.1.10  root     2065:                 case ID_MONITOR_SYSCLK:
                   2066:                        SetMonitor(id, _("System Clock"));
1.1       root     2067:                        break;
1.1.1.10  root     2068: 
1.1.1.17  root     2069:                 case ID_MONITOR_SYSPORT:
                   2070:                        SetMonitor(id, _("System Port"));
                   2071:                        break;
                   2072: 
                   2073:                 case ID_MONITOR_VIRTIO_BLOCK0 ...
                   2074:                      ID_MONITOR_VIRTIO_BLOCK7:
                   2075:                 {
1.1.1.18  root     2076:                        uint n = id - ID_MONITOR_VIRTIO_BLOCK0;
                   2077:                        wxString name = _("VirtIO Block") + string_format(" #%u", n);
1.1.1.17  root     2078:                        SetMonitor(id, name);
                   2079:                        break;
                   2080:                 }
                   2081: 
                   2082:                 case ID_MONITOR_VIRTIO_NET:
                   2083:                        SetMonitor(id, _("VirtIO Network"));
                   2084:                        break;
                   2085: 
1.1.1.21  root     2086:                 case ID_MONITOR_VIRTIO_SCSI:
                   2087:                        SetMonitor(id, "VirtIO SCSI");
                   2088:                        break;
                   2089: 
1.1.1.18  root     2090:                 case ID_MONITOR_VIRTIO_ENTROPY:
                   2091:                        SetMonitor(id, _("VirtIO Entropy"));
                   2092:                        break;
                   2093: 
1.1.1.10  root     2094:                 case ID_MONITOR_WXHOSTINFO:
                   2095:                        SetMonitor(id, _("Host Information"));
1.1       root     2096:                        break;
1.1.1.10  root     2097: 
1.1.1.22  root     2098:                 case ID_MONITOR_XPASCI:
                   2099:                        SetMonitor(id, "HD647180 ASCI");
                   2100:                        break;
                   2101: 
1.1.1.15  root     2102:                 case ID_MONITOR_XPREG:
1.1.1.22  root     2103:                        SetMonitor(id, "HD647180 " + _("Registers"));
1.1.1.15  root     2104:                        break;
                   2105: 
                   2106:                 case ID_MONITOR_XPINTR:
1.1.1.22  root     2107:                        SetMonitor(id, "HD647180 " + _("Interrupts"));
1.1.1.15  root     2108:                        break;
                   2109: 
                   2110:                 case ID_MONITOR_XPIO:
                   2111:                        SetMonitor(id, _("HD647180 Internal Devices"));
                   2112:                        break;
                   2113: 
1.1.1.10  root     2114:                 case ID_SUBWIN_BRHIST:
1.1.1.15  root     2115:                 {
                   2116:                        wxString name = MPUName() + " " + _("Branch History");
1.1.1.21  root     2117:                        try {
                   2118:                                windows[id].reset(new WXScrollMonitorWindow(this, name,
                   2119:                                        gMonitorManager->Get(id)));
                   2120:                        } catch (...) { }
1.1.1.4   root     2121:                        break;
1.1.1.15  root     2122:                 }
1.1.1.10  root     2123: 
                   2124:                 case ID_SUBWIN_EXHIST:
1.1.1.15  root     2125:                 {
                   2126:                        wxString name = MPUName() + " " + _("Exception History");
1.1.1.21  root     2127:                        try {
                   2128:                                windows[id].reset(new WXScrollMonitorWindow(this, name,
                   2129:                                        gMonitorManager->Get(id)));
                   2130:                        } catch (...) { }
1.1.1.5   root     2131:                        break;
1.1.1.15  root     2132:                 }
1.1.1.10  root     2133: 
                   2134:                 case ID_SUBWIN_CACHE0:
                   2135:                 case ID_SUBWIN_CACHE1:
                   2136:                 case ID_SUBWIN_CACHE2:
                   2137:                 case ID_SUBWIN_CACHE3:
                   2138:                 case ID_SUBWIN_CACHE4:
                   2139:                 case ID_SUBWIN_CACHE5:
                   2140:                 case ID_SUBWIN_CACHE6:
                   2141:                 case ID_SUBWIN_CACHE7:
                   2142:                 {
1.1.1.18  root     2143:                        uint n = id - ID_SUBWIN_CACHE0;
1.1.1.10  root     2144:                        wxString name = _("Cache");
1.1.1.18  root     2145:                        name += string_format("#%u", n);
1.1.1.10  root     2146:                        if ((n & 1) == 0) {
                   2147:                                name += _("(Data)");
                   2148:                        } else {
                   2149:                                name += _("(Inst)");
                   2150:                        }
1.1.1.21  root     2151:                        try {
                   2152:                                windows[id].reset(new WXCacheWindow(this, name,
                   2153:                                        gMonitorManager->Get(id)));
                   2154:                        } catch (...) { }
1.1       root     2155:                        break;
1.1.1.10  root     2156:                 }
                   2157: 
1.1.1.15  root     2158:                 case ID_SUBWIN_DIPSW:
1.1.1.21  root     2159:                        try {
                   2160:                                windows[id].reset(new WXDipswWindow(this));
                   2161:                        } catch (...) { }
1.1.1.15  root     2162:                        break;
                   2163: 
1.1.1.23  root     2164:                 case ID_SUBWIN_GVRAM:
1.1.1.21  root     2165:                        try {
1.1.1.23  root     2166:                                windows[id].reset(new WXGVRAMWindow(this, _("Graphic Screen")));
1.1.1.21  root     2167:                        } catch (...) { }
1.1       root     2168:                        break;
1.1.1.21  root     2169: 
1.1.1.23  root     2170:                 case ID_SUBWIN_LCDPANEL:
1.1.1.21  root     2171:                        try {
1.1.1.23  root     2172:                                windows[id].reset(new WXLCDWindow(this));
1.1.1.21  root     2173:                        } catch (...) { }
1.1       root     2174:                        break;
1.1.1.21  root     2175: 
1.1.1.13  root     2176:                 case ID_SUBWIN_LOGSETTING:
1.1.1.21  root     2177:                        try {
                   2178:                                windows[id].reset(new WXLogSettingWindow(this));
                   2179:                        } catch (...) { }
1.1.1.13  root     2180:                        break;
1.1.1.14  root     2181: 
1.1.1.13  root     2182:                 case ID_SUBWIN_LUNAFB:
1.1.1.14  root     2183:                 case ID_SUBWIN_TVRAM:
                   2184:                 {
                   2185:                        // 呼び方が違うので名前と ID が違う
                   2186:                        wxString name;
                   2187:                        if (id == ID_SUBWIN_LUNAFB) {
                   2188:                                name = _("Bitmap Plane");
                   2189:                        } else {
1.1.1.23  root     2190:                                name = _("Text Screen");
1.1.1.14  root     2191:                        }
1.1.1.21  root     2192:                        try {
1.1.1.23  root     2193:                                windows[id].reset(new WXTVRAMWindow(this, name));
1.1.1.21  root     2194:                        } catch (...) { }
1.1.1.14  root     2195:                        break;
                   2196:                 }
                   2197: 
1.1.1.25! root     2198:                 case ID_SUBWIN_MPUPT:
        !          2199:                 {
        !          2200:                        wxString name = MPUName() + " " + _("Page Table");
        !          2201:                        if (MPUName() == "MC68030") {
        !          2202:                                try {
        !          2203:                                        windows[id].reset(new WXPageTable68030Window(this, name));
        !          2204:                                } catch (...) { }
        !          2205:                        } else if (MPUName() == "MC68040") {
        !          2206:                                try {
        !          2207:                                        windows[id].reset(new WXPageTable68040Window(this, name));
        !          2208:                                } catch (...) { }
        !          2209:                        } else {
        !          2210:                                // not supported
        !          2211:                        }
        !          2212:                        break;
        !          2213:                 }
        !          2214: 
1.1.1.17  root     2215:                 case ID_SUBWIN_NEWSIO:
1.1.1.21  root     2216:                        try {
                   2217:                                windows[id].reset(new WXScrollMonitorWindow(this,
                   2218:                                        _("Device Map (NEWS)"),
                   2219:                                        gMonitorManager->Get(id)));
                   2220:                        } catch (...) { }
1.1.1.17  root     2221:                        break;
                   2222: 
1.1.1.15  root     2223:                 case ID_SUBWIN_PALETTE:
1.1.1.21  root     2224:                        try {
1.1.1.23  root     2225:                                windows[id].reset(new WXPaletteWindow(this,
                   2226:                                        _("Palette Colormap")));
1.1.1.21  root     2227:                        } catch (...) { }
1.1.1.15  root     2228:                        break;
                   2229: 
1.1.1.14  root     2230:                 case ID_SUBWIN_ROM:
1.1.1.21  root     2231:                        try {
                   2232:                                windows[id].reset(new WXROMWindow(this));
                   2233:                        } catch (...) { }
1.1       root     2234:                        break;
1.1.1.10  root     2235: 
                   2236:                 case ID_SUBWIN_SOFTKEY:
1.1.1.21  root     2237:                        try {
                   2238:                                windows[id].reset(new WXSoftKeyWindow(this,
                   2239:                                        gMainApp.GetVMType()));
                   2240:                        } catch (...) { }
1.1.1.5   root     2241:                        break;
1.1.1.10  root     2242: 
1.1.1.24  root     2243:                 case ID_SUBWIN_THREADS:
                   2244:                        try {
                   2245:                                windows[id].reset(new WXThreadMonitorWindow(this));
                   2246:                        } catch (...) { }
                   2247:                        break;
                   2248: 
1.1.1.13  root     2249:                 case ID_SUBWIN_VECTOR:
1.1.1.15  root     2250:                 {
                   2251:                        wxString name = MPUName() + " " + _("Vector Table");
1.1.1.21  root     2252:                        try {
                   2253:                                windows[id].reset(new WXScrollMonitorWindow(this, name,
                   2254:                                        gMonitorManager->Get(id)));
                   2255:                        } catch (...) { }
1.1.1.13  root     2256:                        break;
1.1.1.15  root     2257:                 }
                   2258: 
1.1.1.16  root     2259:                 case ID_SUBWIN_X68KIO:
1.1.1.21  root     2260:                        try {
                   2261:                                windows[id].reset(new WXScrollMonitorWindow(this,
                   2262:                                        _("Device Map (24bit space)"),
                   2263:                                        gMonitorManager->Get(id)));
                   2264:                        } catch (...) { }
1.1.1.16  root     2265:                        break;
                   2266: 
1.1.1.15  root     2267:                 case ID_SUBWIN_XPBRHIST:
                   2268:                 {
                   2269:                        wxString name = "HD647180 " + _("Branch History");
1.1.1.21  root     2270:                        try {
                   2271:                                windows[id].reset(new WXScrollMonitorWindow(this, name,
                   2272:                                        gMonitorManager->Get(id)));
                   2273:                        } catch (...) { }
1.1.1.15  root     2274:                        break;
                   2275:                 }
                   2276: 
                   2277:                 case ID_SUBWIN_XPEXHIST:
                   2278:                 {
                   2279:                        wxString name = "HD647180 " + _("Exception History");
1.1.1.21  root     2280:                        try {
                   2281:                                windows[id].reset(new WXScrollMonitorWindow(this, name,
                   2282:                                        gMonitorManager->Get(id)));
                   2283:                        } catch (...) { }
1.1.1.15  root     2284:                        break;
                   2285:                 }
1.1.1.13  root     2286: 
1.1.1.10  root     2287:                 default:
1.1.1.15  root     2288:                        PANIC("'%s' not listed", Monitor::GetIdText(id));
1.1       root     2289:                }
                   2290:                windows[id]->Show();
                   2291:        } else {
                   2292:                // チェックが消えたのでウィンドウを終了
                   2293:                windows[id]->Close();
                   2294:                // (削除自体はこの少し下の DeleteWindow() で行なっている)
                   2295:        }
                   2296: }
                   2297: 
                   2298: // Update UI イベント
                   2299: void
                   2300: WXMainFrame::OnWindowUI(wxUpdateUIEvent& event)
                   2301: {
                   2302:        int id = event.GetId();
                   2303: 
                   2304:        // ウィンドウが存在していればチェックを表示
1.1.1.4   root     2305:        event.Check((bool)windows[id]);
1.1.1.10  root     2306: 
1.1.1.22  root     2307:        // SLIRP モニタだけ無効状態がある。
                   2308: #if defined(HAVE_HOSTNET_SLIRP)
                   2309:        if (__predict_false(id == ID_MONITOR_SLIRP)) {
                   2310:                event.Enable(NetDriverSlirp::IsOccupied());
                   2311:        }
                   2312: #endif
                   2313: 
1.1.1.15  root     2314:        if (IS_MONITOR_MEMDUMP(id) || IS_MONITOR_XPMEMDUMP(id)) {
1.1.1.10  root     2315:                // メニューに現在のアドレスを載せる
1.1.1.15  root     2316:                // (ウィンドウの生存期間外にも呼ばれることに注意)
                   2317:                auto mon = gMonitorManager->Get(id);
1.1.1.19  root     2318:                auto *memdump = dynamic_cast<Memdump *>(mon->obj);
1.1.1.15  root     2319:                assert(memdump);
1.1.1.18  root     2320:                uint32 addr = memdump->GetAddr().Addr();
1.1.1.15  root     2321: 
1.1.1.18  root     2322:                uint n;
1.1.1.15  root     2323:                wxString text = _("Memory Dump");
                   2324:                if (IS_MONITOR_XPMEMDUMP(id)) {
                   2325:                        n = id - ID_MONITOR_XPMEMDUMP0;
1.1.1.18  root     2326:                        text += string_format(" &%u: $%05x", n, addr);
1.1.1.15  root     2327:                } else {
                   2328:                        n = id - ID_MONITOR_MEMDUMP0;
1.1.1.18  root     2329:                        text += string_format(" &%u: $%08x", n, addr);
1.1.1.15  root     2330:                }
                   2331:                event.SetText(text);
1.1.1.10  root     2332:        }
1.1.1.4   root     2333: }
                   2334: 
                   2335: // バージョンダイアログ
                   2336: void
                   2337: WXMainFrame::OnAbout(wxCommandEvent& event)
                   2338: {
                   2339:        WXVersionDlg dlg(this);
                   2340:        dlg.ShowModal();
1.1       root     2341: }
                   2342: 
1.1.1.14  root     2343: // FD を挿入する。
                   2344: void
                   2345: WXMainFrame::InsertFD(int unit, const std::string& path)
                   2346: {
                   2347:        FDDDevice *fdd = fdd_array[unit];
                   2348:        assert(fdd);
                   2349: 
                   2350:        // VM に依頼
                   2351:        // (エラーが起きれば別途 UI メッセージが飛んでくる)
                   2352:        fdd->LoadDiskUI(path);
                   2353: 
                   2354:        // 次回以降のダイアログのカレントディレクトリをここに更新
                   2355:        auto pos = path.rfind('/');
                   2356:        current_dir = path.substr(0, pos);
                   2357: }
                   2358: 
                   2359: // FD をイジェクトする。
                   2360: void
                   2361: WXMainFrame::EjectFD(int unit, bool force)
                   2362: {
                   2363:        FDDDevice *fdd = fdd_array[unit];
                   2364:        assert(fdd);
                   2365: 
                   2366:        fdd->UnloadDiskUI(force);
                   2367: }
                   2368: 
1.1.1.11  root     2369: // CD/MO を挿入する。
1.1       root     2370: void
1.1.1.11  root     2371: WXMainFrame::InsertCD(int id, const std::string& path)
1.1       root     2372: {
1.1.1.11  root     2373:        SCSIDisk *scsidisk = dynamic_cast<SCSIDisk*>(scsidev[id]);
                   2374:        assert(scsidisk);
1.1       root     2375: 
1.1.1.11  root     2376:        // VM に依頼
                   2377:        // (エラーが起きれば別途 UI メッセージが飛んでくる)
                   2378:        scsidisk->LoadDiskUI(path);
                   2379: 
                   2380:        // 次回以降のダイアログのカレントディレクトリをここに更新
                   2381:        auto pos = path.rfind('/');
                   2382:        current_dir = path.substr(0, pos);
1.1       root     2383: }
                   2384: 
1.1.1.11  root     2385: // CD/MO をイジェクトする。
1.1       root     2386: void
1.1.1.11  root     2387: WXMainFrame::EjectCD(int id, bool force)
1.1       root     2388: {
1.1.1.11  root     2389:        SCSIDisk *scsidisk = dynamic_cast<SCSIDisk*>(scsidev[id]);
                   2390:        assert(scsidisk);
                   2391: 
1.1.1.13  root     2392:        scsidisk->UnloadDiskUI(force);
1.1       root     2393: }
                   2394: 
1.1.1.14  root     2395: // CD/MO/FD の挿入失敗メッセージ。
                   2396: // CD/MO と FD でメッセージが同じなので共用する。
1.1.1.4   root     2397: void
1.1.1.14  root     2398: WXMainFrame::OnInsertFailed(wxCommandEvent& event)
1.1.1.4   root     2399: {
1.1.1.11  root     2400:        ::wxMessageBox(_("Cannot load the image file"));
1.1.1.4   root     2401: }
                   2402: 
1.1.1.11  root     2403: // ウィンドウをリストから削除する
                   2404: // (ウィンドウの Close() から呼ばれる)
1.1.1.4   root     2405: void
1.1.1.11  root     2406: WXMainFrame::DeleteWindow(wxWindow *win)
1.1.1.4   root     2407: {
1.1.1.11  root     2408:        for (int id = 0; id < ID_SUBWIN_MAX; id++) {
                   2409:                if (windows[id].get() == win) {
                   2410:                        windows[id].reset();
                   2411:                        break;
                   2412:                }
                   2413:        }
1.1.1.4   root     2414: }
                   2415: 
                   2416: // m680x0 ダブルバスフォールト処理
                   2417: void
                   2418: WXMainFrame::OnHaltNotify(wxCommandEvent& event)
                   2419: {
                   2420:        ::wxMessageBox(_("Double bus fault has occurred in VM"),
                   2421:                wxEmptyString,
                   2422:                wxICON_EXCLAMATION);
                   2423: }
                   2424: 
1.1.1.22  root     2425: // HostNet<n> に対する表示用テキストを返す。
                   2426: wxString
                   2427: WXMainFrame::GetHostNetLabel(uint n) const
                   2428: {
                   2429:        return wxString(string_format("HostNet%u: ", n) +
                   2430:                hostnet[n]->GetPortName());
                   2431: }
                   2432: 
                   2433: // HostCOM<n> に対する表示用テキストを返す。
                   2434: // デバッガ用は呼び出し側で処理すること。
                   2435: wxString
                   2436: WXMainFrame::GetHostComLabel(uint n) const
                   2437: {
                   2438:        assert((int)n >= 0);
                   2439:        return wxString(string_format("HostCom%u: ", n) +
                   2440:                hostcom[n]->GetPortName());
                   2441: }
                   2442: 
                   2443: // メインウィンドウのタイトルを (mousemode によって) 変更する。
                   2444: void
                   2445: WXMainFrame::SetMyTitle(bool mousemode)
                   2446: {
                   2447:        wxString new_title = frame_title;
                   2448:        if (mousemode) {
                   2449:                // メッセージを表示したい
                   2450:                new_title += " (CTRL + F12 to quit mouse mode)";
                   2451:        }
                   2452:        SetTitle(new_title);
                   2453: }
                   2454: 
1.1.1.10  root     2455: // 起動時にオープンするサブウィンドウ (-M オプション)
                   2456: /*static*/ std::array<bool, ID_SUBWIN_MAX> WXMainFrame::subwindow_start;
1.1.1.15  root     2457: 
                   2458: // モニタの更新頻度
                   2459: /*static*/ int WXMainFrame::monitor_rate;

unix.superglobalmegacorp.com

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