# 機能設計書 84-TextUnformatted

## 概要

本ドキュメントは、Dear ImGuiライブラリにおけるTextUnformatted関数の機能設計を定義する。TextUnformattedは、フォーマット処理なしで生のテキストを表示する機能である。

### 本機能の処理概要

TextUnformatted関数は、printf形式のフォーマット処理を行わずに、生のテキストデータを直接画面に描画する機能を提供する。大量のテキストを高速に表示する場合に推奨される。

**業務上の目的・背景**：Text関数はprintf形式のフォーマット処理を行うため、フォーマット文字列のパースとバッファへのコピーが発生する。一方TextUnformattedは、テキストをそのまま描画するため、メモリコピーが発生せず、バッファサイズの制限もない。ログビューア、コンソール出力、大量のテキストドキュメントなど、パフォーマンスが重要な場面で使用される。

**機能の利用シーン**：
- ログビューアやコンソールで大量のテキストを表示する場合
- 外部ファイルから読み込んだテキストを表示する場合
- ユーザー入力テキストをそのまま表示する場合（セキュリティ上、フォーマット文字列として解釈させたくない場合）
- 長いテキストドキュメントを効率的に表示する場合

**主要な処理内容**：
1. ウィンドウのSkipItems確認（スキップ対象の場合は早期リターン）
2. テキスト長の計算（text_endが指定されていない場合）
3. 短いテキスト（2000文字以下）または折り返し有効時：通常描画
4. 長いテキスト：クリッピング最適化を適用した描画

**関連システム・外部連携**：ImGuiContext、ImGuiWindow、ImDrawList（描画コマンド生成）

**権限による制御**：なし。すべてのImGuiユーザーが利用可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 3 | Debug Log Window | 補助機能 | ログテキストの表示 |
| 11 | Log | 主機能 | ログテキストの表示 |
| 14 | Long Text | 主機能 | 大量テキストの効率的な表示 |

## 機能種別

表示機能 / テキストウィジェット

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| text | const char* | Yes | 表示するテキストの開始ポインタ | NULL時は空文字列として扱う |
| text_end | const char* | No（デフォルト: NULL） | テキストの終了ポインタ | NULL時は'\0'まで |

### 入力データソース

呼び出し元コードからの直接入力

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| (なし) | void | 戻り値なし。描画コマンドが生成される |

### 出力先

ImDrawList（ウィンドウの描画リスト）

## 処理フロー

### 処理シーケンス

```
1. ウィンドウのSkipItems確認
   └─ SkipItemsがtrueの場合は早期リターン
2. テキスト範囲の正規化
   └─ text == text_endの場合は空文字列として扱う
3. テキスト長の計算
   └─ text_endがNULLの場合はstrlenで計算
4. 描画モードの判定
   └─ 2000文字以下または折り返し有効：通常モード
   └─ それ以外：長テキストモード（クリッピング最適化）
5. 描画実行
   └─ RenderTextWrapped/RenderTextで実際の描画を実行
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[GetCurrentWindow]
    B --> C{SkipItems?}
    C -->|Yes| D[リターン]
    C -->|No| E[テキスト範囲正規化]
    E --> F[テキスト長計算]
    F --> G{長さ <= 2000 または 折り返し有効?}
    G -->|Yes| H[通常描画モード]
    G -->|No| I[長テキスト描画モード]
    H --> J[CalcTextSize]
    J --> K[ItemSize/ItemAdd]
    K --> L[RenderTextWrapped]
    I --> M[行単位クリッピング処理]
    M --> N[可視行のみRenderText]
    L --> O[終了]
    N --> O
    D --> O
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | NULLテキスト | textがNULLの場合、空文字列として扱う | 常時 |
| BR-02 | 長テキスト最適化 | 2000文字を超えるテキストではクリッピング最適化を適用 | 折り返し無効時 |
| BR-03 | フォーマット無効 | printf形式のフォーマット文字列（%s等）はそのまま表示 | 常時 |

### 計算ロジック

- **テキストサイズ計算**: CalcTextSize関数でテキストの幅と高さを計算
- **長テキストクリッピング**: 可視領域外の行はスキップし、描画コストを削減

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

該当なし（メモリ内操作のみ）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | - | 通常エラーは発生しない | - |

### リトライ仕様

該当なし

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

該当なし

## パフォーマンス要件

- 2000文字以下：O(n)で描画（nはテキスト長）
- 2000文字超：可視行のみ描画することでO(可視行数)に最適化
- メモリコピーなし：入力バッファを直接参照
- バッファサイズ制限なし：任意長のテキストを処理可能

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

- TextUnformattedはフォーマット文字列として解釈しないため、フォーマット文字列攻撃のリスクがない
- ユーザー入力テキストを表示する場合に推奨

## 備考

- Text関数の代わりに使用することで、フォーマット処理のオーバーヘッドを回避可能
- text_endを指定することで、NULL終端でないバッファも扱える
- ImGuiTextFlags_NoWidthForLargeClippedTextフラグを内部で使用

---

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

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

### 推奨読解順序

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

テキスト描画に関連する構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | imgui_internal.h | `imgui_internal.h` | ImGuiWindowTempData構造体のCursorPos、TextWrapPos |
| 1-2 | imgui.h | `imgui.h` | ImDrawList関連の描画コマンド構造 |

**読解のコツ**: テキスト描画はCursorPosの位置から開始され、描画後にカーソル位置が更新される。

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

TextUnformatted関数の実装を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | imgui.h | `imgui.h` | TextUnformatted関数宣言（614行目） |
| 2-2 | imgui_widgets.cpp | `imgui_widgets.cpp` | TextUnformatted関数実装（268-271行目） |

**主要処理フロー**:
1. **268-271行目**: TextUnformattedはTextExへのラッパー
2. **ImGuiTextFlags_NoWidthForLargeClippedText**フラグを渡してTextExを呼び出す

#### Step 3: 内部実装TextExを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | imgui_widgets.cpp | `imgui_widgets.cpp` | TextEx関数実装（160-266行目） |

**主要処理フロー**:
- **162-164行目**: ウィンドウ取得とSkipItems確認
- **167-174行目**: テキスト範囲の正規化と長さ計算
- **176-192行目**: 短いテキスト/折り返し時の通常描画パス
- **193-265行目**: 長いテキストのクリッピング最適化パス
  - **206-224行目**: 可視領域外の行をスキップ
  - **226-244行目**: 可視行の描画
  - **246-258行目**: 残りの行をカウント（幅計算のみ）

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

```
ImGui::TextUnformatted(text, text_end)
    │
    └─ ImGui::TextEx(text, text_end, ImGuiTextFlags_NoWidthForLargeClippedText)
           │
           ├─ GetCurrentWindow()
           │
           ├─ CalcTextSize() / CalcWrapWidthForPos()
           │
           ├─ ItemSize() / ItemAdd()
           │
           └─ RenderTextWrapped() / RenderText()
                  │
                  └─ ImDrawList::AddText()
```

### データフロー図

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

text/text_end ───▶ TextEx() ───▶ ImDrawList描画コマンド
                       │
                       ├── CursorPos（描画開始位置）
                       │
                       ├── CalcTextSize（サイズ計算）
                       │
                       └── RenderTextWrapped/RenderText（描画）
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| imgui.h | `imgui.h` | ヘッダー | TextUnformatted関数の宣言（614行目） |
| imgui_widgets.cpp | `imgui_widgets.cpp` | ソース | TextUnformatted/TextEx関数の実装（160-271行目） |
| imgui_internal.h | `imgui_internal.h` | 内部ヘッダー | ImGuiTextFlags定義、内部構造体 |
| imgui_draw.cpp | `imgui_draw.cpp` | ソース | RenderText系関数の実装 |
