# 機能設計書 70-クリップボード操作

## 概要

本ドキュメントは、Ghosttyターミナルエミュレータにおける OSC 52 クリップボード操作機能の設計を記述する。

### 本機能の処理概要

OSC 52 クリップボード操作機能は、ターミナルアプリケーションからシステムクリップボードへのアクセスを提供する標準 OSC シーケンスである。リモート SSH セッションからでもローカルのクリップボードを操作でき、テキストのコピー・ペーストをプログラムから行うことが可能。

**業務上の目的・背景**：リモートサーバーで作業する際、テキストをローカルマシンのクリップボードにコピーしたり、ローカルのクリップボード内容をリモートセッションに貼り付けたりする需要がある。OSC 52 は多くのターミナルエミュレータがサポートする標準的なプロトコルで、tmux や vim などのアプリケーションが利用している。

**機能の利用シーン**：
- vim/neovim でのヤンク・ペースト
- tmux でのバッファ操作
- スクリプトからのクリップボード操作
- SSH 経由でのリモートクリップボードアクセス

**主要な処理内容**：
1. OSC 52 シーケンスの解析
2. クリップボード照会（?）リクエスト処理
3. クリップボード設定リクエスト処理
4. クリップボードクリアリクエスト処理
5. セキュリティ確認ダイアログ表示（設定による）

**関連システム・外部連携**：
- システムクリップボード: OS ネイティブ API
- GTK/Cocoa: クリップボード UI
- アプリランタイム: 確認ダイアログ

**権限による制御**：`clipboard-read`, `clipboard-write` 設定で読み書きアクセスを制御

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | メインターミナルウィンドウ | 主機能 | クリップボード操作 |
| 14 | クリップボード確認ダイアログ | 補助機能 | 貼り付け確認 |

## 機能種別

クリップボード / プロトコル処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| kind | u8 | No | クリップボード種別（c=clipboard, s=selection, p=primary） | c, s, p のいずれか |
| data | []const u8 | Yes | Base64 エンコードデータ、または "?" | - |

### クリップボード種別

| 種別 | コード | 説明 |
|------|--------|------|
| standard | c | システムクリップボード |
| selection | s | 選択バッファ（X11） |
| primary | p | プライマリ選択（X11） |

### 入力データソース

- OSC 52 シーケンス: `ESC ] 52 ; <kind> ; <data> ST`
- `<data>` が `?` の場合は照会、それ以外は設定
- `<data>` が空の場合はクリア

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| Response | []const u8 | Base64 エンコードされたクリップボード内容 |

### 出力先

- PTY: 応答シーケンス `ESC ] 52 ; <kind> ; <base64_data> ST`
- システムクリップボード: 設定時

## 処理フロー

### 処理シーケンス

```
1. OSC 52 シーケンス受信
   └─ osc.Parser で解析
   └─ clipboard_operation.parse 呼び出し

2. コマンド解析
   └─ kind 抽出（省略時は c）
   └─ data 抽出
   └─ clipboard_contents 構造体生成

3. StreamHandler 処理
   └─ clipboardContents 関数呼び出し
   └─ clipboard_type 決定

4. 照会リクエスト（data == "?"）
   └─ surface に clipboard_read メッセージ送信
   └─ アプリランタイムがクリップボード読み込み
   └─ Base64 エンコードして応答

5. 設定リクエスト（data != "?"）
   └─ clipboard_write 設定チェック
   └─ surface に clipboard_write メッセージ送信
   └─ 確認ダイアログ表示（設定による）
   └─ システムクリップボードに設定

6. クリアリクエスト（data == ""）
   └─ 空文字列をクリップボードに設定
```

### フローチャート

```mermaid
flowchart TD
    A[OSC 52 受信] --> B[osc.Parser]
    B --> C[clipboard_operation.parse]
    C --> D{kind 解析}
    D -->|c| E[standard]
    D -->|s| F[selection]
    D -->|p| G[primary]
    D -->|省略| E
    E --> H{data?}
    F --> H
    G --> H
    H -->|"?"| I[clipboard_read メッセージ]
    H -->|空| J[clipboard_write クリア]
    H -->|Base64| K[clipboard_write 設定]
    I --> L[Surface に送信]
    J --> L
    K --> L
    L --> M{読み込み?}
    M -->|Yes| N[クリップボード取得]
    M -->|No| O{書き込み許可?}
    N --> P[Base64 エンコード]
    P --> Q[OSC 52 応答送信]
    O -->|Yes| R{確認必要?}
    O -->|No| S[無視]
    R -->|Yes| T[確認ダイアログ]
    R -->|No| U[クリップボード設定]
    T --> V{許可?}
    V -->|Yes| U
    V -->|No| S
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-70-01 | デフォルト kind | kind 省略時は 'c'（standard）を使用 | 常時 |
| BR-70-02 | 読み込み制御 | `clipboard-read` 設定で読み込みアクセスを制御 | 照会時 |
| BR-70-03 | 書き込み制御 | `clipboard-write` 設定で書き込みアクセスを制御 | 設定時 |
| BR-70-04 | 確認ダイアログ | `clipboard-write=ask` の場合は確認ダイアログを表示 | 設定時 |
| BR-70-05 | Base64 エンコード | データは Base64 でエンコード/デコード | 常時 |
| BR-70-06 | iTerm2 互換 | OSC 1337 CopyToClipboard も clipboard 操作として処理 | iTerm2 互換 |

### 計算ロジック

Base64 デコードは標準ライブラリを使用。不正な Base64 データは無視される。

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

該当なし（本機能はデータベースを使用しない）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | InvalidFormat | 不正な OSC 形式 | リクエストを無視 |
| - | AccessDenied | 読み書きが無効化 | リクエストを無視 |
| - | UserRejected | 確認ダイアログで拒否 | リクエストを無視 |

### リトライ仕様

該当なし

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

該当なし

## パフォーマンス要件

- 大きなクリップボードデータ（数MB）でもハングしないこと
- 確認ダイアログはモーダルでメインスレッドをブロックしないこと

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

- クリップボード読み込みはデフォルトで無効
- クリップボード書き込みは確認オプションあり
- 確認ダイアログで内容をプレビュー表示
- 機密情報のブラー表示オプション

## 備考

- X11 では selection と primary の両方をサポート
- macOS/Windows では standard のみ使用（他は同義として扱う）
- iTerm2 の CopyToClipboard (OSC 1337) も同様に処理

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | osc.zig | `src/terminal/osc.zig` | clipboard_contents 構造体（52-55行目） |
| 1-2 | stream.zig | `src/terminal/stream.zig` | ClipboardContents（122行目） |

**読解のコツ**: `clipboard_contents` は `kind`（u8）と `data`（Base64 文字列）を持つシンプルな構造。

#### Step 2: OSC パーサーを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | clipboard_operation.zig | `src/terminal/osc/parsers/clipboard_operation.zig` | parse 関数（9-48行目） |

**主要処理フロー**:
- **9-23行目**: kind がない場合のデフォルト 'c' 設定
- **24-29行目**: kind=; の形式を処理
- **31-46行目**: 通常の kind;data 形式を処理

#### Step 3: StreamHandler 処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | stream_handler.zig | `src/termio/stream_handler.zig` | clipboardContents 関数（1039-1067行目） |

**主要処理フロー**:
- **1044-1049行目**: kind から clipboard_type への変換
- **1052-1055行目**: "?" の場合は clipboard_read メッセージ
- **1058-1066行目**: それ以外は clipboard_write メッセージ

#### Step 4: Surface メッセージを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | surface.zig | `src/apprt/surface.zig` | clipboard_read, clipboard_write メッセージ |
| 4-2 | structs.zig | `src/apprt/structs.zig` | Clipboard enum |

#### Step 5: GTK 実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | clipboard_confirmation_dialog.zig | `src/apprt/gtk/class/clipboard_confirmation_dialog.zig` | 確認ダイアログ |

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

```
OSC 52 シーケンス受信
    │
    └─ osc.Parser.next
           │
           └─ clipboard_operation.parse
                  │
                  └─ Command.clipboard_contents 生成

Stream 処理
    │
    └─ stream.vt(.clipboard_contents)
           │
           └─ StreamHandler.clipboardContents
                  │
                  ├─ clipboard_type 変換
                  │
                  └─ surfaceMessageWriter
                         │
                         ├─ .clipboard_read（照会）
                         │     │
                         │     └─ Surface.clipboardRead
                         │            │
                         │            └─ システムクリップボード取得
                         │            │
                         │            └─ Base64 エンコード
                         │            │
                         │            └─ OSC 52 応答送信
                         │
                         └─ .clipboard_write（設定）
                               │
                               └─ Surface.clipboardWrite
                                      │
                                      ├─ 確認ダイアログ（ask）
                                      │
                                      └─ システムクリップボード設定
```

### データフロー図

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

OSC 52 シーケンス ───────▶ osc.Parser
                               │
                               ▼
                        clipboard_operation.parse
                               │
                               ▼
kind + data ─────────────▶ clipboard_contents
                               │
                               ▼
                        StreamHandler.clipboardContents
                               │
                               ├─ clipboard_read ────▶ システム取得 ────▶ Base64 ────▶ OSC 52 応答
                               │
                               └─ clipboard_write
                                      │
                                      ├─ deny ────▶ 無視
                                      │
                                      ├─ allow ────▶ システム設定
                                      │
                                      └─ ask ────▶ 確認ダイアログ ────▶ システム設定/無視
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| osc.zig | `src/terminal/osc.zig` | ソース | clipboard_contents 定義 |
| clipboard_operation.zig | `src/terminal/osc/parsers/clipboard_operation.zig` | ソース | OSC 52 パーサー |
| stream_handler.zig | `src/termio/stream_handler.zig` | ソース | clipboardContents 処理 |
| stream.zig | `src/terminal/stream.zig` | ソース | ClipboardContents アクション |
| surface.zig | `src/apprt/surface.zig` | ソース | Surface メッセージ定義 |
| structs.zig | `src/apprt/structs.zig` | ソース | Clipboard enum |
| clipboard_confirmation_dialog.zig | `src/apprt/gtk/class/clipboard_confirmation_dialog.zig` | ソース | GTK 確認ダイアログ |
| iterm2.zig | `src/terminal/osc/parsers/iterm2.zig` | ソース | iTerm2 CopyToClipboard 互換 |
| Config.zig | `src/config/Config.zig` | ソース | clipboard-read, clipboard-write 設定 |
