Annotation of nono/wx/wxapp.cpp, revision 1.1.1.8

1.1       root        1: //
                      2: // nono
1.1.1.3   root        3: // Copyright (C) 2020 nono project
                      4: // Licensed under nono-license.txt
1.1       root        5: //
                      6: 
1.1.1.8 ! root        7: #include "wxdumpmonitor.h"
1.1       root        8: #include "wxmainframe.h"
                      9: #include "wxmainview.h"
                     10: #include "wxtextpanel.h"
1.1.1.4   root       11: #include "wxversion.h"
1.1       root       12: #include "mainapp.h"
1.1.1.3   root       13: #include "mpu680x0.h"
                     14: #include "mpu88xx0.h"
1.1.1.7   root       15: #include "scheduler.h"
1.1.1.8 ! root       16: #include <algorithm>
1.1.1.3   root       17: #include <wx/intl.h>
1.1       root       18: 
                     19: // イベントタイプの定義
1.1.1.3   root       20: wxDEFINE_EVENT(WXW_EVT_HALT_NOTIFY, wxCommandEvent);
1.1       root       21: 
1.1.1.8 ! root       22: class WXApp : public wxApp
1.1       root       23: {
1.1.1.6   root       24:        using inherited = wxApp;
1.1       root       25:  public:
                     26:        bool OnInit();
1.1.1.6   root       27:        int OnRun() override;
1.1       root       28:  private:
                     29:        bool ParseMonitors(const wxString& str);
1.1.1.8 ! root       30:        void ShowMonitorsName();
1.1       root       31:        int SearchMonitorName(const char *name);
1.1.1.3   root       32: 
                     33:        wxLocale locale;
1.1       root       34: };
                     35: 
1.1.1.3   root       36: // IMPLEMENT_APP() は闇マクロすぎて clang のちからには耐えられない
                     37: #if defined(__clang__)
                     38: #pragma clang diagnostic push
                     39: #pragma clang diagnostic ignored "-Weverything"
                     40: #endif
1.1       root       41: IMPLEMENT_APP(WXApp)
1.1.1.3   root       42: #if defined(__clang__)
                     43: #pragma clang diagnostic pop
                     44: #endif
1.1       root       45: 
                     46: bool
                     47: WXApp::OnInit()
                     48: {
1.1.1.6   root       49:        return true;
                     50: }
                     51: 
                     52: int
                     53: WXApp::OnRun()
                     54: {
1.1.1.5   root       55:        int rv;
                     56: 
1.1.1.7   root       57:        rv = gMainApp.Init1(false, argc, argv);
1.1.1.5   root       58:        if (rv != MainApp::PASS) {
1.1.1.6   root       59:                return rv;
1.1       root       60:        }
                     61: 
1.1.1.3   root       62:        // 環境変数 $NONO_BUILD_HOME が定義されていればカタログ検索パスに
                     63:        // $NONO_BUILD_HOME/po を追加する (システムパスより前に挿入される)。
                     64:        // カタログ開発時にワークツリーにあるカタログを見るため。
                     65:        locale.Init(wxLANGUAGE_DEFAULT);
                     66:        const char *build_home = getenv("NONO_BUILD_HOME");
                     67:        if (build_home) {
                     68:                wxString path(build_home);
                     69:                path += "/po";
                     70:                wxLocale::AddCatalogLookupPathPrefix(path);
                     71:        }
                     72:        locale.AddCatalog("nono");
                     73: 
1.1.1.2   root       74:        // --fontsize テキスト系コントロールのフォントサイズ
                     75:        // 紛らわしいが ::global_fontsize は 12, 16 とかいう値。
1.1.1.4   root       76:        // WXTextPanel::global_fontsize (FontId) は enum 値。
                     77:        FontId fontid;
1.1.1.2   root       78:        switch (gMainApp.fontsize) {
                     79:         case 12:
1.1.1.4   root       80:                fontid = FontId::_6x12;
1.1.1.2   root       81:                break;
                     82:         case 16:
1.1.1.4   root       83:                fontid = FontId::_8x16;
1.1.1.2   root       84:                break;
                     85:         default:
                     86:                warnx("invalid fontsize: %d", gMainApp.fontsize);
1.1.1.7   root       87:                return EXIT_FAILURE;
1.1       root       88:        }
1.1.1.4   root       89:        WXTextPanel::global_fontid = fontid;
                     90: 
                     91:        // グローバルオブジェクト (どこでやるのがいいか)
                     92:        gHostInfo.reset(new HostInfoMonitor());
1.1       root       93: 
1.1.1.8 ! root       94:        // これ以降モニタの登録をしてはいけない。
        !            95:        gMonitorManager.Fix();
        !            96: 
1.1       root       97:        // -M 起動時に表示するモニタ
1.1.1.2   root       98:        if (!gMainApp.monitor_opt.empty()) {
                     99:                if (!ParseMonitors(gMainApp.monitor_opt)) {
1.1.1.7   root      100:                        return EXIT_FAILURE;
1.1       root      101:                }
                    102:        }
                    103: 
1.1.1.2   root      104:        // -s screen scale
                    105:        WXMainView::screen_scale = gMainApp.screen_scale;
1.1       root      106: 
1.1.1.7   root      107:        // 引数処理が終わったので、スレッド作成を伴う初期化。
                    108:        if (!gMainApp.Init2()) {
                    109:                return EXIT_FAILURE;
                    110:        }
                    111: 
                    112:        // VM にコールバックを登録
                    113:        gScheduler->SetPowerOffCallback(wxmainframe_poweroff_callback);
                    114:        if (gMPU680x0) {
                    115:                gMPU680x0->SetHaltCallback(wxmainframe_halt_callback, this);
1.1       root      116:        }
                    117: 
1.1.1.2   root      118:        // メインウィンドウ
                    119:        gMainFrame = new WXMainFrame(NULL);
                    120:        gMainFrame->Show(true);
                    121:        SetTopWindow(gMainFrame);
1.1.1.6   root      122: 
                    123:        return inherited::OnRun();
1.1       root      124: }
                    125: 
                    126: // -M オプションの解析。書式は
1.1.1.8 ! root      127: //  -M <arg>[,<arg>[,...]]
        !           128: // <arg> のどれかが "help" なら有効な名前を列挙して終了。
        !           129: // <arg> は通常モニタ名(サブウィンドウ名)のみだが
        !           130: // memdump* の場合のみ <name>=<hexaddr> 形式を受け付ける。
        !           131: // 継続する場合は true、しない場合は false を返す。
1.1       root      132: bool
                    133: WXApp::ParseMonitors(const wxString& str)
                    134: {
1.1.1.8 ! root      135:        std::vector<std::string> args = string_split(str, ',');
1.1       root      136: 
1.1.1.8 ! root      137:        // "help" があればヘルプを表示して終了
        !           138:        for (const auto& arg : args) {
        !           139:                if (arg == "help") {
        !           140:                        ShowMonitorsName();
        !           141:                        return false;
1.1       root      142:                }
                    143:        }
                    144: 
1.1.1.8 ! root      145:        // 一致するモニタ(ウィンドウ)の開始フラグを立てる
        !           146:        for (const auto& arg : args) {
        !           147:                std::string name;
        !           148:                std::string value;
        !           149: 
        !           150:                auto pos = arg.find('=');
        !           151:                if (pos != std::string::npos) {
        !           152:                        name = arg.substr(0, pos);
        !           153:                        value = arg.substr(++pos);
        !           154:                } else {
        !           155:                        name = arg;
1.1.1.3   root      156:                }
1.1.1.8 ! root      157: 
        !           158:                // この名前のウィンドウを探して start フラグを立てる
        !           159:                int id = SearchMonitorName(name.c_str());
        !           160:                if (id < 0) {
1.1       root      161:                        return false;
                    162:                }
1.1.1.8 ! root      163:                WXMainFrame::subwindow_start[id] = true;
        !           164: 
        !           165:                // 値付き memdump の処理
        !           166:                if (IS_MONITOR_MEMDUMP(id) && value.empty() == false) {
        !           167:                        char *end;
        !           168:                        errno = 0;
        !           169:                        unsigned long u = strtoul(value.c_str(), &end, 16);
        !           170:                        if (end == optarg || end[0] != '\0') {
        !           171:                                warnx("%s: syntax error on monitor address", value.c_str());
        !           172:                                return -1;
        !           173:                        }
        !           174:                        if (errno == ERANGE || u > 0xffffffff) {
        !           175:                                errno = ERANGE;
        !           176:                                warn("%s", value.c_str());
        !           177:                                return -1;
        !           178:                        }
        !           179:                        WXMemdumpWindow::SetStickyAddr(id, (uint32)u);
        !           180:                }
1.1       root      181:        }
                    182:        return true;
                    183: }
                    184: 
1.1.1.8 ! root      185: // モニタ名の一覧を表示する
        !           186: void
        !           187: WXApp::ShowMonitorsName()
        !           188: {
        !           189:        std::vector<int> list;
        !           190: 
        !           191:        // モニターは登録されていれば列挙
        !           192:        // (登録されているものを全部列挙ではないことに注意)
        !           193:        for (int id = ID_MONITOR_START; id <= ID_MONITOR_END; id++) {
        !           194:                if (gMonitorManager.Find(id)) {
        !           195:                        list.push_back(id);
        !           196:                }
        !           197:        }
        !           198:        // サブウィンドウは機種情報から判断
        !           199:        for (int id = ID_SUBWIN_START; id <= ID_SUBWIN_END; id++) {
        !           200:                vmf_t feature = gMonitorManager.GetFeature(id);
        !           201:                if (gMainApp.HasVMFeature(feature)) {
        !           202:                        list.push_back(id);
        !           203:                }
        !           204:        }
        !           205: 
        !           206:        // 一覧を表示
        !           207:        std::string msg = MonitorManager::MakeListString(list);
        !           208:        printf("%s", msg.c_str());
        !           209: }
        !           210: 
        !           211: // モニタ名 name を検索し、一つに確定すればその id を返す。
        !           212: // 確定しない、あるいは一致しない場合はエラーメッセージを表示し -1 を返す。
        !           213: //
        !           214: // "memdump" (数字なし) は空いてる memdump<N> を順に使用する。
        !           215: // ただし今の所この処理は1パスで前から順に処理しているだけなので、
        !           216: // "memdump0,memdump" は指定可能だが(2つ目が memdump1 になる)、
        !           217: // "memdump,memdump0" は memdump0 を2回指定したことになる。
1.1       root      218: int
                    219: WXApp::SearchMonitorName(const char *name)
                    220: {
1.1.1.8 ! root      221:        std::vector<int> candidates;
        !           222:        std::vector<std::string> cand_names;
        !           223: 
        !           224:        for (int id = ID_MONITOR_START; id <= ID_SUBWIN_END; id++) {
        !           225:                if (id < ID_SUBWIN_START) {
        !           226:                        // モニターは登録されていなければ除外する
        !           227:                        if (gMonitorManager.Find(id) == NULL) {
        !           228:                                continue;
        !           229:                        }
        !           230:                } else {
        !           231:                        // サブウィンドウは該当機種でなければ除外する
        !           232:                        vmf_t feature = gMonitorManager.GetFeature(id);
        !           233:                        if (gMainApp.HasVMFeature(feature) == false) {
        !           234:                                continue;
        !           235:                        }
        !           236:                }
        !           237: 
        !           238:                const auto& aliases = gMonitorManager.GetAliases(id);
        !           239: 
        !           240:                bool matched = false;
        !           241:                for (const auto& alias : aliases) {
        !           242:                        // 全文一致したら確定
        !           243:                        // ("lunafb" と "lunafb0" みたいなのがあるため)
        !           244:                        if (alias == name) {
        !           245:                                return id;
        !           246:                        }
        !           247: 
        !           248:                        // 部分一致したら名前はすべて覚えておく
        !           249:                        if (starts_with_ignorecase(alias, name)) {
        !           250:                                cand_names.push_back(alias);
        !           251:                                matched = true;
        !           252:                        }
        !           253:                }
        !           254:                // 同じオブジェクトで別名が複数回部分一致しても、1回として数える
        !           255:                if (matched) {
        !           256:                        candidates.push_back(id);
        !           257:                }
        !           258:        }
        !           259: 
        !           260:        if (candidates.empty()) {
        !           261:                // 一致しない
        !           262:                warnx("Unknown window name \"%s\"", name);
        !           263:                return -1;
        !           264:        } else if (candidates.size() == 1) {
        !           265:                // 部分一致したのが1つだけなら確定
        !           266:                return candidates[0];
        !           267:        } else {
        !           268:                // 候補が複数あった
        !           269: 
        !           270:                // 候補が memdumpN のみなら無記名 memdump とする。
        !           271:                bool is_memdump = std::all_of(candidates.begin(), candidates.end(),
        !           272:                        [](int x) { return IS_MONITOR_MEMDUMP(x); }
        !           273:                );
        !           274:                if (is_memdump) {
        !           275:                        // この時点で空いてるものを返す
        !           276:                        for (int i = 0; i < MAX_MEMDUMP_MONITOR; i++) {
        !           277:                                int id = ID_MONITOR_MEMDUMP0 + i;
        !           278:                                if (WXMainFrame::subwindow_start[id] == false) {
        !           279:                                        return id;
        !           280:                                }
        !           281:                        }
        !           282:                        // 空きがなければエラー
        !           283:                        warnx("No more memdump windows available");
        !           284:                        return -1;
        !           285:                }
        !           286: 
        !           287:                // そうでなければ、候補を表示
        !           288:                std::string candstr;
        !           289:                for (const auto& cname : cand_names) {
        !           290:                        candstr += ' ';
        !           291:                        candstr += cname;
1.1       root      292:                }
1.1.1.8 ! root      293:                warnx("Ambiguous window name \"%s\": candidates are%s",
        !           294:                        name, candstr.c_str());
        !           295:                return -1;
1.1       root      296:        }
                    297: }

unix.superglobalmegacorp.com

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