# 機能設計書 105-Undo/Redo

## 概要

本ドキュメントは、K-Shoot Editor(譜面エディタ)における最大7段階のUndo/Redo操作機能の設計を記述する。ノート・アナログ・スピン・Tilt等の配列単位でスナップショットを保持し、編集操作の取り消しと再実行を実現する。

### 本機能の処理概要

本機能は、譜面エディタの編集操作に対するUndo(元に戻す)およびRedo(やり直し)機能を提供する。最大7段階(UNDO_MAX=7)のスナップショットをリングバッファ方式で管理し、すべての譜面データ配列(note, analog, spin, tilt, ztop, zbot, zside, bpml, anagain, anafil, anvol, anse, beatl, stp, analogparent, analogparentran, comment, commentstr)の完全なコピーを保持する。

**業務上の目的・背景**: 譜面編集作業において、誤った操作を取り消せることは作業効率と品質の面で不可欠である。特にノート配置・削除・移動などの破壊的操作に対する安全網として機能する。

**機能の利用シーン**: 編集メニューの「元に戻す」(Ctrl+Z) / 「やり直し」(Ctrl+Y) から実行する。ノート配置・削除・コピー&ペースト・選択操作の反転・ランダム化・小節削除/挿入など、すべての破壊的編集操作の前に自動的にスナップショットが保存される。

**主要な処理内容**:
1. `*undokakuho`(Undo確保): 現在の全配列状態をud_xxx配列にコピーし、リングバッファのカーソルを進める
2. CMD_EDIT_UNDO: リングバッファを1つ戻り、ud_xxx配列から全配列を復元(`*undofukugen`)
3. CMD_EDIT_REDO: リングバッファを1つ進め、ud_xxx配列から全配列を復元(`*undofukugen`)
4. Redo最大数の管理: 新規編集操作が発生するとud_redomax=0にリセット

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

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | 譜面エディタ | 主画面 | 編集メニュー > 元に戻す(Ctrl+Z) / やり直し(Ctrl+Y) |

## 機能種別

状態管理 / メモリ操作

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| cmd | 整数 | Yes | CMD_EDIT_UNDO(60) または CMD_EDIT_REDO(61) | 有効なコマンド値 |
| ud_cnt | 整数 | Yes | 現在のUndo履歴数 | 0以上 |
| ud_redomax | 整数 | Yes | 利用可能なRedo回数 | 0以上 |

### 入力データソース

メモリ上の全譜面データ配列(保存対象)

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ud_note | 整数配列[131072][6][7] | ノートデータのスナップショット(7段階分) |
| ud_analog | 整数配列[131072][7][7] | アナログデータのスナップショット |
| ud_spin | 整数配列[131072][6][7] | スピンデータのスナップショット |
| ud_bpml | 整数配列[131072][2][7] | BPMデータのスナップショット |
| (他多数の配列) | - | tilt, ztop, zbot, zside, anagain, anafil, anvol, anse, beatl, stp等 |

### 出力先

メモリ上のud_xxx配列(リングバッファ)

## 処理フロー

### 処理シーケンス

```
1. *undokakuho (スナップショット保存)
   ├─ ud_cur = (ud_cur+1) \ UNDO_MAX  (リングバッファカーソル進行)
   ├─ ud_cnt = min(ud_cnt+1, UNDO_MAX) (履歴カウント更新)
   ├─ 全配列をud_xxx.(xxx).(ud_cur)にコピー
   └─ ud_redomax = 0 (新規編集でRedo履歴をクリア)

2. CMD_EDIT_UNDO (元に戻す)
   ├─ ud_cnt <= 0 の場合は処理なし
   ├─ ud_redofl=1 の場合、現在状態をスナップショットに保存
   ├─ ud_cur = (UNDO_MAX+ud_cur-1) \ UNDO_MAX (カーソル後退)
   ├─ ud_cnt-- (履歴カウント減少)
   ├─ ud_redomax++ (Redo可能数増加)
   └─ *undofukugen (スナップショットから復元)

3. CMD_EDIT_REDO (やり直し)
   ├─ ud_redomax <= 0 の場合は処理なし
   ├─ ud_cur = (ud_cur+1) \ UNDO_MAX (カーソル前進)
   ├─ ud_cnt++ (履歴カウント増加)
   ├─ ud_redomax-- (Redo可能数減少)
   └─ *undofukugen (スナップショットから復元)
```

### フローチャート

```mermaid
flowchart TD
    A[コマンド受信] --> B{コマンド種別?}
    B -->|CMD_EDIT_UNDO| C{ud_cnt > 0?}
    C -->|No| Z[処理なし]
    C -->|Yes| D{ud_redofl = 1?}
    D -->|Yes| E[現在状態をスナップショット保存]
    D -->|No| F[カーソル後退]
    E --> E2[カーソル後退]
    E2 --> G[*undofukugen で復元]
    F --> G
    B -->|CMD_EDIT_REDO| H{ud_redomax > 0?}
    H -->|No| Z
    H -->|Yes| I[カーソル前進]
    I --> J[*undofukugen で復元]
    G --> K[*refreshtitle, *draw]
    J --> K
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-105-01 | 最大Undo段階数 | UNDO_MAX=7 段階までのUndo/Redo操作を保持する | 常時 |
| BR-105-02 | リングバッファ方式 | スナップショットはリングバッファで管理し、最大数を超えると最古のデータが上書きされる | スナップショット数がUNDO_MAXを超えた場合 |
| BR-105-03 | Redo履歴クリア | 新規の編集操作(*undokakuho呼び出し)時にud_redomax=0に設定し、Redo履歴をクリアする | 新規編集操作時 |
| BR-105-04 | 全配列コピー | スナップショットはnote/analog/spin/tilt/ztop/zbot/zside/bpml/anagain/anafil/anvol/anse/beatl/stp/analogparent/analogparentran/comment/commentstrの全配列を対象とする | 常時 |
| BR-105-05 | ファイル操作時リセット | ファイルを開く(CMD_OPEN)/新規作成(CMD_NEW)時にUndo履歴はリセットされる | CMD_OPEN/CMD_NEW実行時 |

### 計算ロジック

リングバッファのカーソル計算:
- 前進: `ud_cur = (ud_cur + 1) \ UNDO_MAX` (`\` はHSP3のモジュロ演算子)
- 後退: `ud_cur = (UNDO_MAX + ud_cur - 1) \ UNDO_MAX`

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

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 無操作 | Undo実行時にud_cnt<=0 | 何もせずreturn |
| - | 無操作 | Redo実行時にud_redomax<=0 | 何もせずreturn |

### リトライ仕様

該当なし。

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

該当なし。

## パフォーマンス要件

- 各スナップショットは約131072x6要素の整数配列を複数含むため、メモリ消費が大きい
- 7段階分のスナップショットでおよそ数十MBのメモリを使用する見込み

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

特になし。

## 備考

- `ud_redofl` 変数は初回Undo時に現在状態を保存するために使用される。これにより、Undo後にさらにUndoした場合でも正しく復元できる
- `*undokakuho` は「undo確保」(Undo保の確保)の略であり、HSP3のラベル命名規則に従っている
- `*undofukugen` は「undo復元」の略で、スナップショットからの復元処理を行う

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | kshooteditor.hsp | `kshooteditor.hsp` | 208行目: `#define UNDO_MAX 7` で最大Undo段階数を定義 |
| 1-2 | kshooteditor.hsp | `kshooteditor.hsp` | 288-310行目: ud_xxx配列の宣言。各配列の第3次元がUNDO_MAX段階分のスナップショット |

**読解のコツ**: HSP3のdim命令で `dim ud_note,131072,6,UNDO_MAX` は3次元配列を宣言する。第1次元がデータ要素、第2次元がプロパティ、第3次元がスナップショットスロットに対応する。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | kshooteditor.hsp | `kshooteditor.hsp` | 5167-5190行目: CMD_EDIT_UNDO / CMD_EDIT_REDO処理 |

**主要処理フロー**:
1. **5167行目**: `if(cmd=CMD_EDIT_UNDO)` Undo処理開始
2. **5169行目**: `if(ud_cnt<=0):return` Undo不可チェック
3. **5170-5174行目**: `ud_redofl=1` の場合、現在状態をスナップショットに保存
4. **5176行目**: `ud_cur=(UNDO_MAX+ud_cur-1)\UNDO_MAX` カーソル後退(モジュロ演算)
5. **5177行目**: `ud_cnt--` 履歴カウント減少
6. **5178行目**: `ud_redomax++` Redo可能数増加
7. **5179行目**: `gosub *undofukugen` スナップショットから復元
8. **5182行目**: `if(cmd=CMD_EDIT_REDO)` Redo処理開始
9. **5184行目**: `if(ud_redomax<=0):return` Redo不可チェック
10. **5185-5187行目**: カーソル前進、カウント更新
11. **5188行目**: `gosub *undofukugen` スナップショットから復元

#### Step 3: スナップショット保存処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | kshooteditor.hsp | `kshooteditor.hsp` | `*undokakuho` ラベル(grepで5238行目等に呼び出し確認) |

**主要処理フロー**:
- 全配列のコピー処理(note→ud_note, analog→ud_analog等)
- ud_curのインクリメント(リングバッファ方式)
- ud_redomax=0 (Redo履歴クリア)

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

```
*OnCommand
    │
    ├─ CMD_EDIT_UNDO
    │   ├─ *undokakuho (初回Undo時に現在状態保存)
    │   └─ *undofukugen (スナップショットから復元)
    │
    ├─ CMD_EDIT_REDO
    │   └─ *undofukugen (スナップショットから復元)
    │
    └─ (各編集コマンド)
        └─ *undokakuho (編集前にスナップショット保存)
            ※ CMD_EDIT_DELETE, CMD_EDIT_PASTE, CMD_EDIT_SELFLIP,
              CMD_EDIT_SELRANDOMIZE, CMD_EDIT_ADDBLANK,
              CMD_EDIT_REMOVEMEASURE, ノート配置操作等から呼び出し
```

### データフロー図

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

全譜面配列(note等)  ───────▶  *undokakuho               ───▶  ud_xxx配列
(現在の編集状態)               (スナップショット保存)            (リングバッファ)

ud_xxx配列          ───────▶  *undofukugen              ───▶  全譜面配列(note等)
(リングバッファ)               (スナップショット復元)            (復元された状態)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| kshooteditor.hsp | `kshooteditor.hsp` | ソース | Undo/Redo処理(CMD_EDIT_UNDO/REDO, *undokakuho, *undofukugen) |
