--- nono/lib/textscreen.cpp 2026/04/29 17:05:08 1.1.1.9 +++ nono/lib/textscreen.cpp 2026/04/29 17:05:30 1.1.1.12 @@ -56,6 +56,50 @@ TextScreen::Clear() 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() @@ -85,8 +129,8 @@ TextScreen::Putc(uint16 ch) Ascend(); } -// 現在のカーソル位置の文字を取得 -// カーソルは移動する。 +// 現在のカーソル位置の文字を取得。 +// カーソルは移動しない。 // カーソルが範囲外だったときは 0 を返す。 uint16 TextScreen::Getc() @@ -95,9 +139,7 @@ TextScreen::Getc() return 0; } - uint16 ch = textbuf[(Y * col) + X]; - Ascend(); - return ch; + return textbuf[(Y * col) + X]; } // テキストスクリーンに文字列を出力する。 @@ -105,7 +147,8 @@ void TextScreen::Puts(const char *str) { while (*str != '\0') { - Putc(*str++); + uint16 ch = (uint8)*str++; + Putc(ch); } } @@ -162,6 +205,22 @@ TextScreen::Print(int x, int y, TA attr, 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 @@ -186,3 +245,27 @@ TextScreen::SetAttr(TA attr) 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); +}