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

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

//
// テキストスクリーン
//

#pragma once

#include "header.h"
#include <vector>

// 属性
class TA
{
 public:
	enum TextAttr : uint {
		// 文字(2バイト)の上位バイトが属性。
		//
		//  15  14  13  12  11  10   9   8
		// +---+---+---+---+---+---+---+---+
		// | B |     -     |  Color Code   |
		// +---+---+---+---+---+---+---+---+
		//
		// B はボールド。
		// Color Code は 4bit の前景色・背景色ペアの固定パレット。
		Normal			= 0x00U << 8,	// 通常描画色
		Reverse			= 0x01U << 8,	// 反転、背景黒
		Off				= 0x02U << 8,	// オフを示す
		Disable			= 0x03U << 8,	// 無効を示す
		ReverseRed		= 0x04U << 8,	// 反転、背景赤
		ReverseGreen	= 0x05U << 8,	// 反転、背景緑
		ReverseOrange	= 0x06U << 8,	// 反転、背景オレンジ

		Bold			= 0x80U << 8,	// ボールド

		// エイリアス
		On				= Reverse,			// オンは反転で表現している
		Em				= Bold | Normal,	// 通常色 + 強調のショートカット
	} attr {};

	TA() { }
	TA(TextAttr attr_) : attr(attr_) { }
	// uint からのコンストラクタ
	TA(uint attr_) : TA((TextAttr)attr_) { }

	// uint へのキャスト
	operator uint() const {
		return (uint)attr;
	}

	// static member
	// val によって On か Off を返す
	static const TA OnOff(bool val) {
		return (val) ? TA::On : TA::Off;
	}
};

//
// テキストスクリーン
//
// col × row で指定されるテキスト画面。
// 表示可能なのは 0x20..0x7e の printable 文字。
// 及び \n (0x0a) は復帰改行する。
// それ以外の 0x20 未満と 0x7f の動作は未定。
// 漢字は 2桁占有する。文字列として指定する時は UTF-8 だが、内部コードは
// Shift_JIS なので、第一水準、第二水準の文字だけを指定すること。
//
// TextScreen() コンストラクタで作成して Init(col, row) するか、
// TextScreen(col, row) コンストラクタを呼ぶかどちらか選択。
// チェックとかはしていないので併用しないこと。
//
// Locate などにより範囲外にカーソルを移動することはできる。
// ただしその位置を始点としての文字出力は無視される。
class TextScreen final
{
 public:
	// 文字の送りモード
	enum ModeKind {
		// 右端は無視される
		Fixed,
		// 右端は次の行に改行し、最終行だったときは上スクロールする
		Console,
		// 右端は次の行に改行し、最終行右端は左上に戻る
		Ring,
	} Mode { Fixed };

	TextScreen();
	TextScreen(int col, int row);
	~TextScreen();

	// 初期化
	void Init(int col, int row, ModeKind mode = ModeKind::Fixed);

	// 画面をクリアして、カーソルをホームポジションに移動
	void Clear();

	// 現在位置を移動
	void Locate(int x, int y) {
		X = x;
		Y = y;
		OutOfScreen = (X < 0 || X >= col || Y < 0 || Y >= row);
	}
	void SetX(int x) {
		X = x;
		OutOfScreen = (X < 0 || X >= col);
	}
	void SetY(int y) {
		Y = y;
		OutOfScreen = (Y < 0 || Y >= row);
	}

	// 文字出力後の右移動
	void Ascend();

	// 復帰
	void CR() noexcept {
		X = 0;
	}

	// 改行
	void LF();

	// 復帰改行
	void CRLF() {
		CR();
		LF();
	}

	// 1行の上スクロール
	void ScrollUp();

	//
	// 出力関数群
	// 出力関数はカーソル位置を更新する。
	//

	// 現在位置に1文字出力 (上位バイトは属性)
	void Putc(uint16 ch);

	// 座標を指定して1文字出力 (上位バイトは属性)
	void Putc(int x, int y, uint16 ch) {
		Locate(x, y);
		Putc(ch);
	}

	// 座標と属性を指定して1文字出力
	void Putc(int x, int y, TA attr, uint16 ch) {
		Locate(x, y);
		Putc((uint)attr | ch);
	}

	// 現在位置に文字列を出力
	void Puts(const char *str);

	// 現在位置に指定の属性で文字列を出力
	void Puts(TA attr, const char *str);

	// 座標を指定して文字列を出力
	void Puts(int x, int y, const char *str) {
		Locate(x, y);
		Puts(str);
	}

	// 座標と属性を指定して、文字列を出力
	void Puts(int x, int y, TA attr, const char *str) {
		Locate(x, y);
		Puts(attr, str);
	}

	// 現在位置に属性なしで書式付き文字列を出力
	void Print(const char *fmt, ...) __printflike(2, 3);

	// 座標を指定して属性なしで書式付き文字列を出力
	void Print(int x, int y, const char *fmt, ...) __printflike(4, 5);

	// 座標と属性を指定して、書式付き文字列を出力
	void Print(int x, int y, TA attr, const char *fmt, ...)
		__printflike(5, 6);

	// 現在のカーソル位置の文字を取得
	// カーソルは移動しない。
	uint16 Getc();

	// 現在のカーソル位置に文字を出力。
	// カーソルは移動しない。ch がカーソル移動を伴う制御文字なら動作不定。
	void Setc(uint16 ch);

	// 指定のカーソル位置に文字を出力。
	// カーソルは移動しない。ch がカーソル移動を伴う制御文字なら動作不定。
	void Setc(int x, int y, uint16 ch);

	// 現在位置の属性を取得
	TA GetAttr() const;

	// 現在位置の属性を attr に設定
	// カーソルは移動しない。
	void SetAttr(TA attr);

	// バッファを取得。(描画デバイス向け)
	const std::vector<uint16>& GetBuf() const { return textbuf; }

	// 現在の X 座標を取得
	int GetX() const noexcept { return X; }
	// 現在の Y 座標を取得
	int GetY() const noexcept { return Y; }

	// 桁数を取得
	int GetCol() const noexcept { return col; }

	// 行数を取得
	int GetRow() const noexcept { return row; }

	// 行単位のコピー
	void CopyRowsFrom(int dst_y, int row, const TextScreen& src, int src_y);

	// ユーザ定義の引数
	// ご自由にお使いください。例えばモニタの出力開始オフセットやアドレス
	// など、呼び出し側が設定して書き出す側がそれに従った内容を出力する
	// ような用途。
	uint64 userdata {};

 private:
	// バッファ (幅x高さちょうどの長さ、ゼロ終端文字列ではない)
	// 上位8ビットは属性、下位8ビットが文字コード。
	std::vector<uint16> textbuf {};

	// 幅
	int col {};

	// 高さ
	int row {};

	// カーソル X 座標
	int X {};

	// カーソル Y 座標
	int Y {};

	// カーソルが画面外に位置するとき true
	bool OutOfScreen {};
};

unix.superglobalmegacorp.com

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