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