# 画面設計書 14-検索ウィンドウ

## 概要

本ドキュメントは、LLDB Curses GUIにおける検索ウィンドウの画面設計を記述したものである。

### 本画面の処理概要

本画面は、ファイル、シンボル、変数などを検索するための汎用検索ウィンドウである。検索テキストを入力すると、CommonCompletionSearcherDelegateを使用してリアルタイムで補完候補を表示し、ユーザーが選択した候補に対してコールバック処理を実行する。

**業務上の目的・背景**：デバッグ中に特定のファイル、シンボル、変数を素早く検索・選択できることは、効率的なデバッグワークフローにおいて重要である。特に大規模なコードベースでは、ファイル名やシンボル名を手動で入力するよりも、補完機能を活用した検索が生産性を大幅に向上させる。この検索ウィンドウは、プロセスアタッチフォームでのプロセス名検索など、様々な場面で再利用される汎用コンポーネントとして設計されている。

**画面へのアクセス方法**：
- プロセスアタッチフォームなど、検索機能を必要とするフォームから呼び出される
- 直接的なメニューアクセスはなく、他のフォームやダイアログから間接的に起動

**主要な操作・処理内容**：
1. 検索テキストフィールドに文字を入力
2. 入力に応じてリアルタイムで検索結果（マッチ候補）が更新
3. 上下矢印キーまたはTab/Shift+Tabで候補を選択
4. Enterキーで選択した候補を確定し、コールバックを実行
5. ESCキーで検索をキャンセルしウィンドウを閉じる

**画面遷移**：
- 遷移元：プロセスアタッチフォーム（プロセス検索時）、その他検索を必要とするフォーム
- 遷移先：Enterで選択確定後、呼び出し元のフォームに戻る。ESCでキャンセル時も呼び出し元に戻る

**権限による表示制御**：特になし。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 8 | LLDB | 主機能 | SearcherWindowDelegateによるファイル/シンボル/変数検索。CommonCompletionSearcherDelegateを使用した補完機能 |

## 画面種別

検索ダイアログ

## URL/ルーティング

該当なし（Curses GUI内部のサブウィンドウとして表示）

## 入出力項目

| 項目名 | 項目種別 | データ型 | 必須 | 初期値 | 説明 |
|--------|----------|----------|------|--------|------|
| Search | テキストフィールド | String | - | 空文字列 | 検索文字列の入力フィールド |

## 表示項目

| 項目名 | 表示位置 | 説明 |
|--------|----------|------|
| タイトル | ウィンドウ上部 | SearcherDelegateから取得したウィンドウ名 |
| フッター | ウィンドウ下部 | "Press Esc to Cancel" |
| Searchフィールド | コンテンツ上部 | 検索テキスト入力フィールド |
| マッチリスト | Searchフィールド下部 | 検索結果の候補リスト（スクロール可能） |

### ウィンドウレイアウト

```
___<Searcher Window Name>____________________________
|                                                   |
| __[Search]_______________________________________ |
| |                                               | |
| |_______________________________________________| |
| - Match 1.                                        |
| - Match 2.                                        |
| - ...                                             |
|                                                   |
|____________________________[Press Esc to Cancel]__|
```

## イベント仕様

### 1-テキスト入力

1. TextFieldDelegateがキー入力を処理
2. FieldDelegateHandleChar()がeKeyHandledを返した場合、UpdateMatches()を呼び出し
3. SearcherDelegate::UpdateMatches()で検索結果を更新
4. m_selected_matchを0にリセット（先頭候補を選択）

### 2-候補選択（下方向）

1. Tab または下矢印キーを押下
2. SelectNext()を呼び出し
3. m_selected_matchが最後の候補でなければインクリメント

### 3-候補選択（上方向）

1. Shift+Tab または上矢印キーを押下
2. SelectPrevious()を呼び出し
3. m_selected_matchが0でなければデクリメント

### 4-候補確定

1. Enter または改行キーを押下
2. ExecuteCallback(window)を呼び出し
3. SearcherDelegate::ExecuteCallback(m_selected_match)でコールバック実行
4. 親ウィンドウからサブウィンドウを削除

### 5-キャンセル

1. ESCキーを押下
2. 親ウィンドウからサブウィンドウを削除
3. コールバックは実行されない

### 6-スクロール更新

1. UpdateScrolling()で選択項目が可視範囲に入るよう調整
2. 選択項目がm_first_visible_matchより上なら、m_first_visible_matchを更新
3. 選択項目が最後の可視項目より下なら、m_first_visible_matchを更新

## データベース更新仕様

該当なし（データベースを使用しないデバッガアプリケーション）

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|--------------|------|---------------|----------|
| MSG-001 | UI | Press Esc to Cancel | ウィンドウフッターに常時表示 |

## 例外処理

| 例外条件 | 処理内容 |
|----------|----------|
| マッチなし | 空のリストを表示（DrawMatches()で何も描画しない） |
| 検索エラー | SearcherDelegateの実装に依存 |

## 備考

- SearcherWindowDelegateはWindowDelegateを継承した汎用検索ウィンドウ
- 検索ロジックはSearcherDelegateSPに委譲（ストラテジーパターン）
- CommonCompletionSearcherDelegateはCommandCompletionsの共通コールバックを使用
- ウィンドウ内部は1文字のパディングで囲まれている

---

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

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

### 推奨読解順序

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

まず、SearcherDelegateインターフェースとSearcherWindowDelegateの関係を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | IOHandlerCursesGUI.cpp | `lldb/source/Core/IOHandlerCursesGUI.cpp` | 行3650-3670: SearcherDelegateインターフェース |
| 1-2 | IOHandlerCursesGUI.cpp | `lldb/source/Core/IOHandlerCursesGUI.cpp` | 行3827-3863: CommonCompletionSearcherDelegateクラス |

**読解のコツ**: SearcherDelegateは以下の抽象メソッドを定義：
- GetNumberOfMatches(): マッチ数を返す
- GetMatchTextAtIndex(index): 指定インデックスのマッチテキストを返す
- UpdateMatches(text): 検索テキストでマッチリストを更新
- ExecuteCallback(match_index): 選択されたマッチに対するコールバック実行

#### Step 2: SearcherWindowDelegateを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | IOHandlerCursesGUI.cpp | `lldb/source/Core/IOHandlerCursesGUI.cpp` | 行3672-3818: SearcherWindowDelegateクラス全体 |

**主要処理フロー**:
- **行3674-3677**: コンストラクタ - SearcherDelegateSPとTextFieldDelegateを初期化
- **行3697-3704**: GetNumberOfVisibleMatches() - 可視マッチ数の計算
- **行3706-3717**: UpdateScrolling() - 選択項目の可視性確保
- **行3719-3736**: DrawMatches() - マッチリストの描画
- **行3738-3748**: DrawContent() - テキストフィールドとマッチリストの描画
- **行3750-3761**: WindowDelegateDraw() - ウィンドウ全体の描画
- **行3763-3771**: SelectNext()/SelectPrevious() - 候補選択
- **行3773-3776**: ExecuteCallback() - コールバック実行とウィンドウ削除
- **行3778-3781**: UpdateMatches() - 検索結果更新
- **行3783-3809**: WindowDelegateHandleChar() - キー入力処理

#### Step 3: CommonCompletionSearcherDelegateを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | IOHandlerCursesGUI.cpp | `lldb/source/Core/IOHandlerCursesGUI.cpp` | 行3827-3863: CommonCompletionSearcherDelegateクラス |

**主要処理フロー**:
- **行3831-3834**: コンストラクタ - Debugger、completion_mask、callbackを受け取る
- **行3836-3840**: GetNumberOfMatches()/GetMatchTextAtIndex() - StringListへの委譲
- **行3842-3849**: UpdateMatches() - CommandCompletions::InvokeCommonCompletionCallbacksを使用
- **行3851-3853**: ExecuteCallback() - ユーザー定義のコールバック関数を実行

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

```
[呼び出し元フォーム]
    |
    +-- new SearcherWindowDelegate(delegate_sp)
            |
            +-- m_delegate_sp [SearcherDelegateSP]
            +-- m_text_field [TextFieldDelegate]
            +-- m_selected_match = 0
            +-- m_first_visible_match = 0

[描画時]
SearcherWindowDelegate::WindowDelegateDraw()
    |
    +-- window.Erase()
    |
    +-- window.DrawTitleBox(name, "Press Esc to Cancel")
    |
    +-- DrawContent()
            |
            +-- content_bounds.HorizontalSplit() [テキストフィールドとマッチ領域を分割]
            |
            +-- m_text_field.FieldDelegateDraw() [テキストフィールド描画]
            |
            +-- DrawMatches() [マッチリスト描画]
                    |
                    +-- UpdateScrolling()
                    |
                    +-- GetNumberOfVisibleMatches()
                    |
                    +-- m_delegate_sp->GetMatchTextAtIndex() [各マッチテキスト取得]

[キー入力時]
SearcherWindowDelegate::WindowDelegateHandleChar()
    |
    +-- [Enter/改行] ExecuteCallback()
    |       |
    |       +-- m_delegate_sp->ExecuteCallback(m_selected_match)
    |       +-- window.GetParent()->RemoveSubWindow()
    |
    +-- [Tab/下矢印] SelectNext()
    |
    +-- [Shift+Tab/上矢印] SelectPrevious()
    |
    +-- [ESC] RemoveSubWindow()
    |
    +-- [その他] m_text_field.FieldDelegateHandleChar()
            |
            +-- [eKeyHandled] UpdateMatches()
                    |
                    +-- m_delegate_sp->UpdateMatches(m_text_field.GetText())
                    +-- m_selected_match = 0
```

### データフロー図

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

ユーザー入力 ----------------> TextFieldDelegate -----------------> 検索テキスト
(キーボード)                        |
                                    v
                            SearcherWindowDelegate
                                    |
                                    +-- UpdateMatches()
                                            |
                                            v
                            SearcherDelegate::UpdateMatches()
                                            |
                                            v
                            [CommonCompletionSearcherDelegate]
                                            |
                                            +-- CommandCompletions::InvokeCommonCompletionCallbacks()
                                                    |
                                                    v
                                            CompletionResult
                                                    |
                                                    +-- GetMatches() --> StringList (m_matches)
                                                            |
                                                            v
                                                    マッチリスト表示

選択確定 -------------------> ExecuteCallback() -----------------> コールバック実行
(Enterキー)                         |
                                    +-- m_callback(selected_match)
                                            |
                                            v
                                    呼び出し元フォームへ結果を通知
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| IOHandlerCursesGUI.cpp | `lldb/source/Core/IOHandlerCursesGUI.cpp` | ソース | SearcherWindowDelegate（行3672-3818）、SearcherDelegate（行3650-3670）、CommonCompletionSearcherDelegate（行3827-3863）の実装 |
| CommandCompletions.h | `lldb/include/lldb/Interpreter/CommandCompletions.h` | ヘッダー | InvokeCommonCompletionCallbacks()のインターフェース |
| CompletionRequest.h | `lldb/include/lldb/Utility/CompletionRequest.h` | ヘッダー | CompletionRequestクラスの定義 |
| StringList.h | `lldb/include/lldb/Utility/StringList.h` | ヘッダー | StringListクラス（検索結果の格納） |
