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