# 機能設計書 97-テキスト選択

## 概要

本ドキュメントは、Windows Terminal におけるテキスト選択機能（TerminalSelection）の機能設計を記述する。マウスやキーボードによるテキスト選択の管理（ワード選択・ブロック選択含む）の構造と動作を解説する。

### 本機能の処理概要

テキスト選択機能は、Terminal クラスの一部として実装され、ユーザーがマウスのドラッグ操作やキーボードのShift+矢印キー操作で行うテキスト選択を管理する。選択範囲の開始点（anchor/start）、終了点（end）、ピボット（pivot）を追跡し、文字単位・単語単位・行単位・ブロック選択の各モードをサポートする。

**業務上の目的・背景**：ターミナルでのテキスト選択は、コマンド出力のコピー、エラーメッセージの共有、テキストの再利用など、日常的な操作で必須の機能である。Windows Terminalでは従来のConsole Hostの選択機能を大幅に改善し、ワード選択（ダブルクリック）、行選択（トリプルクリック）、マークモード（キーボードのみの選択）をサポートしている。

**機能の利用シーン**：マウスでテキストをドラッグして選択、ダブルクリックで単語選択、Shift+矢印キーで選択範囲の拡張、Ctrl+Shift+Aで全選択、マークモードでのキーボードのみの選択操作など。

**主要な処理内容**：
1. マウスによる選択開始・拡張・完了（クリック、ドラッグ、ダブル/トリプルクリック）
2. キーボードによる選択操作（Shift+矢印、Ctrl+Shift+Home/End等）
3. 選択拡張モード管理（文字/単語/行）
4. ブロック選択（矩形選択）対応
5. ピボットメカニズム（選択反転時の基準点管理）
6. 選択端点の切替（SwitchSelectionEndpoint）
7. マークモード（キーボードのみの選択）
8. 選択範囲の描画用スパン生成

**関連システム・外部連携**：TextBuffer から選択範囲のテキストを取得する。Renderer に選択範囲の描画指示を出す。TermControl からのマウス/キーボードイベントを受け取る。

**権限による制御**：特になし。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 6 | TermControl（ターミナル表示） | 主画面 | マウス・キーボードによるテキスト選択 |

## 機能種別

ユーザーインタラクション / 選択管理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| viewportPos | til::point | Yes | ビューポート相対のマウス位置 | ビューポート内 |
| expansionMode | SelectionExpansion | Yes | 選択拡張モード（Char/Word/Line） | 有効な列挙値 |
| direction | SelectionDirection | Yes | 選択方向（Left/Right/Up/Down等） | 有効な列挙値 |
| mode | SelectionExpansion | Yes | 拡張モード（Char/Word/Line） | 有効な列挙値 |
| mods | ControlKeyStates | No | 修飾キー状態 | - |

### 入力データソース

- TermControl からのマウスイベント（クリック、ドラッグ）
- TermControl からのキーボードイベント（Shift+方向キー等）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 選択スパン | vector\<til::point_span\> | 選択範囲のスパンリスト（描画用） |
| 選択テキスト | wstring | 選択範囲のプレーンテキスト |

### 出力先

Renderer（選択範囲の描画）、クリップボード（コピー操作）

## 処理フロー

### 処理シーケンス

```
1. MultiClickSelection() - マウスクリックによる選択開始
   └─ クリック回数に応じた拡張モード設定（Char/Word/Line）
2. SetSelectionAnchor() - 選択開始点設定
   └─ _selection->start = position, _selection->pivot = position
3. SetSelectionEnd() - 選択終了点設定
   └─ 拡張モードに応じて終了点を調整
4. UpdateSelection() - キーボードによる選択拡張
   └─ 方向と拡張モードに応じて選択範囲を更新
5. _GetSelectionSpans() - 描画用スパン生成
   └─ TextBuffer::GetTextSpansでスパン計算
```

### フローチャート

```mermaid
flowchart TD
    A[マウスクリック/キー入力] --> B{操作種別}
    B -->|シングルクリック| C[SetSelectionAnchor - 文字選択開始]
    B -->|ダブルクリック| D[MultiClickSelection - 単語選択]
    B -->|トリプルクリック| E[MultiClickSelection - 行選択]
    B -->|ドラッグ| F[SetSelectionEnd - 選択拡張]
    B -->|Shift+矢印| G[UpdateSelection - キーボード選択]
    C --> H[選択範囲更新]
    D --> H
    E --> H
    F --> H
    G --> H
    H --> I[_GetSelectionSpans]
    I --> J[Renderer に描画通知]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-97-01 | ピボットメカニズム | 選択方向が反転してもピボット位置は常に選択範囲に含まれる | 選択拡張時 |
| BR-97-02 | 単語選択拡張 | ダブルクリックで開始した選択をドラッグで拡張すると、単語境界で拡張される | ドラッグ選択時 |
| BR-97-03 | 端点切替 | SwitchSelectionEndpointで操作対象の端点をstart/end間で切替 | マークモード時 |
| BR-97-04 | DBCS対応 | 選択開始/終了点がDBCS後続バイト上にある場合、先行バイトまで拡張 | CJKテキスト選択時 |

### 計算ロジック

- 選択スパン生成: TextBuffer::GetTextSpans() で start/end/blockSelection からスパンリストを計算
- ピボット適用: start < pivot ならば end = pivot, start = mousePos。start >= pivot ならば start = pivot, end = mousePos

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

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 選択なし | 正常 | IsSelectionActive() == false | 空のスパンリストを返却 |

### リトライ仕様

リトライは行わない。

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

該当なし。

## パフォーマンス要件

- til::generational による選択スパンのキャッシュ（変更がない場合は再計算を回避）

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

特になし。

## 備考

- TerminalSelection.cpp の冒頭コメント（13-43行目）にピボットメカニズムの図解が記述されている
- 選択状態は til::generational\<SelectionInfo\> で管理され、変更検出が最適化されている

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Terminal.hpp | `src/cascadia/TerminalCore/Terminal.hpp` | SelectionInfo構造体、SelectionInteractionMode/Direction/Expansion/Endpoint列挙体 |

**読解のコツ**: Terminal.hpp の #pragma region TextSelection (249行目以降) に選択関連の宣言がまとめられている。SelectionInfo構造体はtil::generationalでラップされ、変更追跡が可能。

**主要処理フロー**:
1. **251-257行目**: SelectionInteractionMode列挙体（None/Mouse/Keyboard/Mark）
2. **259-270行目**: SelectionDirection列挙体（Left/Right/Up/Down/Home/End）
3. **273-279行目**: SelectionExpansion列挙体（Char/Word/Line/Buffer）
4. **282-293行目**: SelectionEndpoint列挙体（Start/End）
5. **388-396行目**: SelectionInfo構造体（start/end/pivot/blockSelection）

#### Step 2: 選択処理の実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | TerminalSelection.cpp | `src/cascadia/TerminalCore/TerminalSelection.cpp` | テキスト選択の全実装 |

**主要処理フロー**:
- **13-43行目**: ピボットメカニズムの設計説明コメント
- **49-64行目**: _GetSelectionSpans() - 選択スパン生成
- **72-76行目**: GetSelectionAnchor() - 選択開始点取得
- **84-88行目**: GetSelectionEnd() - 選択終了点取得
- **93行目以降**: SelectionStartForRendering() - DBCS対応の描画開始点

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

```
TermControl (マウス/キーイベント)
    │
    ├─ Terminal::MultiClickSelection()
    │      └─ SetSelectionAnchor() + SetSelectionEnd()
    │
    ├─ Terminal::SetSelectionEnd()
    │      └─ _selection->end 更新 + ピボット処理
    │
    ├─ Terminal::UpdateSelection()
    │      └─ 方向・モードに応じた選択端点移動
    │
    ├─ Terminal::SwitchSelectionEndpoint()
    │      └─ _selectionEndpoint の Start/End 切替
    │
    └─ Terminal::_GetSelectionSpans()
           └─ TextBuffer::GetTextSpans()
```

### データフロー図

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

マウスイベント       ───▶ Terminal (SelectionInfo)  ───▶ 選択スパン
(クリック/ドラッグ)         (start/end/pivot管理)           (描画用)
                           │
キーボードイベント   ───▶ UpdateSelection           ───▶ TextBuffer::GetTextSpans
(Shift+矢印)              (方向・モード処理)               (スパン計算)
                           │
                         ピボット処理               ───▶ Renderer
                           (選択反転時の基準管理)          (選択範囲描画)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| TerminalSelection.cpp | `src/cascadia/TerminalCore/TerminalSelection.cpp` | ソース | テキスト選択処理の実装 |
| Terminal.hpp | `src/cascadia/TerminalCore/Terminal.hpp` | ソース | Terminal クラス定義（SelectionInfo等の型定義含む） |
| textBuffer.hpp | `src/buffer/out/textBuffer.hpp` | ソース | GetTextSpans/GetTextRects等の選択関連メソッド |
