# 複雑なスクリプト複雑なスクリプト

この章は、2章で説明したスクリプトよりも、さらに複雑なスクリプトについて説明します。 このスクリプトは非常に長いため、スクリプト全体は、付録Cにリストします。 このマニュアルは、KornShellプログラミングのチュートリアルではありません。 KornShellプログラミングをあまり理解していない場合は、KornShellプログラミング用の マニュアルを入手し、参照してください。

## script_findの使用方法

スクリプト
`script_find`は、`dtksh`を使用して、`find`コマンドのグラフィカル・インタフェースを 提供する方法を示しています。`script_find`は、`find`コマンドのパラメータを 指定できるウィンドウを生成します。スクリプトを完全に理解するには、`find`を理解し、 マニュアル・ページを使用可能にしておく必要があります。`script_find`によって 生成されるウィンドウ内の多くのトグル・ボタン・メニュー選択肢は、`find`コマンドの 知識が多少必要です。

スクリプトのウィンドウで、検索するディレクトリとファイル名を指定します。 他のオプションで、検索用のファイル・システムの型と一致するファイルの型を 制限できます。図4-1にscript_findのウィンドウを示します。

### script_findのウィンドウ

ウィンドウの上部にあるテキスト・フィールドに、捜したい検索ディレクトリとファイル名 を入力します。そして、5つのトグル・ボタンから適用可能な選択（または選択肢）を 選択します。オプション・メニューで、検索をさらに制限できます。必要な選択をすべて 行ってから[OK]ボタンをクリックします。処理が正常に終ると、その後すぐに ウィンドウが現れ、`find`操作の結果が表示されます。検索ディレクトリ またはファイル名を指定しないと、または無効なディレクトリを指定すると、エラー・ ダイアログが表示されます。たとえば、`/users/dlm`ディレクトリ 下のどこに`two_letter_calls`というファイルがあるか捜しますとします。 検索ディレクトリのテキスト・フィールドに、そのディレクトリを入力するときに、 `/users/dlm`の代わりに`/users/dln`と誤って入力したと します。その状態で、[OK]または[Apply]をクリックすると、`script_find`は、`/users/dln`ディレクトリを見つけることができません。 そのため、エラー・ダイアログを生成して、これをユーザに通知します。

### script_findエラー・ダイアログ

誤りを訂正すると、`script_find`は適切に実行し、要求したファイルの 絶対パスを表示した`dtterm`ウィンドウを生成し、ファイルが見つかった ことを示します。

### 絶対パスが示されているウィンドウ

`script_find`が指定したディレクトリに見つからなかった時は、`dtterm`ウィンドウには何も表示されません。

## script_findの解析

`script_find`の構造は、Cプログラムと似ています。初めにいくつかの関数とコールバック、 次にメイン・スクリプトが示されるという構造です。

スクリプトの初めの2行は重要で、すべての`dtksh`スクリプトに含める 必要があります。

    #! /usr/dt/bin/dtksh
    . /usr/dt/lib/dtksh/DtFunc.dtsh

1行めは`dtksh`システムを実行します。2行めは`dtksh`簡易関数をロードします。 2行めは、第2章で説明したスクリプトには使用されていません。それは、これらの スクリプトが`dtksh`簡易関数を使用しないためです。

### 関数とコールバック

`script_find`には、次の関数とコールバックがあります。

- `PostErrorDialog()`

- `OkCallback()`

- LoadStickyValues()

- `EvalCmd()`

- `RetrieveAndSaveCurrentValues()`

#### PostErrorDialog()

この関数は、ユーザが無効なディレクトリを入力したときなど、エラーの発見時に呼び 出されます。この関数は、ダイアログ・ボックスを表示 し、簡易関数`
DtkshDisplayErrorDialog()`を呼び出されます。 この関数は、「Find Error」というタイトルで、呼び出した位置から渡される変数$1にメッセージが格納されているダイアログ・ボックスを表示します。

    dialogPostErrorDialog()
    {
         DtDisplayErrorDialog “Find Error” “$1” \
         DIALOG_PRIMARY_APPLICATION_MODAL
    }

最後のパラメータ、`DIALOG_PRIMARY_APPLICATION_MODAL`は、他の相互動作が発生する前に 応答しなければならないダイアログを生成するように`dtksh`に伝えます。

#### OkCallback()

`OkCallback()`は、メインの`script_find`ウィンドウ上の[OK]または[Apply]ボタンの どちらかを押されると呼び出されます。 [OK]をボタンを押すと、script_findウィンドウ は管理されなくなります。[OK]または[Apply]ボタンで、入力した検索ディレクトリを 確認します。それが無効な場合、`OkCallback()`は、`PostErrorDialog()`を 呼び出します。それが有効な場合は、`script_find`のトグル・ボタンの状態がチェックされ、 その状態と一致するように、変数`$CMD`を調整します。 この変数には、最後に実行されるコマンドのすべてが含まれます。

#### LoadStickyValues()

この関数は、ウィンドウが生成および管理された後、メイン・プリグラムから呼び出され ます。スクリプトの最新の実行結果から、すべての値をロードします。 それらの値は`RetrieveandSaveCurrentValues()`関数によって、`Find.sticky`ファイルに保存されます。

#### EvalCmd()

`EvalCmd()`は`LoadStickyValues()`で使用され、`dtksh`コマンドとして`Find.sticky`の各行を評価します。 `Find.sticky`ファイル内のリストが次のとおりです。

    XmTextSetString $SD “/users/dlm”
    XmTextFieldSetInsertionPosition $SD 10
    XmTextSetString $FNP “two_letter_calls”
    XmTextFieldSetInsertionPosition $FNP 16
    XtSetValues $FSTYPE menuHistory:$NODIR
    XtSetValues $FILETYPE menuHistory:$NOTYPE
    XmToggleButtonSetState $T2 true false
    XmToggleButtonSetState $T4 true false

#### RetrievAndSaveCurrentValues()

`RetrieveAndSaveCurrentValues()`は、`script_find`ウィンドウにあるウィジェットの現在の設定と値を 検索し、それらを`Find.sticky`ファイルに保存します。 `Find.sticky`ファイルは、次にスクリプトが実行される時に、 `LoadStickyValues()`によって使用されます。

### メイン・スクリプト

スクリプトの残りは、Cプログラムの`Main()`に相当するものです。Xtイントリンシクス を初期化し、`script_find`ウィンドウで使用するすべてのウィジェットを生成します。 1行めの`set -f`は、`dtksh`に対し、パス名にあるワイルドカードの文字列の 拡張を禁止するよう指示しています。これは、`find`コマンドがこの拡張を実行できる ようにするために必要です。

`script_find`ウィンドウ(図4-4参照)は、4つの領域をもつフォーム・ウィジェットから 構成されます。領域は、セパレータ・ウィジェットによって明確にされています。 それぞれの領域にはいくつかのウィジェットがあり、そのすべてがフォーム・ウィジェット の子になります。

#### script_findウィンドウにあるウィジェット

ウィジェットは、領域ごとに順番に、上から下へ作成されます。

#### 初期化

初期化は、次のようなXtイントリンシクス関数`XtInitialize`で行います。

    XtInitialize TOPLEVEL find Dtksh $0 “${@:-}”

これは、次に生成されるフォーム・ウィジェットの親であるトップレベル・ シェルを生成します。

#### フォーム・ウィジェットの生成

メインの親ウィジェットとしてフォーム・ウィジェットを使用します。 フォーム・ウィジェットは、ユーザが子ウィジェットを抑制できるマネージャ・ ウィジェットです。メインの`script_find`ウィンドウにあるほとんどのウィジェットが フォーム・ウィジェットの子です。残りのウィジェットの作成の説明は、ウィンドウの 4つの領域(図4-4参照)ごとに説明します。

#### 1つめの領域

1つめの領域は、2つのラベル・ウィジェットと2つのテキストフィールド・ウィジェット、 および1つめと2つめの領域を区切るセパレータから構成されています。

##### `script_find`ウィンドウの1つめの領域

次のコードの部分は、1つめのラベル・ウィジェットを生成および配置し、`DtkshAnchorTop` および`DtkshAnchorLeft`簡易関数を使用して、フォーム・ウィジェットにそれを 配置します。

    XtCreateManagedWidget SDLABEL sdlabel XmLabel $FORM \
      labelString:”Search Directory:” \
      $(DtkshAnchorTop 12) \
      $(DtkshAnchorLeft 10)

次のコードの部分は、1つめのテキストフィールド・ウィジェットを生成および配置 しています。このウィジェットは、フォーム・ウィジェットとラベル・ウィジェットの 両方に関連して配置されます。

    XtCreateManagedWidget SD sd XmText $FORM \
      columns:30 \
      value:”.” \
      $(DtkshAnchorTop 6) \
      $(DtkshRightOf $SDLABEL 10) \
      $(DtkshAnchorRight 10) \
      navigationType:EXCLUSIVE_TAB_GROUP
    XmTextFieldSetInsertionPosition $SD 1

残りのラベル・ウィジェットとテキストフィールト・ウィジェットは、同じ方法で生成 されます。

セパレータ・ウィジェットはフォーム・ウィジェットの子として生成され、2つめのテキストフィールドの下に配置されます。

    XtCreateManagedWidget SEP sep XmSeparator $FORM \
      separatorType:SINGLE_DASHED_LINE \
      $(DtkshUnder $FNP 10) \
      $(DtkshSpanWidth)

#### 2つめの領域

2つめの領域は、1つのローカラム・ウィジェット、5つのトグルボタン・ガジェット、 およびセパレータ・ウィジェットから構成されます。

##### `script_find`ウィンドウの2つめの領域

ガジェットは、多くの属性を、その親に依存するウィジェットで、メモリ・リソースを節約できます。

ローカラム・ウィジェットは、フォーム・ウィジェットの子として生成され、1つめの 領域に生成されたセパレータ・ウィジェットの直下に配置されます。

    XtCreateManagedWidget RC rc XmRowColumn $FORM \
           orientation:HORIZONTAL \
           numColumns:3 \
           packing:PACK_COLUMN \
      $(DtkshUnder $SEP 10) \
      $(DtkshSpanWidth 10 10) \
      navigationType:EXCLUSIVE_TAB_GROUP

5つのトグルボタン・ガジェットは、`DtkshAddButtons`簡易関数を使用して、 ローカラム・ウィジェットの子として生成されます。

    DtkshAddButtons -w $RC XmToggleButtonGadget \
      T1 “Cross Mount Points”           ““\
      T2 “Print Matching Filenames”     ““\
      T3 “Search Hidden Subdirectories” ““\
      T4 “Follow Symbolic Links”        ““\
      T5 “Descend Subdirectories First” ““

次にセパレータ・ウィジェットが生成され、2つめと3つめの領域を区切ります。 このセパレータ・ウィジェットIDは、`SEP2`と呼ばれています。

    XtCreateManagedWidget SEP2 sep XmSeparator $FORM \
     separatorType:SINGLE_DASHED_LINE \
     $(DtkshUnder $RC 10) \
     $(DtkshSpanWidth)

#### 3つめの領域

3つめの領域は、2つのオプション・メニューとセパレータ・ウィジェットから生成されます。

##### `script_find`ウィンドウの3つめの領域

オプション・メニューは、プルダウン・メニューです。ユーザがオプション・メニュー・ ボタンをクリックすると、多数の選択肢をもつメニュー区画が現れます。ユーザは、適切 な選択肢にポインタをドラッグし、マウス・ボタンを離します。メニュー区画は消え、 オプション・メニュー・ボタンのラベルに新しい選択肢が表示されます。

1つめのオプション・メニューのメニュー区画は、多数のプッシュ・ボタン・ガジェット から構成され、`find`コマンドに強いることができる様々な制約を表示しています。

    XmCreatePulldownMenu PANE $FORM pane
    DtkshAddButtons -w $PANE XmPushButtonGadget \
      NODIR “no restrictions” ““\
      NFS   “nfs”             ““\
      CDFS  “cdfs”            ““\
      HFS   “hfs”             ““
    Next, the Option Menu button itself is created and managed, with the
    menu pane just created ($PANE) identified as a subMenuId:
    XmCreateOptionMenu FSTYPE $FORM fstype \
           labelString:”Restrict Search To File System Type:” \
           menuHistory:$NODIR \
           subMenuId:$PANE \
      $(DtkshUnder $SEP2 20) \
      $(DtkshSpanWidth 10 10) \
      navigationType:EXCLUSIVE_TAB_GROUP
    XtManageChild $FSTYPE

2つめのオプション・メニュー・ボタンも、同じ方法で生成されます。このボタンは、 `find`コマンドに、さらに制約を与えます。

3つめのセパレータは、他のセパレータと同じ方法で生成されます。

#### 4つめの領域

4つめの領域は、フォーム・ウィジェットの子である4つのプッシュ・ボタンから構成され ています。

4つのプッシュ・ボタンは次のように使用されます。

- [OK]は、`script_find`ウィンドウに入力されたパラメータで`find`コマンドを 実行し、`script_find`ウィンドウを閉じます。

- [Apply]は、`script_find`ウィンドウに入力されたパラメータで`find`コマンドを実行します。 `script_find`ウィンドウは閉じません。

- [Close]は、`find`コマンドを実行せずに`script_find`を終了します。

- [Help]は、`script_find`の使用に関する情報を示すダイアログ・ボックスを生成します。

プッシュ・ボタンは、それぞれ異なったラベルが付きますが、他のウィジェットとほとんど 同じ方法で生成および配置されます。 次のコードの部分は、[OK]ボタンを生成する方法を示しています。

    XtCreateManagedWidget OK ok XmPushButton $FORM \
           labelString:”Ok” \
      $(DtkshUnder $SEP3 10) \
      $(DtkshFloatLeft 4) \
      $(DtkshFloatRight 24) \
      $(DtkshAnchorBottom 10)
    XtAddCallback $OK activateCallback “OkCallback”

#### オペレーティング・パラメータの設定

`XtSetValues`は、最初のオペレーティング・パラメータを設定するのに使用します。

    XtSetValues $FORM \
      initialFocus:$SD \
      defaultButton:$OK \
      cancelButton:$CLOSE \
      navigationType:EXCLUSIVE_TAB_GROUP

- 最初のフォーカスは、1つめの領域の最初のテキストフィールド・ウィジェットに設定 されます。

- デフォルト・ボタンは4つめの領域の[OK]ボタンに設定されます。

- 取消しボタンは4つめの領域の[Close]ボタンに設定されます。

- ナビゲーション型は`EXCLUSIVE_TAB_GROUP.`に設定されます。

次の行は、改行キーがフォーム・ウィジェット内でデフォルト・ボタンをアクティブに しないテキストフィールド・ウィジェットを構成します。使用方法の詳細は、付録Bの `EXCLUSIVE_TAB_GROUP`の説明を参照してください。

    DtkshSetReturnKeyControls $SD $FNP $FORM $OK

#### 認識とループ

スクリプトの最後の3行は、`script_find`ウィンドウの前の値をロードし、 トップレベル・ウィジェットを実現します。そして、ユーザの入力を待つループに入り ます。

    LoadStickyValues
    XtRealizeWidget $TOPLEVEL
    XtMainLoop