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

## 概要

本ドキュメントは、K-Shoot Editor(譜面エディタ)におけるCut/Copy/Paste/Deleteの各クリップボード操作機能の設計を記述する。

### 本機能の処理概要

本機能は、譜面上の選択されたオブジェクト(ノート、アナログ、スピン、STOP、Tilt、Zoom等)に対する切り取り(Cut)、コピー(Copy)、貼り付け(Paste)、削除(Delete)の操作を提供する。内部クリップボード配列(clipnote, clipanalog, clipspin, clipstp, cliptilt, clipztop, clipzbot, clipzside)にデータを保持する。

**業務上の目的・背景**: 譜面編集において、ノートパターンの複製・移動は頻繁に行われる操作であり、効率的な編集作業のために不可欠である。

**機能の利用シーン**: 編集メニューの切り取り(Ctrl+X)、コピー(Ctrl+C)、貼り付け(Ctrl+V)、削除(Delete)、またはツールバーボタンから実行する。

**主要な処理内容**:
1. CMD_EDIT_CUT: CMD_EDIT_COPYとCMD_EDIT_DELETEを順次実行する
2. CMD_EDIT_COPY: 選択中オブジェクトの全データをclipxxx配列にコピー
3. CMD_EDIT_PASTE: clipxxx配列のデータをカーソル位置(cnowf)に相対配置。位置オフセットは選択データの最小位置(minpos)からの差分で計算
4. CMD_EDIT_DELETE: 選択中オブジェクトを各配列から削除し、インデックスを再構築

**関連システム・外部連携**: なし(内部クリップボードのみ使用、OS クリップボードは使用しない)。

**権限による制御**: なし。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | 譜面エディタ | 主画面 | 編集メニュー > 切り取り/コピー/貼り付け/削除 |

## 機能種別

CRUD操作(内部クリップボード)

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| cmd | 整数 | Yes | CMD_EDIT_CUT/COPY/PASTE/DELETE | 有効なコマンド値 |
| selnote/selanalog/selspin/selstp | 整数配列 | Yes | 選択中オブジェクトのインデックス | 選択数>0(Copy/Cut/Delete時) |
| cnowf | 整数 | Yes | 現在のカーソル位置(Paste時の貼り付け先) | - |

### 入力データソース

メモリ上の選択状態配列(selnote, selanalog, selspin, selstp)

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| clipnote | 整数配列[131072][6] | コピーされたノートデータ |
| clipanalog | 整数配列[131072][7] | コピーされたアナログデータ(+analogparentran) |
| clipspin | 整数配列[131072][6] | コピーされたスピンデータ |
| clipstp | 整数配列[131072][2] | コピーされたSTOPデータ |

### 出力先

内部クリップボード配列(メモリ上)

## 処理フロー

### 処理シーケンス

```
1. CMD_EDIT_CUT (切り取り)
   ├─ acmd=CMD_EDIT_COPY → gosub *OnCommand (コピー実行)
   └─ acmd=CMD_EDIT_DELETE → gosub *OnCommand (削除実行)

2. CMD_EDIT_COPY (コピー)
   ├─ selnum>0 の場合のみ実行
   ├─ 選択ノートをclipnote配列にコピー(6プロパティ + notesefname)
   ├─ 選択アナログをclipanalog配列にコピー(6プロパティ + analogparentran)
   ├─ 選択スピンをclipspin配列にコピー(6プロパティ)
   └─ 選択STOPをclipstp配列にコピー(2プロパティ)

3. CMD_EDIT_PASTE (貼り付け)
   ├─ clipnum>0 の場合のみ実行
   ├─ *undokakuho でUndo用スナップショット保存
   ├─ minpos算出(全clipデータの最小位置)
   ├─ 各clipデータをcnowf+(元位置-minpos)に挿入
   │   ├─ noteの挿入(位置順を維持して配列をシフト)
   │   ├─ analogの挿入
   │   ├─ spinの挿入
   │   ├─ stpの挿入
   │   ├─ tiltの挿入(同一位置は上書き)
   │   ├─ ztopの挿入(同一位置は上書き)
   │   ├─ zbotの挿入(同一位置は上書き)
   │   └─ zsideの挿入(同一位置は上書き)
   └─ 貼り付けたオブジェクトを選択状態にする

4. CMD_EDIT_DELETE (削除)
   ├─ selnum>0 の場合のみ *undokakuho 実行
   ├─ 選択ノートを配列から削除(後続要素を前にシフト)
   ├─ 選択アナログを配列から削除(parent参照の再構築含む)
   ├─ 選択スピンを配列から削除
   ├─ 選択STOPを配列から削除
   └─ *selinit で選択状態初期化
```

### フローチャート

```mermaid
flowchart TD
    A[コマンド受信] --> B{コマンド種別?}
    B -->|CUT| C[COPY実行]
    C --> D[DELETE実行]
    B -->|COPY| E{selnum > 0?}
    E -->|Yes| F[選択データをclip配列にコピー]
    E -->|No| Z[処理なし]
    B -->|PASTE| G{clipnum > 0?}
    G -->|Yes| H[Undoスナップショット保存]
    H --> I[minpos算出]
    I --> J[カーソル位置に挿入]
    G -->|No| Z
    B -->|DELETE| K{selnum > 0?}
    K -->|Yes| L[Undoスナップショット保存]
    L --> M[選択データを配列から削除]
    K -->|No| Z
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-106-01 | CutはCopy+Delete | Cut操作はCopyとDeleteを順次実行する複合コマンドである | CMD_EDIT_CUT実行時 |
| BR-106-02 | 相対位置貼り付け | Paste時はデータの最小位置からの相対オフセットでカーソル位置に配置する | CMD_EDIT_PASTE実行時 |
| BR-106-03 | 同一位置上書き | Tilt/Zoom系データは同一位置にPasteした場合、既存データを上書きする | CMD_EDIT_PASTE実行時(tilt/ztop/zbot/zside) |
| BR-106-04 | Undo連携 | Paste/Delete操作前に*undokakuhoでスナップショットを保存する | CMD_EDIT_PASTE/DELETE実行時 |
| BR-106-05 | 選択状態更新 | Paste後は貼り付けたオブジェクトが選択状態になる | CMD_EDIT_PASTE完了後 |

### 計算ロジック

Paste時の位置計算:
- `minpos`: 全clipデータの最小位置値
- 各要素の貼り付け位置: `cnowf + (元の位置 - minpos)`

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

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 無操作 | Copy/Cut/Delete時にselnum=0(選択なし) | 何もせずreturn |
| - | 無操作 | Paste時にclipnum=0(クリップボード空) | 何もせずreturn |

### リトライ仕様

該当なし。

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

該当なし。

## パフォーマンス要件

配列シフト操作(挿入/削除)は要素数に比例した計算コストがかかる。最大131072要素のシフトが発生し得る。

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

特になし。

## 備考

- 内部クリップボードを使用するため、OSのクリップボードとは独立した動作をする
- Copy操作ではTilt/Zoom系のデータ(`cliptiltnum=0`, `clipztopnum=0`等)はリセットされる(Tilt/Zoom系のCopyは別途CMD_EDIT_COPY_TILT/CMD_EDIT_COPY_ZOOMコマンドで行う)
- Delete時のアナログ削除では、parent参照(analogparent)の再構築が行われ、削除されたノードの子ノードにparentranが引き継がれる

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | kshooteditor.hsp | `kshooteditor.hsp` | 456-473行目: clipxxx配列の宣言(clipnote, clipanalog, clipspin, clipstp, cliptilt, clipztop, clipzbot, clipzside) |
| 1-2 | kshooteditor.hsp | `kshooteditor.hsp` | 47-48行目: selnum/clipnumマクロ定義(選択数/クリップ数の計算) |

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | kshooteditor.hsp | `kshooteditor.hsp` | 5191-5196行目: CMD_EDIT_CUT(CopyとDeleteの順次実行) |
| 2-2 | kshooteditor.hsp | `kshooteditor.hsp` | 5197-5234行目: CMD_EDIT_COPY |
| 2-3 | kshooteditor.hsp | `kshooteditor.hsp` | 5235-5510行目: CMD_EDIT_PASTE |
| 2-4 | kshooteditor.hsp | `kshooteditor.hsp` | 5511-5609行目: CMD_EDIT_DELETE |

**主要処理フロー(CMD_EDIT_PASTE)**:
- **5237行目**: `if(clipnum>0)` でクリップボード非空チェック
- **5238行目**: `gosub *undokakuho` でUndo保存
- **5241-5265行目**: minpos(最小位置)算出
- **5266-5296行目**: ノートの挿入(位置ソートを維持して配列シフト)
- **5298-5331行目**: アナログの挿入
- **5332-5363行目**: スピンの挿入
- **5364-5387行目**: STOPの挿入
- **5388-5507行目**: Tilt/Zoom系の挿入(同一位置上書き)

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

```
*OnCommand
    │
    ├─ CMD_EDIT_CUT
    │   ├─ CMD_EDIT_COPY (acmd経由)
    │   └─ CMD_EDIT_DELETE (acmd経由)
    │
    ├─ CMD_EDIT_COPY
    │   └─ selnote/selanalog/selspin/selstp → clipxxx配列コピー
    │
    ├─ CMD_EDIT_PASTE
    │   ├─ *undokakuho (Undo保存)
    │   ├─ minpos算出
    │   ├─ 各clipデータの挿入処理
    │   └─ *refreshtitle / *draw
    │
    └─ CMD_EDIT_DELETE
        ├─ *undokakuho (Undo保存)
        ├─ 選択ノート削除(配列シフト)
        ├─ 選択アナログ削除(parent再構築含む)
        ├─ 選択スピン削除
        ├─ 選択STOP削除
        └─ *selinit / *draw
```

### データフロー図

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

選択オブジェクト      ──────▶  CMD_EDIT_COPY             ───▶  clipxxx配列
(selnote等)                   (データコピー)                    (内部クリップボード)

clipxxx配列          ──────▶  CMD_EDIT_PASTE            ───▶  note/analog等配列
(内部クリップボード)           (カーソル位置に挿入)              (更新された譜面データ)

選択オブジェクト      ──────▶  CMD_EDIT_DELETE           ───▶  note/analog等配列
(selnote等)                   (配列から削除)                    (オブジェクト除去済み)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| kshooteditor.hsp | `kshooteditor.hsp` | ソース | Cut/Copy/Paste/Delete処理(5191-5609行目) |
