--- nono/lib/textscreen.h 2026/04/29 17:04:43 1.1.1.6 +++ nono/lib/textscreen.h 2026/04/29 17:05:22 1.1.1.13 @@ -4,32 +4,55 @@ // Licensed under nono-license.txt // +// +// テキストスクリーン +// + #pragma once #include "header.h" +#include // 属性 class TA { public: enum TextAttr : uint { - Normal = 0x00 << 8, - // On, Off, Disable は3ビットを使った状態値。 - // これらが実際どう表現されるかはデバイスによる。 - On = 0x01 << 8, // ビットとかがオンであることを示す - Off = 0x02 << 8, // ビットとかがオフであることを示す - Disable = 0x03 << 8, // 機能などが無効であることを示す - Em = 0x04 << 8, // 値の変化など強調することを示す + // 文字(2バイト)の上位バイトが属性。 + // + // 15 14 13 12 11 10 9 8 + // +---+---+---+---+---+---+---+---+ + // | B | - | Color Code | + // +---+---+---+---+---+---+---+---+ + // + // B はボールド。 + // Color Code は 4bit の前景色・背景色ペアの固定パレット。 + Normal = 0x00 << 8, // 通常描画色 + Reverse = 0x01 << 8, // 反転、背景黒 + Off = 0x02 << 8, // オフを示す + Disable = 0x03 << 8, // 無効を示す + ReverseRed = 0x04 << 8, // 反転、背景赤 + ReverseGreen = 0x05 << 8, // 反転、背景緑 + ReverseOrange = 0x06 << 8, // 反転、背景オレンジ + + Bold = 0x80 << 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; @@ -41,7 +64,8 @@ class TA // // col × row で指定されるテキスト画面。 // 表示可能なのは 0x20..0x7e の printable 文字。 -// 0x20 未満と 0x7f の動作は未定。 +// 及び \n (0x0a) は復帰改行する。 +// それ以外の 0x20 未満と 0x7f の動作は未定。 // 漢字は 2桁占有する。文字列として指定する時は UTF-8 だが、内部コードは // Shift_JIS なので、第一水準、第二水準の文字だけを指定すること。 // @@ -49,15 +73,27 @@ class 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(); @@ -66,54 +102,114 @@ class TextScreen 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文字出力 (上位バイトは属性) - // 出力後カーソルは移動する。移動後画面からはみ出しても何もしない。 - virtual void Putc(uint16 ch); + 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); - // バッファアドレスを取得。(描画デバイス向け) - const uint16 *GetBuf() const { return textbuf.get(); } + // 現在のカーソル位置の文字を取得 + // カーソルは移動する。 + uint16 Getc(); + + // 現在位置の属性を取得 + TA GetAttr() const; + + // 現在位置の属性を attr に設定 + // カーソルは移動しない。 + void SetAttr(TA attr); - // XXX 生バッファを取得 - // バッファの内部構造を変えた場合はこれを呼んでる人については - // 見直しをすること。そのうちなんとかするかも - uint16 *GetRawBuf() { return textbuf.get(); } + // バッファを取得。(描画デバイス向け) + const std::vector& GetBuf() const { return textbuf; } // 現在の X 座標を取得 int GetX() const { return X; } @@ -126,6 +222,9 @@ class TextScreen // 行数を取得 int GetRow() const { return row; } + // 行単位のコピー + void CopyRowsFrom(int dst_y, int row, const TextScreen& src, int src_y); + // ユーザ定義の引数 // ご自由にお使いください。例えばモニタの出力開始オフセットやアドレス // など、呼び出し側が設定して書き出す側がそれに従った内容を出力する @@ -135,7 +234,7 @@ class TextScreen protected: // バッファ (幅x高さちょうどの長さ、ゼロ終端文字列ではない) // 上位8ビットは属性、下位8ビットが文字コード。 - std::unique_ptr textbuf {}; + std::vector textbuf {}; // 幅 int col {}; @@ -148,40 +247,7 @@ class TextScreen // カーソル Y 座標 int Y {}; -}; - -// -// テキストコンソール -// -class TextConsole : public TextScreen -{ - using inherited = TextScreen; - public: - TextConsole(); - virtual ~TextConsole() override; - - // 現在位置に1文字出力 (上位バイトは属性) - // 出力後カーソルは移動する。右端で改行、下端で行スクロールが起きる。 - void Putc(uint16 ch) override; - - private: - // 改行(次の行の左端に移動) - void CRLF(); -}; - -// -// モニターインタフェース -// -// モニターされる側はこのインタフェースを実装すること。 -// -class IMonitor -{ - public: - virtual ~IMonitor(); - - // 自身の現在の状態を TextScreen に書き出す - virtual void MonitorUpdate(TextScreen&) = 0; - // このモニターが必要とするサイズ(桁数×行数)を取得する - virtual nnSize GetMonitorSize() = 0; + // カーソルが画面外に位置するとき true + bool OutOfScreen {}; };