# 機能設計書 100-画面バッファ管理

## 概要

本ドキュメントは、Console Host における画面バッファ管理（SCREEN_INFORMATION）の機能設計を記述する。コンソールの画面バッファの作成、ビューポート管理、カーソル制御、フォント管理、スクロールバー、代替バッファ切替の構造と動作を解説する。

### 本機能の処理概要

SCREEN_INFORMATION クラスは、Console Host の画面出力バッファを管理する中核コンポーネントである。TextBuffer（テキストデータの実体）を所有し、Viewport（表示領域）、Cursor（カーソル位置・形状）、Font（フォント情報）、StateMachine（VTパーサー）を統合して、コンソール画面の全側面を制御する。ConsoleObjectHeader と IIoProvider を継承し、Console API のオブジェクト管理フレームワークに統合される。

**業務上の目的・背景**：Console APIを使用するCUIアプリケーション（cmd.exe、PowerShell等）は、画面バッファを通じて出力を表示する。SCREEN_INFORMATION はこれらのAPIのバックエンドとして、バッファのサイズ管理、ビューポートのスクロール、カーソルの位置管理、フォントの変更、および VT シーケンス処理のための StateMachine を提供する。代替バッファ（Alternate Screen Buffer）をサポートし、vi や less 等のフルスクリーンアプリケーションとの互換性を確保する。

**機能の利用シーン**：CUIアプリケーションが WriteConsole でテキストを出力する際、SCREEN_INFORMATION が管理する TextBuffer にデータが書き込まれ、Viewport 経由でレンダラーに表示される。ウィンドウリサイズ時にはバッファサイズとビューポートの再計算が行われる。ConPTYモードではバッファがビューポートサイズに固定される。

**主要な処理内容**：
1. 画面バッファの作成（CreateInstance）とリンクリスト管理
2. TextBuffer の所有と管理（リサイズ、リフロー）
3. Viewport（表示領域）の位置・サイズ制御
4. カーソルの位置設定、形状変更、可視制御
5. フォント管理とレンダラー連携
6. スクロールバー状態の計算と更新
7. 代替バッファ（Alternate Screen Buffer）の作成・切替・破棄
8. StateMachine（VTパーサー）の初期化と所有
9. ウィンドウリサイズ処理（バッファ調整、ビューポート調整、リフロー）
10. VirtualBottom によるターミナルスクロールモード対応
11. ConPTY カーソル位置同期

**関連システム・外部連携**：Console API（GetConsoleScreenBufferInfo / SetConsoleScreenBufferSize / SetConsoleCursorPosition 等）の画面出力側バックエンド。TextBuffer と連携してテキストデータを保持し、Renderer と連携して画面に描画する。StateMachine を所有してVTシーケンスの解析を行う。ConPTYモードでは VtIo と連携する。

**権限による制御**：OutputMode フラグ（ENABLE_PROCESSED_OUTPUT, ENABLE_WRAP_AT_EOL_OUTPUT, ENABLE_VIRTUAL_TERMINAL_PROCESSING 等）による出力処理モード制御。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | conhost.exe ウィンドウ | 主画面 | テキスト出力の表示、スクロール操作 |

## 機能種別

データ管理 / 画面バッファリング

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| windowSize | til::size | Yes | 初期ウィンドウサイズ（文字単位） | 正の整数 |
| fontInfo | FontInfo | Yes | 初期フォント情報 | - |
| screenBufferSize | til::size | Yes | 初期バッファサイズ（文字単位） | SHORT_MAX未満 |
| defaultAttributes | TextAttribute | Yes | デフォルトテキスト属性 | - |
| popupAttributes | TextAttribute | Yes | ポップアップ用テキスト属性 | - |
| cursorSize | UINT | Yes | カーソルサイズ（パーセント） | - |
| Position | til::point | Yes | カーソル位置（SetCursorPosition用） | バッファ範囲内 |

### 入力データソース

- Console API（CreateConsoleScreenBuffer / SetConsoleScreenBufferSize 等）からのサイズ指定
- ウィンドウメッセージからのリサイズイベント
- VTシーケンスからの代替バッファ切替指示（DECSET 1049）
- ConPTYからのビューポートリサイズ

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| バッファ情報 | til::size, til::point, til::inclusive_rect | GetScreenBufferInformation で返却 |
| テキストデータ | TextBufferCellIterator | GetCellDataAt で返却 |
| ビューポート | Viewport | GetViewport で返却 |
| スクロールバー状態 | ScrollBarState | FetchScrollBarState で返却 |

### 出力先

Console API応答（GetConsoleScreenBufferInfo等）、レンダラー（GDI/Atlas/VtIo）への描画指示

## 処理フロー

### 処理シーケンス

```
1. CreateInstance() - 画面バッファ作成
   ├─ SCREEN_INFORMATION コンストラクタ
   ├─ Viewport 初期化（PTYモードならバッファサイズ、それ以外はウィンドウサイズ）
   ├─ TextBuffer 作成（coordScreenBufferSize, defaultAttributes, cursorSize）
   ├─ カーソルタイプ設定
   └─ _InitializeOutputStateMachine()
       ├─ AdaptDispatch 作成
       ├─ OutputStateMachineEngine 作成
       └─ StateMachine 作成
2. s_InsertScreenBuffer() - グローバルリンクリストに追加
3. ProcessResizeWindow() - ウィンドウリサイズ処理
   ├─ _AdjustScreenBuffer() - バッファサイズ調整
   ├─ _CalculateViewportSize() - ビューポート再計算
   ├─ _AdjustViewportSize() - ビューポート適用
   └─ UpdateScrollBars() - スクロールバー更新
4. UseAlternateScreenBuffer() - 代替バッファ切替
   ├─ _CreateAltBuffer() - 代替バッファ作成
   ├─ カーソルスタイル・位置コピー
   ├─ s_InsertScreenBuffer() - リストに追加
   └─ SetActiveScreenBuffer() - アクティブバッファ切替
5. UseMainScreenBuffer() - メインバッファ復帰
   ├─ _handleDeferredResize() - 遅延リサイズ処理
   ├─ SetActiveScreenBuffer() - アクティブバッファ切替
   ├─ カーソルスタイルコピーバック
   └─ s_RemoveScreenBuffer() - 代替バッファ削除
```

### フローチャート

```mermaid
flowchart TD
    A[CreateInstance呼出] --> B[コンストラクタ: OutputMode初期化]
    B --> C{PTYモード?}
    C -->|Yes| D[Viewport = バッファサイズ]
    C -->|No| E[Viewport = ウィンドウサイズ]
    D --> F[TextBuffer作成]
    E --> F
    F --> G[StateMachine初期化]
    G --> H[s_InsertScreenBuffer]
    H --> I[画面バッファ使用開始]

    J[ウィンドウリサイズ] --> K[_AdjustScreenBuffer]
    K --> L{WrapText?}
    L -->|Yes| M[バッファ幅=ウィンドウ幅]
    L -->|No| N[バッファサイズ維持]
    M --> O[_CalculateViewportSize]
    N --> O
    O --> P[_AdjustViewportSize]
    P --> Q[UpdateScrollBars]

    R[DECSET 1049] --> S[UseAlternateScreenBuffer]
    S --> T[_CreateAltBuffer]
    T --> U[SetActiveScreenBuffer]
    U --> V[代替バッファ使用中]
    V --> W[DECRST 1049]
    W --> X[UseMainScreenBuffer]
    X --> Y[_handleDeferredResize]
    Y --> Z[メインバッファ復帰]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-100-01 | デフォルト出力モード | ENABLE_PROCESSED_OUTPUT \| ENABLE_WRAP_AT_EOL_OUTPUT | SCREEN_INFORMATION作成時 |
| BR-100-02 | VTモード自動有効化 | VirtualTerminalLevel != 0 の場合、ENABLE_VIRTUAL_TERMINAL_PROCESSINGを自動設定 | コンストラクタ |
| BR-100-03 | PTYモードバッファ制約 | 代替バッファまたはVtIoモード時、バッファサイズをビューポートに固定 | _IsInPtyMode() == true |
| BR-100-04 | 代替バッファStateMachine共有 | 代替バッファはメインバッファのStateMachineを共有 | UseAlternateScreenBuffer時 |
| BR-100-05 | リサイズリフロー | WrapText有効かつメインバッファの場合、リサイズ時にテキストリフローを実行 | ResizeScreenBuffer時 |
| BR-100-06 | VirtualBottom追跡 | API呼び出しによるビューポート移動時のみVirtualBottomを更新（ユーザースクロールでは不変） | SetViewportOrigin(updateBottom=true) |
| BR-100-07 | カーソル位置範囲検証 | カーソル位置はバッファサイズの範囲内でなければならない | SetCursorPosition |
| BR-100-08 | 代替バッファカーソル同期 | 代替バッファ作成時にメインバッファのカーソルスタイル・可視性をコピー、復帰時にコピーバック | UseAlternateScreenBuffer / UseMainScreenBuffer |

### 計算ロジック

| ロジック名 | 内容 |
|-----------|------|
| ビューポート文字数計算 | クライアントピクセル領域 / フォントサイズ（スクロールバー分を除く） |
| スクロールバー可視判定 | バッファピクセルサイズ > クライアントピクセルサイズの場合に表示 |
| VirtualBottom推定 | リサイズ後: max(lastNonSpaceRow, cursorRow + cursorDistanceFromBottom, viewportHeight - 1) |

## データベース操作仕様

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| STATUS_INVALID_PARAMETER | パラメータエラー | バッファサイズがSHORT_MAX以上 | エラーを返却 |
| STATUS_INVALID_PARAMETER | パラメータエラー | カーソル位置がバッファ範囲外 | エラーを返却 |
| STATUS_INVALID_PARAMETER | パラメータエラー | ビューポート原点がバッファ外 | エラーを返却 |
| E_NOT_VALID_STATE | 状態エラー | フォントサイズが0 | エラーを返却 |
| E_FAIL | 初期化エラー | IWindowMetricsの取得失敗 | THROW_HR |

### リトライ仕様

リトライは行わない。初期化失敗時は呼び出し元にエラーを返却する。

## トランザクション仕様

該当なし。

## パフォーマンス要件

- ResizeWithReflow はテキストの再折り返しを行うため、大きなバッファでは負荷が高い。代替バッファではリフローをスキップする
- _AdjustScreenBuffer はサイズ変更がない場合 S_FALSE を返して不要な処理をスキップ
- ConPTY カーソル位置同期は atomic_wait で効率的にブロック（タイムアウト500ms）
- IsMaximizedX/Y でビューポートとバッファの一致を判定し、不要なスクロールバー更新を回避

## セキュリティ考慮事項

- OutputMode フラグによるモード制御（プロセスごとに設定可能）
- コンソールロックの取得が必要な操作（s_InsertScreenBuffer, s_RemoveScreenBuffer）

## 備考

- OutputMode のデフォルト値は ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT（screenInfo.hpp 167行目）
- ConsoleObjectHeader を継承しており、Console API のオブジェクト管理に統合されている
- SCREEN_INFORMATION はリンクリスト（Next ポインタ）で管理される
- 代替バッファ切替時、メインバッファの StateMachine を代替バッファが共有する設計

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | screenInfo.hpp | `src/host/screenInfo.hpp` | SCREEN_INFORMATION クラス定義全体 |

**読解のコツ**: SCREEN_INFORMATION は ConsoleObjectHeader と IIoProvider を多重継承している。パブリックメンバは機能別リージョン（Creation, Buffer, Cursor, I/O, Rendering/Viewport, Windowing, General Information, Helpers）に分かれている。プライベートメンバを把握すると内部状態が理解しやすい。

**主要処理フロー**:
1. **31行目**: ConsoleObjectHeader と IIoProvider の多重継承
2. **36-51行目**: SnapOnScopeExit 内部構造体 - scope_exit パターンでカーソル可視化を保証
3. **53-58行目**: ScrollBarState 構造体 - maxSize, viewport, isAltBuffer
4. **74行目**: CreateInstance() 静的ファクトリメソッド
5. **79-80行目**: GetTextBuffer() - TextBuffer への参照取得
6. **82-84行目**: ResizeScreenBuffer / ResizeWithReflow / ResizeTraditional - 3種のリサイズ方式
7. **85-86行目**: UseAlternateScreenBuffer / UseMainScreenBuffer - 代替バッファ切替
8. **100-107行目**: カーソル操作メソッド群
9. **110-111行目**: GetStateMachine() - VTパーサーへのアクセス
10. **132-138行目**: Viewport 管理メソッド群
11. **167行目**: OutputMode デフォルト値（ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT）
12. **203行目**: _textBuffer (std::unique_ptr\<TextBuffer\>) - テキストバッファ本体
13. **205行目**: _stateMachine (std::shared_ptr\<StateMachine\>) - VTパーサー（代替バッファと共有）
14. **208行目**: _viewport (Viewport) - 表示領域
15. **209-210行目**: _psiAlternateBuffer / _psiMainBuffer - 代替バッファポインタ
16. **220行目**: _virtualBottom - ターミナルスクロールモード用の仮想下端

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | screenInfo.cpp | `src/host/screenInfo.cpp` | CreateInstance 実装 |
| 2-2 | output.cpp | `src/host/output.cpp` | DoCreateScreenBuffer - 起動時のバッファ作成 |

**主要処理フロー**:
- **screenInfo.cpp 21-39行目**: コンストラクタ - IWindowMetrics、PopupAttributes、Font の初期化。VirtualTerminalLevel != 0 の場合に ENABLE_VIRTUAL_TERMINAL_PROCESSING を自動設定
- **screenInfo.cpp 61-110行目**: CreateInstance() - ファクトリメソッド。Viewport、TextBuffer、StateMachine を順に初期化
- **screenInfo.cpp 82-83行目**: PTYモード時はビューポートをバッファサイズに設定（通常はウィンドウサイズ）
- **output.cpp 20-56行目**: DoCreateScreenBuffer() - グローバル設定からパラメータを取得し CreateInstance を呼び出す

#### Step 3: ビューポートとリサイズ処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | screenInfo.cpp | `src/host/screenInfo.cpp` | ProcessResizeWindow、SetViewportOrigin、ResizeWithReflow |

**主要処理フロー**:
- **756-786行目**: ProcessResizeWindow() - ウィンドウリサイズの4段階処理（バッファ調整→ビューポート計算→ビューポート適用→スクロールバー更新）
- **642-721行目**: SetViewportOrigin() - 絶対/相対指定、ターミナルスクロールモード対応、VirtualBottom 更新
- **1276-1327行目**: ResizeWithReflow() - テキストリフロー付きリサイズ。カーソルの相対位置と VirtualBottom を保持
- **1352-1410行目**: ResizeScreenBuffer() - リフロー/従来型の判定。WrapText有効かつメインバッファならリフロー

#### Step 4: 代替バッファ管理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | screenInfo.cpp | `src/host/screenInfo.cpp` | UseAlternateScreenBuffer、UseMainScreenBuffer、_CreateAltBuffer |

**主要処理フロー**:
- **1771-1811行目**: _CreateAltBuffer() - カーソルスタイルコピー、StateMachine共有、OutputModeコピー
- **1877-1912行目**: UseAlternateScreenBuffer() - 遅延リサイズ処理後に代替バッファを作成・切替
- **1920-1953行目**: UseMainScreenBuffer() - カーソルスタイルのコピーバック、代替バッファ削除

### プログラム呼び出し階層図

```
DoCreateScreenBuffer() [output.cpp:20]
    │
    └─ SCREEN_INFORMATION::CreateInstance() [screenInfo.cpp:61]
           ├─ new SCREEN_INFORMATION() [screenInfo.cpp:21]
           │      └─ OutputMode にVT処理フラグ設定（VirtualTerminalLevel != 0時）
           ├─ Viewport::FromDimensions() [screenInfo.cpp:82]
           ├─ std::make_unique<TextBuffer>() [screenInfo.cpp:87]
           ├─ Cursor::SetType() [screenInfo.cpp:94]
           └─ _InitializeOutputStateMachine() [screenInfo.cpp:224]
                  ├─ AdaptDispatch 作成
                  ├─ OutputStateMachineEngine 作成
                  └─ StateMachine 作成

ProcessResizeWindow() [screenInfo.cpp:756]
    │
    ├─ _AdjustScreenBuffer() [screenInfo.cpp:848]
    │      ├─ _AdjustScreenBufferHelper() [screenInfo.cpp:801]
    │      │      └─ s_CalculateScrollbarVisibility() [screenInfo.cpp:1195]
    │      └─ ResizeScreenBuffer() [screenInfo.cpp:1352]
    │             ├─ ResizeWithReflow() [screenInfo.cpp:1276]
    │             │      └─ TextBuffer::Reflow()
    │             └─ ResizeTraditional() [screenInfo.cpp:1336]
    │
    ├─ _CalculateViewportSize() [screenInfo.cpp:914]
    ├─ _AdjustViewportSize() [screenInfo.cpp:1138]
    │      └─ _InternalSetViewportSize() [screenInfo.cpp:954]
    └─ UpdateScrollBars() [screenInfo.cpp:562]

UseAlternateScreenBuffer() [screenInfo.cpp:1877]
    │
    ├─ _handleDeferredResize() [screenInfo.cpp:1822]
    ├─ _CreateAltBuffer() [screenInfo.cpp:1771]
    │      ├─ CreateInstance()
    │      ├─ カーソルスタイル・位置コピー
    │      ├─ s_InsertScreenBuffer() [screenInfo.cpp:159]
    │      └─ StateMachine共有設定
    └─ SetActiveScreenBuffer() [output.cpp:433]

UseMainScreenBuffer() [screenInfo.cpp:1920]
    │
    ├─ _handleDeferredResize()
    ├─ SetActiveScreenBuffer()
    ├─ カーソルスタイルコピーバック
    └─ s_RemoveScreenBuffer() [screenInfo.cpp:175]
```

### データフロー図

```
[入力]                    [処理]                          [出力]

Console API             ───▶ SCREEN_INFORMATION       ───▶ TextBuffer
(CreateScreenBuffer)          ::CreateInstance               (テキストデータ格納)
                              (バッファ作成)                   │
                                                             Viewport
ウィンドウリサイズ      ───▶ ProcessResizeWindow             (表示領域制御)
(WM_SIZE)                     (_AdjustScreenBuffer           │
                               + _AdjustViewportSize)  ───▶ Renderer
                                                             (画面描画)
VTシーケンス           ───▶ StateMachine              ───▶ AdaptDispatch
(WriteConsole)                (VTパース)                      (VTコマンド実行)
                                                             │
                                                        ───▶ TextBuffer書き込み

DECSET 1049            ───▶ UseAlternateScreenBuffer
                              (_CreateAltBuffer         ───▶ 代替バッファ有効
                               + SetActiveScreenBuffer)

DECRST 1049            ───▶ UseMainScreenBuffer        ───▶ メインバッファ復帰
                              (カーソル復元
                               + 代替バッファ削除)

ConPTYリサイズ         ───▶ SetViewportSize            ───▶ バッファリサイズ
                              (ResizeScreenBuffer             + ビューポート更新
                               + _InternalSetViewportSize)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| screenInfo.hpp | `src/host/screenInfo.hpp` | ソース | SCREEN_INFORMATION クラス定義 |
| screenInfo.cpp | `src/host/screenInfo.cpp` | ソース | SCREEN_INFORMATION 実装（約2050行） |
| output.h | `src/host/output.h` | ソース | 出力関連関数宣言 |
| output.cpp | `src/host/output.cpp` | ソース | DoCreateScreenBuffer、ScrollRegion、ReadOutputString等 |
| outputStream.hpp | `src/host/outputStream.hpp` | ソース | ConhostInternalGetSet（_apiメンバの型） |
| textBuffer.hpp | `src/buffer/out/textBuffer.hpp` | ソース | TextBuffer クラス定義 |
| ObjectHeader.h | `src/server/ObjectHeader.h` | ソース | ConsoleObjectHeader 基底クラス |
| globals.h | `src/host/globals.h` | ソース | グローバル状態（ScreenBuffers リンクリスト） |
| adaptDispatch.hpp | `src/terminal/adapter/adaptDispatch.hpp` | ソース | VTアダプター（StateMachine が使用） |
| stateMachine.hpp | `src/terminal/parser/stateMachine.hpp` | ソース | VTパーサー |
| OutputStateMachineEngine.hpp | `src/terminal/parser/OutputStateMachineEngine.hpp` | ソース | 出力用VTエンジン |
| FontInfo.hpp | `src/renderer/inc/FontInfo.hpp` | ソース | FontInfo クラス |
| FontInfoDesired.hpp | `src/renderer/inc/FontInfoDesired.hpp` | ソース | FontInfoDesired クラス |
| Viewport.hpp | `src/types/inc/Viewport.hpp` | ソース | Viewport クラス |
| selection.hpp | `src/host/selection.hpp` | ソース | 選択機能（リサイズ時にクリア） |
