--- nono/lib/textscreen.h 2026/04/29 17:04:28 1.1 +++ nono/lib/textscreen.h 2026/04/29 17:05:08 1.1.1.9 @@ -1,19 +1,67 @@ // // nono -// Copyright (C) 2018 isaki@NetBSD.org +// Copyright (C) 2020 nono project +// Licensed under nono-license.txt +// + +// +// テキストスクリーン // #pragma once +#include "header.h" +#include + // 属性 -enum TA { - Normal = 0x00 << 8, - // On, Off, Disable は3ビットを使った状態値。 - // これらが実際どう表現されるかはデバイスによる。 - On = 0x01 << 8, // ビットとかがオンであることを示す - Off = 0x02 << 8, // ビットとかがオフであることを示す - Disable = 0x03 << 8, // 機能などが無効であることを示す - Em = 0x04 << 8, // 値の変化など強調することを示す +class TA +{ + public: + enum TextAttr : uint { + Normal = 0x00 << 8, + // スイッチ用機能ビット + // On, Off, Disable は2ビットを使った3状態値。 + // これらが実際どう表現されるかはデバイスによる。 + On = 0x01 << 8, // ビットとかがオンであることを示す + Off = 0x02 << 8, // ビットとかがオフであることを示す + Disable = 0x03 << 8, // 機能などが無効であることを示す + // On, Off, Disable のスイッチ用機能のビットマスク + SwitchMask = 0x03 << 8, + + // Em は独立したビットによる状態。 + Em = 0x04 << 8, // 値の変化など強調することを示す + } attr {}; + + TA() { } + TA(TextAttr attr_) : attr(attr_) { } + // uint からのコンストラクタ + TA(uint attr_) : TA((TextAttr)attr_) { } + + // uint へのキャスト + operator uint() const { + return (uint)attr; + } + + // スイッチ用機能ビット部を返す。 + TextAttr GetSwitch() const { + return (TextAttr)(attr & SwitchMask); + } + + // スイッチ用機能ビット部を設定する。 + void SetSwitch(TextAttr a) { + attr = (TextAttr)((attr & ~SwitchMask) | (a & SwitchMask)); + } + + // スイッチ用機能ビットの状態を調べる。 + bool IsOn() const { return GetSwitch() == TA::On; } + bool IsOff() const { return GetSwitch() == TA::Off; } + bool IsDisable() const { return GetSwitch() == TA::Disable; } + + // static member + // val によって On か Off を返す + static const TA OnOff(bool val) { + return (val) ? TA::On : TA::Off; + } }; // @@ -21,7 +69,8 @@ enum TA { // // col × row で指定されるテキスト画面。 // 表示可能なのは 0x20..0x7e の printable 文字。 -// 0x20 未満と 0x7f の動作は未定。 +// 及び \n (0x0a) は復帰改行する。 +// それ以外の 0x20 未満と 0x7f の動作は未定。 // 漢字は 2桁占有する。文字列として指定する時は UTF-8 だが、内部コードは // Shift_JIS なので、第一水準、第二水準の文字だけを指定すること。 // @@ -29,42 +78,136 @@ enum TA { // TextScreen(col, row) コンストラクタを呼ぶかどちらか選択。 // チェックとかはしていないので併用しないこと。 // +// Locate などにより範囲外にカーソルを移動することはできる。 +// ただしその位置を始点としての文字出力は無視される。 class TextScreen { public: + // 文字の送りモード + enum ModeKind { + // 右端は無視される + Fixed, + // 右端は次の行に改行し、最終行だったときは上スクロールする + Console, + // 右端は次の行に改行し、最終行右端は左上に戻る + Ring, + } Mode { Fixed }; + TextScreen(); TextScreen(int col, int row); virtual ~TextScreen(); // 初期化 - void Init(int col, int row); + 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 Ascend() { + X++; + if (X >= col) { + switch (Mode) { + case Fixed: + OutOfScreen = true; + break; + case Console: + case Ring: + CRLF(); + break; + } + } + } + + // 復帰改行 + void CRLF() + { + X = 0; + 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 ScrollUp(); + + // + // 出力関数群 + // 出力関数はカーソル位置を更新する。 + // + // 現在位置に1文字出力 (上位バイトは属性) void Putc(uint16 ch); - // 現在位置に字列を出力 + // 現在位置に文字列を出力 void Puts(const char *str); // 現在位置に指定の属性で文字列を出力 - void Puts(uint attr, 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, uint attr, const char *fmt, ...) + void Print(int x, int y, TA attr, const char *fmt, ...) __printflike(5, 6); - // バッファアドレスを取得。(描画デバイス向け) - const uint16 *GetBuf() const { return textbuf; } - - // XXX 生バッファを取得 - // バッファの内部構造を変えた場合はこれを呼んでる人については - // 見直しをすること。そのうちなんとかするかも - uint16 *GetRawBuf() { return textbuf; } + // 現在のカーソル位置の文字を取得 + // カーソルは移動する。 + uint16 Getc(); + + // 現在位置の属性を取得 + TA GetAttr() const; + + // 現在位置の属性を attr に設定 + // カーソルは移動しない。 + void SetAttr(TA attr); + + // バッファを取得。(描画デバイス向け) + const std::vector& GetBuf() const { return textbuf; } + + // 現在の X 座標を取得 + int GetX() const { return X; } + // 現在の Y 座標を取得 + int GetY() const { return Y; } // 桁数を取得 int GetCol() const { return col; } @@ -72,20 +215,29 @@ class TextScreen // 行数を取得 int GetRow() const { return row; } - private: + // ユーザ定義の引数 + // ご自由にお使いください。例えばモニタの出力開始オフセットやアドレス + // など、呼び出し側が設定して書き出す側がそれに従った内容を出力する + // ような用途。 + uint64 userdata {}; + + protected: // バッファ (幅x高さちょうどの長さ、ゼロ終端文字列ではない) // 上位8ビットは属性、下位8ビットが文字コード。 - uint16 *textbuf = NULL; + std::vector textbuf {}; // 幅 - int col = 0; + int col {}; // 高さ - int row = 0; + int row {}; // カーソル X 座標 - int X = 0; + int X {}; // カーソル Y 座標 - int Y = 0; + int Y {}; + + // カーソルが画面外に位置するとき true + bool OutOfScreen {}; };