File:  [Isaki's NoNo m68k/m88k emulator] / nono / lib / monitor.cpp
Revision 1.1.1.8 (vendor branch): download - view: text, annotated - select for diffs
Wed Apr 29 17:05:56 2026 UTC (2 months, 3 weeks ago) by root
Branches: MAIN, Isaki
CVS tags: v027, HEAD
nono 1.7.0

//
// nono
// Copyright (C) 2021 nono project
// Licensed under nono-license.txt
//

//
// モニタ管理
//

#include "monitor.h"
#include <algorithm>

//
// モニター
//

// コンストラクタ
Monitor::Monitor()
{
}

// コンストラクタ
Monitor::Monitor(uint id_, Object *obj_)
{
	id = id_;
	obj = obj_;
}

// デストラクタ
Monitor::~Monitor()
{
}

// ID を表示用文字列にして返す
/*static*/ const char *
Monitor::GetIdText(uint target_id)
{
	for (const auto& p : idtext) {
		uint id = p.first;
		const char *text = p.second;

		if (id == target_id) {
			return text;
		}
	}
	return "unknownID?";
}


//
// モニターマネージャ
//

// グローバル参照用
MonitorManager *gMonitorManager;

// コンストラクタ
MonitorManager::MonitorManager()
{
}

// デストラクタ
MonitorManager::~MonitorManager()
{
	gMonitorManager = NULL;
}

// モニタを登録。
Monitor *
MonitorManager::Regist(uint id_, Object *parent_)
{
	return RegistCommon(id_, parent_, NULL);
}

// 呼び出し側で作成したモニタを登録。
Monitor *
MonitorManager::Regist(Monitor *monitor_)
{
	return RegistCommon(monitor_->GetId(), monitor_->obj, monitor_);
}

// id_, parent_ のモニタを登録。
// monitor_ は通常 NULL を指定しておけばこちらで標準モニタを作成する。
// 呼び出し元で派生クラスなどを生成していればそれを指定。
// 成功すればモニターを返す。通常失敗しない。
// 失敗すればいずれのケースも assert で終了する。
Monitor *
MonitorManager::RegistCommon(uint id_, Object *parent_, Monitor *monitor_)
{
	assert(id_ < ID_SUBWIN_MAX);

	// 追加が遅すぎる。
	assert(fixed == false);

	// 二重登録防止。
	assertmsg((bool)monitors[id_] == false,
		"%s already registered", Monitor::GetIdText(id_));

	// 登録、もしくはここで生成。
	if (monitor_) {
		monitors[id_].reset(monitor_);
	} else {
		monitors[id_].reset(new Monitor(id_, parent_));
		assertmsg((bool)monitors[id_], "cannot create new monitor");
	}

	// 名前が衝突していないことを確認。
	// どのケースの衝突も検出できるよう、追加後に全部列挙して..
	std::vector<std::string> names;
	for (const auto& uptr : monitors) {
		if ((bool)uptr) {
			const Monitor *m = uptr.get();
			const std::vector<std::string>& aliases = GetAliases(m->GetId());
			names.insert(names.end(), aliases.begin(), aliases.end());
		}
	}
	if (names.size() > 1) {
		// ソートして..
		std::sort(names.begin(), names.end());
		// 同じものが並んでいないか。
		for (int i = 0, sz = names.size() - 1; i < sz; i++) {
			assertmsg(names[i] != names[i + 1],
				"monitor alias \"%s\" duplicated", names[i].c_str());
		}
	}

	return monitors[id_].get();
}

// mon がリストにあれば削除する。なければ何もしない。
void
MonitorManager::Unregist(Monitor *mon)
{
	uint id = mon->GetId();
	monitors[id].reset();
}


// これ以降は追加禁止
void
MonitorManager::Fix()
{
	assert(fixed == false);

	fixed = true;

	// デバッグ用。
	if (0) {
		uint i = 0;
		for (const auto& uptr : monitors) {
			if ((bool)uptr) {
				const Monitor *m = uptr.get();
				auto sz = m->GetSize();
				printf("[%2u] %s\t%d,%d\n", i++, m->GetIdText(),
					sz.width, sz.height);
			}
		}
	}
}

// 指定された id を持つモニターを返す。
// こっちは、なければ assert する。
Monitor *
MonitorManager::Get(uint id) const
{
	Monitor *mon = Find(id);
	assertmsg(mon, "id=%u not found", id);
	return mon;
}

// 現在登録されているモニターの一覧を返す。
const std::vector<Monitor *>
MonitorManager::GetList() const
{
	std::vector<Monitor *> list;

	for (auto& uptr : monitors) {
		if ((bool)uptr) {
			list.push_back(uptr.get());
		}
	}

	return list;
}

// id リストから一覧表示用の文字列リストを生成して返す
std::vector<std::string>
MonitorManager::MakeListString(std::vector<uint> list) const
{
	std::vector<std::string> rv;

	// id をモニター情報内の1つ目の名前順にソートする
	std::sort(list.begin(), list.end(),
		[&](const auto& a_id, const auto& b_id) {
			const auto& a_alias = GetAliases(a_id);
			const auto& b_alias = GetAliases(b_id);
			const std::string a_name = a_alias[0];
			const std::string b_name = b_alias[0];

			return strcmp(a_name.c_str(), b_name.c_str()) < 0;
		}
	);

	for (const auto id : list) {
		const auto& aliases = GetAliases(id);
		assert(aliases.empty() == false);

		std::string str = aliases[0];
		if (aliases.size() > 1) {
			str += " (alias:";
			for (int i = 1, sz = aliases.size(); i < sz; i++) {
				str += ' ';
				str += aliases[i];
			}
			str += ')';
		}
		rv.push_back(str);
	}
	return rv;
}

unix.superglobalmegacorp.com

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