# 機能設計書 103-選択機能

## 概要

本ドキュメントは、Windows Console Host (conhost.exe) におけるテキスト選択・コピー機能について記述する。Selectionクラスを中心に、マークモード選択、マウス選択、行選択、ブロック選択、色選択などの多様な選択モードと、キーボード・マウスによる選択操作の処理を設計レベルで詳述する。

### 本機能の処理概要

**業務上の目的・背景**：コンソール上のテキストを選択してクリップボードにコピーする機能は、CUIアプリケーションの出力を活用するために不可欠である。Windows Console Hostでは、Quick Editモード（マウスドラッグ選択）とMark Mode（キーボード選択）の2つの主要な選択方式を提供し、さらに行選択とブロック（矩形）選択を切り替えることができる。

**機能の利用シーン**：ユーザーがコンソール出力をコピーしたい場合、マウスドラッグまたはキーボード操作でテキストを選択し、Enter/Ctrl+Cでクリップボードにコピーするシーンで利用される。また、Alt+数字キーでテキストに色を付ける機能（Color Selection）も提供される。

**主要な処理内容**：
1. マウスドラッグによるテキスト選択の開始・拡張・終了を管理する
2. Mark Modeでのキーボードナビゲーションによるテキスト選択を管理する
3. 行選択モードとブロック（矩形）選択モードを切り替える
4. Shift+矢印キーによる選択範囲の拡張（ワード単位の移動含む）を処理する
5. 選択領域の色付け（Color Selection）を行う
6. 全選択（SelectAll）で入力行またはバッファ全体を選択する
7. 選択状態の可視化（反転表示）をレンダラーに通知する

**関連システム・外部連携**：レンダラー(TriggerSelection)、アクセシビリティ通知(SelectionChanged/CursorChanged)と連携する。

**権限による制御**：特段の権限制御はない。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | コンソールウィンドウ | 主画面 | マウスドラッグ/キーボード操作によるテキスト選択 |

## 機能種別

UI操作処理 / テキスト選択管理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| coordBufferPos | til::point | Yes | バッファ内の座標位置 | バッファ範囲内 |
| pInputKeyInfo | INPUT_KEY_INFO* | Yes | キー入力情報 | NULLでないこと |
| fMakeVisible | bool | No | 選択表示のON/OFF | - |

### 入力データソース

- マウスイベント（WM_LBUTTONDOWN, WM_MOUSEMOVE, WM_LBUTTONUP）
- キーボードイベント（矢印キー、Shift、Ctrl、Home/End、Enter、Escape）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| selectionSpans | vector<til::point_span> | 選択範囲のスパンリスト |
| selectionFlags | DWORD | 選択状態フラグ |
| selectionRect | til::inclusive_rect | 選択矩形領域 |

### 出力先

- レンダラーへの選択領域通知
- クリップボードへのテキストコピー（CopyToClipboard結果として）
- アクセシビリティ通知

## 処理フロー

### 処理シーケンス

```
1. 選択開始
   ├─ マウス選択: InitializeMouseSelection
   │   └─ Quick Editモードでのドラッグ開始
   └─ マーク選択: InitializeMarkSelection
       └─ カーソル位置を保存し選択カーソルに変更

2. 選択拡張
   ├─ マウスドラッグ: ExtendSelection
   └─ キーボード: HandleKeySelectionEvent
       ├─ Shift+矢印: 1文字/1行ずつ拡張
       ├─ Shift+Ctrl+矢印: ワード単位で拡張
       ├─ Shift+Home/End: 行頭/行末まで拡張
       └─ Shift+PgUp/PgDn: 1ページ拡張

3. 選択終了
   ├─ Enter/Ctrl+C: CopyToClipboard結果を返却
   ├─ Escape: ClearSelection
   └─ 数字キー(色選択): _HandleColorSelection
```

### フローチャート

```mermaid
flowchart TD
    A[入力イベント] --> B{選択中?}
    B -->|No| C{マウスドラッグ?}
    C -->|Yes| D[InitializeMouseSelection]
    C -->|No| E{Markモード?}
    E -->|Yes| F[InitializeMarkSelection]
    B -->|Yes| G{キーイベント?}
    G -->|Escape| H[ClearSelection]
    G -->|Enter/Ctrl+C| I[CopyToClipboard]
    G -->|Shift+矢印| J[ExtendSelection]
    G -->|数字キー| K[_HandleColorSelection]
    D --> L[ShowSelection]
    J --> L
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-103-1 | ALT切替 | ALTキー押下時に行選択/ブロック選択が切り替わる | 選択開始時 |
| BR-103-2 | DBCS考慮 | ダブルバイト文字の途中に選択端点が来ないよう調整 | 選択操作時 |
| BR-103-3 | 入力行境界 | 入力行が存在する場合、Home/Endは入力行境界で一旦停止 | Shift+Home/End |
| BR-103-4 | ワード選択 | Shift+Ctrl+矢印で単語区切り文字を境界として移動 | WordByWordSelection |

### 計算ロジック

行選択は `fLineSelection != fUseAlternateSelection` で判定される。ALTキーでfUseAlternateSelectionが切り替わるため、デフォルト行選択時はALTでブロック選択に、デフォルトブロック選択時はALTで行選択に切り替わる。

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

本機能はデータベースを使用しない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| FAIL_FAST | 致命的エラー | 選択状態でない時にHandleKeySelectionEvent呼び出し | プロセスクラッシュ |

### リトライ仕様

リトライは不要。

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

該当なし。

## パフォーマンス要件

- 選択領域の再描画はWM_MOUSEMOVEの頻度で発生するため、同一セル内での移動時は再描画をスキップする最適化あり(_ExtendSelectionの288-291行目)

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

- クリップボードへのコピーはユーザー操作に限定される

## 備考

- Selectionクラスはシングルトンパターン(Selection::Instance())で実装されている
- SelectionDataはtil::generationalでラップされ、世代管理による効率的な変更検出を実現

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | selection.hpp | `src/host/selection.hpp` | Selectionクラスの宣言、SelectionData内部構造体(156-181行目) |

**読解のコツ**: SelectionDataにはフラグ(fSelectionVisible, fLineSelection, fUseAlternateSelection等)と選択範囲(coordSelectionAnchor, srSelectionRect)、保存カーソル情報が含まれる。

#### Step 2: 選択状態管理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | selectionState.cpp | `src/host/selectionState.cpp` | 各種状態判定メソッド |

**主要処理フロー**:
- **18-22行目**: IsInSelectingState - CONSOLE_SELECTINGフラグで判定
- **55-61行目**: IsLineSelection - fLineSelection XOR fUseAlternateSelection
- **279-288行目**: SetLineSelection - 既存選択クリア後にフラグ変更

#### Step 3: 選択操作を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | selection.cpp | `src/host/selection.cpp` | 選択の初期化、拡張、クリア、色付け |
| 3-2 | selectionInput.cpp | `src/host/selectionInput.cpp` | キーボード入力による選択操作 |

**主要処理フロー**:
- selection.cpp **150-185行目**: InitializeMouseSelection - マウス選択開始
- selection.cpp **206-209行目**: ExtendSelection - 選択拡張のラッパー
- selection.cpp **218-302行目**: _ExtendSelection - 実際の拡張ロジック
- selectionInput.cpp **18-79行目**: HandleKeySelectionEvent - キーイベント振り分け
- selectionInput.cpp **279-595行目**: HandleKeyboardLineSelectionEvent - Shift+矢印処理

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

```
Selection::Instance() (シングルトン)
    |
    +-- InitializeMouseSelection / InitializeMarkSelection
    |       +-- ClearSelection(true)
    |       +-- _SetSelectingState(true)
    |       +-- _SaveCursorData
    |
    +-- HandleKeySelectionEvent
    |       +-- _HandleColorSelection
    |       +-- _HandleMarkModeSelectionNav
    |       +-- HandleKeyboardLineSelectionEvent
    |           +-- WordByWordSelection
    |
    +-- ExtendSelection / _ExtendSelection
    |       +-- _PaintSelection -> Renderer::TriggerSelection
    |
    +-- ClearSelection
    |       +-- _CancelMouseSelection / _CancelMarkSelection
    |       +-- _RestoreDataToCursor
    |
    +-- SelectAll
            +-- SelectNewRegion -> InitializeMouseSelection + ExtendSelection
```

### データフロー図

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

マウスドラッグ -----------> InitializeMouseSelection ----> SelectionData更新
                           ExtendSelection                 +-> _PaintSelection
                                                              +-> Renderer

キーボード操作 -----------> HandleKeySelectionEvent -----> 選択範囲変更
                           HandleKeyboardLineSelectionEvent +-> Accessibility通知

Enter/Ctrl+C ------------> KeySelectionEventResult ------> CopyToClipboard指示
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| selection.hpp | `src/host/selection.hpp` | ソース(ヘッダ) | Selectionクラスの宣言 |
| selection.cpp | `src/host/selection.cpp` | ソース(実装) | 選択の初期化・拡張・クリア・色付け |
| selectionInput.cpp | `src/host/selectionInput.cpp` | ソース(実装) | キーボード入力による選択操作 |
| selectionState.cpp | `src/host/selectionState.cpp` | ソース(実装) | 選択状態の判定・管理 |
