|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.