# 機能設計書 35-マークモード切替

## 概要

本ドキュメントは、Windows Terminal における「マークモード切替」機能（MarkMode アクション）の設計を記述する。キーボードのみでテキスト選択を行う「マークモード」のオン/オフを切り替える機能である。

### 本機能の処理概要

**業務上の目的・背景**：マウスを使用せずにキーボードのみでターミナル上のテキストを選択できるモードを提供する。アクセシビリティの向上、キーボード中心のワークフロー、SSH接続など遠隔操作時のテキスト選択を可能にする。従来の Windows コンソールの「マーク」モードに相当する機能である。

**機能の利用シーン**：ユーザーがキーバインド（例: Ctrl+Shift+M）を押下してマークモードに入り、矢印キーでカーソルを移動してテキストを選択する。再度同じキーバインドを押下するか Esc キーを押すとマークモードを終了する。

**主要な処理内容**：
1. _HandleMarkMode でアクションを受信
2. TermControl.ToggleMarkMode を呼び出し
3. ControlCore 経由で Terminal::ToggleMarkMode を実行
4. マークモードの状態に応じて選択を開始または選択をクリアして終了
5. 選択UIを更新

**関連システム・外部連携**：なし

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 6 | TermControl（ターミナル表示） | 主画面 | ToggleMarkMode によりマークモードを切替 |
| 1 | TerminalPage（メイン画面） | 主画面 | _HandleMarkMode でアクションを処理 |

## 機能種別

テキスト操作 / 選択モード制御

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| (なし) | - | - | MarkMode アクションはパラメータを持たない | - |

### 入力データソース

- 現在のマークモード状態（_selectionMode）
- 現在の選択状態（IsSelectionActive）
- 検索ハイライトフォーカス状態（GetSearchHighlightFocused）
- カーソル位置
- スクロールオフセット

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| (なし) | - | マークモードの状態が切り替わり、選択UIが更新される |

### 出力先

- Terminal の _selectionMode 状態
- TermControl の選択ハイライト表示

## 処理フロー

### 処理シーケンス

```
1. _HandleMarkMode が sender と ActionEventArgs を受信
   └─ _senderOrActiveControl で TermControl を取得
2. TermControl.ToggleMarkMode → ControlCore.ToggleMarkMode
   └─ LockForWriting でロック取得
   └─ Terminal::ToggleMarkMode を呼び出し
3. Terminal::ToggleMarkMode の分岐処理
   ├─ [現在 Mark モード] → ClearSelection で選択解除してモード終了
   └─ [それ以外] → マークモードに入る
       ├─ [既に選択中] → 既存選択を維持し、end 端点を移動対象に設定
       ├─ [検索ハイライトフォーカスあり] → フォーカスされた検索結果を選択範囲として使用
       └─ [選択なし] → カーソル位置（スクロール中はビューポート原点）を開始・終了点に設定
4. _selectionMode を Mark に設定
5. _updateSelectionUI で選択UIを更新
```

### フローチャート

```mermaid
flowchart TD
    A[MarkMode アクション受信] --> B[TermControl.ToggleMarkMode]
    B --> C[ControlCore.ToggleMarkMode]
    C --> D{現在マークモード?}
    D -->|Yes| E[ClearSelection で選択解除]
    D -->|No| F{既に選択中?}
    F -->|Yes| G[End 端点を移動対象に設定]
    F -->|No| H{検索ハイライトフォーカスあり?}
    H -->|Yes| I[検索結果を選択範囲として使用]
    H -->|No| J{スクロールオフセット > 0?}
    J -->|Yes| K[ビューポート原点をカーソル位置とする]
    J -->|No| L[実際のカーソル位置を使用]
    G --> M[_selectionMode = Mark]
    I --> M
    K --> M
    L --> M
    M --> N[_updateSelectionUI]
    E --> O[完了]
    N --> O
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-35-01 | トグル動作 | 既にマークモードの場合は選択をクリアして終了、それ以外の場合はマークモードに入る | 常に適用 |
| BR-35-02 | 既存選択の維持 | マウスやその他の方法で既に選択がある場合、その選択を維持してマークモードに入る | 選択が既にアクティブ |
| BR-35-03 | 検索ハイライト連携 | 検索でフォーカスされた結果がある場合、その範囲を初期選択として使用する | GetSearchHighlightFocused が有効 |
| BR-35-04 | スクロール位置考慮 | スクロールしている場合はビューポートの先頭を開始位置とし、そうでなければカーソル位置を使用する | _scrollOffset != 0 |
| BR-35-05 | URL選択無効化 | マークモードに入ると _selectionIsTargetingUrl が false に設定される | マークモード開始時 |

### 計算ロジック

なし

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

### 操作別データベース影響一覧

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | コントロール未取得 | アクティブな TermControl がない場合 | 何もしない |

### リトライ仕様

リトライは行わない。

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

Terminal::ToggleMarkMode の実行中は LockForWriting でロックを保持する。

## パフォーマンス要件

即座にモード切替が完了すること。

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

特になし。

## 備考

- マークモード中の矢印キー操作は、TerminalInput で処理され、選択範囲の拡縮に使用される
- マークモードは SelectionInteractionMode::Mark として定義される
- SelectionEndpoint フラグにより、Start/End のどちらの端点を動かすかが制御される

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | AppActionHandlers.cpp | `src/cascadia/TerminalApp/AppActionHandlers.cpp` | _HandleMarkMode がエントリーポイント |

**主要処理フロー**:
1. **1417-1425行目**: _senderOrActiveControl で TermControl を取得し、control.ToggleMarkMode() を呼び出す

#### Step 2: TermControl / ControlCore 層

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | TermControl.cpp | `src/cascadia/TerminalControl/TermControl.cpp` | ToggleMarkMode で ControlCore に委譲 |
| 2-2 | ControlCore.cpp | `src/cascadia/TerminalControl/ControlCore.cpp` | ToggleMarkMode でロック取得と Terminal 呼び出し |

**主要処理フロー**:
- **2578-2581行目**（TermControl.cpp）: _core.ToggleMarkMode() を呼び出す
- **1403-1408行目**（ControlCore.cpp）: LockForWriting 後に _terminal->ToggleMarkMode() を呼び、_updateSelectionUI() で UI 更新

#### Step 3: Terminal コア層

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | TerminalSelection.cpp | `src/cascadia/TerminalCore/TerminalSelection.cpp` | Terminal::ToggleMarkMode の詳細な分岐処理 |

**主要処理フロー**:
- **354-404行目**: マークモードのトグルロジック。現在 Mark モードなら ClearSelection、そうでなければ3つのケース（既存選択あり/検索ハイライトあり/選択なし）で分岐

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

```
TerminalPage::_HandleMarkMode (AppActionHandlers.cpp:1417)
    |
    +-- TermControl::ToggleMarkMode (TermControl.cpp:2578)
           |
           +-- ControlCore::ToggleMarkMode (ControlCore.cpp:1403)
                  |
                  +-- Terminal::ToggleMarkMode (TerminalSelection.cpp:354)
                  |      |
                  |      +-- [Mark → 非Mark] ClearSelection
                  |      +-- [非Mark → Mark] SelectionInfo 設定
                  |
                  +-- _updateSelectionUI
```

### データフロー図

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

現在の _selectionMode --> ToggleMarkMode                --> 新しい _selectionMode
カーソル位置                |                                  SelectionInfo 更新
スクロールオフセット        v                                  |
検索ハイライト状態      分岐処理                           --> 選択UIの更新
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| AppActionHandlers.cpp | `src/cascadia/TerminalApp/AppActionHandlers.cpp` | ソース | _HandleMarkMode アクションハンドラ |
| TermControl.cpp | `src/cascadia/TerminalControl/TermControl.cpp` | ソース | ToggleMarkMode の委譲 |
| TermControl.h | `src/cascadia/TerminalControl/TermControl.h` | ヘッダ | ToggleMarkMode 宣言 |
| ControlCore.cpp | `src/cascadia/TerminalControl/ControlCore.cpp` | ソース | ToggleMarkMode のロックと Terminal 呼び出し |
| TerminalSelection.cpp | `src/cascadia/TerminalCore/TerminalSelection.cpp` | ソース | Terminal::ToggleMarkMode の実装 |
| Terminal.hpp | `src/cascadia/TerminalCore/Terminal.hpp` | ヘッダ | ToggleMarkMode メソッド宣言 |
