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

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

unix.superglobalmegacorp.com

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