File:  [Isaki's NoNo m68k/m88k emulator] / nono / lib / textscreen.cpp
Revision 1.1.1.12 (vendor branch): download - view: text, annotated - select for diffs
Wed Apr 29 17:05:30 2026 UTC (2 months, 3 weeks ago) by root
Branches: MAIN, Isaki
CVS tags: v027, v026, v025, v024, v023, v022, v021, HEAD
nono 1.1.0

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

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

#include "textscreen.h"

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

// コンストラクタ
TextScreen::TextScreen(int arg_col, int arg_row)
{
	Init(arg_col, arg_row);
}

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

// 初期化
void
TextScreen::Init(int arg_col, int arg_row, ModeKind mode)
{
	assert(arg_col > 0);
	assert(arg_row > 0);

	col = arg_col;
	row = arg_row;
	Mode = mode;

	textbuf.resize(col * row);
	X = 0;
	Y = 0;

	Clear();
}

// クリア
void
TextScreen::Clear()
{
	for (int i = 0; i < col * row; i++) {
		textbuf[i] = 0x0020;
	}

	// ホームポジション
	Locate(0, 0);
}

// 文字出力後の右移動。
void
TextScreen::Ascend()
{
	X++;
	if (X >= col) {
		switch (Mode) {
		 case Fixed:
			OutOfScreen = true;
			break;
		 case Console:
		 case Ring:
			CRLF();
			break;
		}
	}
}

// 改行。
void
TextScreen::LF()
{
	Y++;
	switch (Mode) {
	 case Fixed:
		break;
	 case Console:
		if (Y >= row) {
			ScrollUp();
			Y = row - 1;
		}
		break;
	 case Ring:
		if (Y >= row) {
			Y = 0;
		}
		break;
	}

	// どのモードであっても OutOfScreen を更新
	// (Y=-1 から CRLF したら表示可能になるべき)
	OutOfScreen = (Y < 0 || Y >= row);
}

// 1 行上スクロール
void
TextScreen::ScrollUp()
{
	memmove(&textbuf[0], &textbuf[col],
		(row - 1) * col * sizeof(textbuf[0]));
	for (int i = 0; i < col; i++) {
		textbuf[(row - 1) * col + i] = 0x0020;
	}
}


// 現在のカーソル位置に1文字出力する。
void
TextScreen::Putc(uint16 ch)
{
	if (ch == '\n') {
		CRLF();
		return;
	}

	if (OutOfScreen) {
		return;
	}

	textbuf[(Y * col) + X] = ch;
	Ascend();
}

// 現在のカーソル位置の文字を取得。
// カーソルは移動しない。
// カーソルが範囲外だったときは 0 を返す。
uint16
TextScreen::Getc()
{
	if (OutOfScreen) {
		return 0;
	}

	return textbuf[(Y * col) + X];
}

// テキストスクリーンに文字列を出力する。
void
TextScreen::Puts(const char *str)
{
	while (*str != '\0') {
		uint16 ch = (uint8)*str++;
		Putc(ch);
	}
}

// テキストスクリーンに文字列を出力する。
void
TextScreen::Puts(TA attr, const char *str)
{
	while (*str != '\0') {
		Putc(((uint)attr) | *str++);
	}
}

// テキストスクリーンの現在位置から書式付き文字列を出力する。
void
TextScreen::Print(const char *fmt, ...)
{
	char buf[1024];
	va_list ap;

	va_start(ap, fmt);
	vsnprintf(buf, sizeof(buf), fmt, ap);
	va_end(ap);

	Puts(buf);
}

// テキストスクリーンに座標を指定して書式付き文字列を出力する。
void
TextScreen::Print(int x, int y, const char *fmt, ...)
{
	char buf[1024];
	va_list ap;

	va_start(ap, fmt);
	vsnprintf(buf, sizeof(buf), fmt, ap);
	va_end(ap);

	Locate(x, y);
	Puts(buf);
}

// テキストスクリーンに座標と属性を指定して、書式付き文字列を出力する。
void
TextScreen::Print(int x, int y, TA attr, const char *fmt, ...)
{
	char buf[1024];
	va_list ap;

	va_start(ap, fmt);
	vsnprintf(buf, sizeof(buf), fmt, ap);
	va_end(ap);

	Locate(x, y);
	Puts(attr, buf);
}

// 現在のカーソル位置に文字を出力。
// カーソルは移動しない。ch がカーソル移動を伴う制御文字なら動作不定。
void
TextScreen::Setc(uint16 ch)
{
	textbuf[(Y * col) + X] = ch;
}

// 指定のカーソル位置に文字を出力。
// カーソルは移動しない。ch がカーソル移動を伴う制御文字なら動作不定。
void
TextScreen::Setc(int x, int y, uint16 ch)
{
	textbuf[(y * col) + x] = ch;
}

// 現在位置の属性を取得
// カーソルが画面外の場合は TA::Normal を返す。
TA
TextScreen::GetAttr() const
{
	if (OutOfScreen) {
		return TA::Normal;
	}

	return TA(textbuf[(Y * col) + X] & 0xff00);
}

// 現在位置の属性を attr に設定する。
// カーソルは移動しない。
void
TextScreen::SetAttr(TA attr)
{
	if (OutOfScreen) {
		return;
	}

	auto& ch = textbuf[(Y * col) + X];
	ch = (ch & 0xff) | (uint)attr;
}

// src の src_y 行目から rows 行をこのスクリーンの dst_y 行目以降にコピーする。
// 双方のカーソルは移動しない。
// もし row がどちらかではみ出た場合はコピーをそこで終了する。
// src と dst (この screen) の桁数が違うと assert する。
void
TextScreen::CopyRowsFrom(int dst_y, int rows, const TextScreen& src, int src_y)
{
	assert(GetCol() == src.GetCol());

	const auto& srcbuf = src.GetBuf();

	// rows を小さいほうに揃える。
	if (rows > GetRow() - dst_y) {
		rows = GetRow() - dst_y;
	}
	if (rows > src.GetRow() - src_y) {
		rows = src.GetRow() - src_y;
	}

	// 内部構造を知っているので一気にコピー。
	memcpy(&textbuf[dst_y * col], &srcbuf[src_y * col],
		sizeof(textbuf[0]) * col * rows);
}

unix.superglobalmegacorp.com

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