# アプリケーションからのアクションの 実行

アプリケーションが拡張性のある一連のデータ型を管理する場合には、アクションの実行によりデータ型を直接実行しなければなりません。 この章では、アプリケーションからアクションを実行する方法について説明します。 アクションの実行方法を示すサンプル・プログラムも示します。

アクションとアクションの作成の詳細については、
このマニュアルの PG.datat.mkr.1と、 共通デスクトップ環境 上級ユーザおよびシステム管理者ガイドの次の章を参照してください。

- 「アクションおよびデータ型の概要」

- 「アクション作成ツールを使ったアクションとデータ型の作成」

- 「手動によるアクションの作成」

- 「手動によるデータ型の作成」

  PG.aIII.mkr.3
  PG.aIII.mkr.4
  PG.aIII.mkr.5
  PG.aIII.mkr.6
  PG.aIII.mkr.7
  PG.aIII.mkr.18

## アプリケーションからアクションを実行する方法

デスクトップ・サービス・ライブラリによってエクスポートされたアクション実行APIは、アプリケーションから別のアプリケーションを実行したり、操作を実行するための方法の1つです。 その他の方法として、次のものがあります。

- `fork/exec`システム・コール

- ToolTalkメッセージ

これらの方法は、それぞれ利点と制約があるので、具体的な状況を評価して、どちらが適切かを判断しなければなりません。

アクション実行APIの利点は、次のとおりです。

- アクションは、従来の コマンド行アプリケーション(すなわち、`COMMAND`アクション)と ToolTalkアプリケーション(すなわち、`TT_MSG`アクション)の両方をカプセル化することができます。 アクションを実行するアプリケーションは、コマンドがフォークされたのか、それともメッセージが送られたのかを知る必要はありません。

- アクションは、多様性を持ち、デスクトップのデータ型機構と統合されます。 このことは、[開く]や[印刷]などのアクションは、与えられる引き数の型に基づいて異なる動作をするが、動作の違いは、アクションを呼び出すアプリケーションに対して透過されることです。

- アクションは、アプリケーション開発者、システム統合者、システム管理者、およびエンド・ユーザに対して、構成の大きな可能性を提供します。 これらのユーザは、アクション・データベースを編集して、アクションの実行方法の定義を変更することができます。

- アクションは、分散環境でも有効です。アプリケーションが `fork/exec`により別のアプリケーションを直接実行する場合には、両方のアプリケーションが同じシステム上で実行できなければなりません。 それに対して、アクション実行APIは、アクション・データベース内の情報に基づいて、どのシステム上で`COMMAND`アクションを実行するかを判断します。

- アクションによって、デスクトップの動作と常に一貫性のあるアプリケーションの動作が可能になります。 これは、デスクトップのコンポーネントがユーザのデータ・ファイルを操作するとき、アクションを使用することで対話するからです。

アクション実行 API の欠点は、戻り値機能が制限されている実行方法であることであり、実行されたアクション・ハンドラとの対話機能がないことです。 これらの機能が必要な場合には、`fork/exec/pipes`を使用できます。ただし、CDEで望ましいプロセス間通信の方法は、一般化されたクライアント/サーバ・パラダイムを持つToolTalkです。

実行について説明します。 アプリケーションがいくつかの異なる形式(テキストとグラフィック)のデータ・ファイルを管理すると仮定し、これらのファイルの編集と表示の手段をユーザに提供する必要があると仮定します。 アクションを使用せずにこれを実現するには、次の方法の一つを使用することになります。

- `
  fork/exec` を使用して、適切なエディタを起動し、ユーザがエディタの名前を指定するための何らかの方法(環境変数など)を考えてください。 このアプローチには次のような制約があります。

  - システム・コールによりサブプロセスを実行し、その結果のシグナルを監視する複雑なコードを書かなければなりません。

  - アプリケーションと同じシステム上で使用できるエディタが必要であり、システム管理者は、`rsh`などの機能を使用する複雑な構成を提供しなければなりません。

  - システム管理者とユーザは、アプリケーションの固有の構成モデルを学び、管理しなければなりません。

- メッセージを使用して、編集や表示などの操作をデータに対して実行することを要求します。 このアプローチには、すべてのデータ型に対して使用可能なToolTalk形式のエディタが必要であるという制約があります。

アクションによりこれを実現するには、バッファまたはデータ・ファイルに対して[開く]アクションを実行するだけです。 アクション実行APIはアクション・データベースに基づいて、送信する適切なメッセージまたは実行するコマンドを判断し、一時ファイルの作成か削除、また必要なシグナルの取り込みなどすべての詳細を処理します。

##
アクションの型

アクションのアプリケーション・プログラム・インタフェース(API)は、どの種類のアクションに対しても機能します。 デスクトップでのアクションの種類は、次のとおりです。

コマンド・アクション
実行するコマンド行を指定します。
ToolTalk アクション
送信するToolTalkメッセージを指定します。 メッセージは、適切なアプリケーションによって受信されます。
マップ・アクション
特定の動作を定義する代わりに、別のアクションを参照します。

詳しくは、共通デスクトップ環境 上級ユーザおよびシステム管理者ガイドの「アクションおよびデータ型の概要」を参照して下さい。

##
アクション実行 API

アクション実行APIは、デスクトップ・サービス・ライブラリからエクスポートされて、次のような多数のタスクを実行する関数を提供します。

- アクションおよびデータ型定義のデータベースを初期化し、読み込みます。 アクションを実行するためには、その前にデータベースが読み込まれていなければなりません。

- データベースに問い合わせます。指定されたアクション、またはそれに関連付けられたアイコン・イメージ、ラベル、または記述が存在するかどうかを判断する関数があります。

- アクションを実行します。 アプリケーションは、ファイルまたはバッファ引き数をアクションに渡すことができます。

- アクション・ステータスを受け取り、引き数を返すコールバックを登録します。

## 関連情報

アクション・コマンド、関数およびデータ形式の詳細については、次のマニュアル・ページを参照して下さい。

- `dtaction`(1)

- `dtactionfile(4)`

- `DtActionCallbackProc`(3)

- `DtActionDescription`(3)

- `DtActionExists`(3)

- `DtActionIcon`(3)

- `DtActionInvoke`(3)

- `DtActionLabel`(3)

- `DtActionQuit`(3)

- `DtActionQuitType`(3)

- `DtActionStUpCb`(3)

- `dtexec`(1)

##
actions.c プログラム例

この節では、簡単なプログラム例`actions.c`について説明します。 `actions.c`の完全なリストは、この章の終りにあります。

### アクションおよびデータ型データベースの読み込み

アプリケーションがアクションを実行するためには、そのまえに、デスクトップ・サービス・ライブラリ(アクション実行 API を含む)を初期化して、アクションおよびデータ型定義のデータベースを読み込まなければなりません。

### デスクトップ・サービス・ライブラリを初期化するには

1. デスクトップ・サービス・ライブラリを初期化するには`
   DtInitialize()`関数を使用します。

       DtInitialize(*display,widget,*name,*tool_class)

   `DtInitialize()`は、デフォルトのイントリンシクス関数`XtAppContext`を使用します。 API は、アプリケーションがapp_contextを指定しなければならないときに使用する追加の関数 `
   DtAppInitialize()`を提供します。:

       DtAppInitialize(app_context,*display,widget,*name, tool_class)

#### DtInitialize() の例

次のコードの一部分は、 プログラム例`actions.c`の中で `DtInitialize()`がどのように使用されているかを示しています。

    if (DtInitialize(XtDisplay(shell), shell, argv[0],ApplicationClass)==False) {
        /* DtInitialize() has already logged an appropriate error msg */
        exit(1);
    }

### アクションおよびデータ型データベースを読み込むには

1. アクションおよびデータ型データベースを読み込むには、`
   DtDbLoad()`関数を使用します。

       DtDbLoad(void)

   `DtDbLoad()`は、アクションおよびデータ型データベースを読み込みます。 この関数は、データベースファイルを検索するディレクトリのセット(データベース検索パス)を判断して、データベース内で見つかった`*.dt`ファイルを読み込みます。 ディレクトリ検索パスは、`DTDATABASESEARCHPATH`環境変数と内部のデフォルト値に基づきます。

### 再読み込みイベントの通知を要求するには

長時間実行中のアプリケーションの中でDtDbLoad()を使用する場合には、データベースが変更されたときには、動的に再読み込みしなければなりません。

1. `
   DtDbReloadNotify()`関数を使用して、再読み込みイベントの通知を要求します。

    /* Notice changes to the database without needing to restart

      application */

     DtDbReloadNotify(DbReloadCallbackProc, callback_proc,

      XTPointer, client_data);

1. 次のことを実行するコールバックを指定します。

   - アプリケーションによって保持されている、キャッシュされたデータベース情報を破棄する。

   - `DtDbLoad()`関数を再びコールする。

C allback_procは、アプリケーションが保持している、キャッシュされたデータベース情報をクリーンアップしてから、`DtDbLoad()`を呼び出します。 Client_dataを使用して、追加のクライアント情報をコールバック・ルーチンに渡すことができます。

### アクション・データベースのチェック

アプリケーションは、アクションのアイコンまたはラベルを表示する必要がある場合には、データベースにアクセスします。 また、アクションを実行する前にアプリケーションは、その存在をチェックできます。 データベース内のアクションは、アクション名によって識別されます。

    ACTION action_name
    {

      …

    }

例えば、[電卓]アクション定義は次のとおりです。

    ACTION Dtcalc

    {

            LABEL    電卓

            ICON      Dtcalc

            ARG_COUNT      0

            TYPE            COMMAND

            WINDOW_TYPE      NO_STDIO

            EXEC_STRING      /usr/dt/bin/dtcalc

            DESCRIPTION      電卓(Dtcalc)アクションは、デスクトップ電卓 \ アプリケー                         ションを起動します。

    }

[電卓]アクションのアクション名はDtcalcです。

実行形式ファイルがデータベース内のアクション名と一致するファイル名を持つときには、そのファイルはアクション・ファイルです。 すなわち、基本のアクションの表現です。 そのファイルのアイコンとラベルに関する情報は、データベースに格納されます。

### 指定されたアクション定義が存在するかどうかを判断するには

1. 指定されたアクション定義が存在するかどうかを判断するには、`
   DtActionExists()`関数を使用します。

       DtActionExists(*name)

   `DtActionExists()`は、 指定された名前がデータベース内のアクションの名前に一致するかどうかをチェックします。 この関数は、名前がアクション名に一致する場合にはTrueを返し、その名前のアクションが見つからない場合にはFalseを返します。

### 指定されたアクションのアイコン・イメージ情報を取り出すには

1. アイコン・イメージ情報を取り出すには、 `DtActionIcon()`関数を使用します。

       DtActionIcon(char *action_name)

アクション定義は、アクションを表すために使われるアイコン・イメージを定義のICONフィールドで指定します。

    ACTION action_name
    {

       ICON  icon_image_base_name
       …

    }

`DtActionIcon()`は、アイコン・イメージ・フィールドの値にある文字列を返します。 アクション定義にアイコン・フィールドがない場合には、この関数はデフォルトのアクション・アイコン・イメージの値`Dtactn`を返します。

次に、使用したいアイコンとサイズの位置を決めます。 アイコンには4つのサイズがあり、ビットマップまたはピックスマップ形式で扱えます。たとえば、[電卓]のアクション定義からアイコン・ファイルのベース名を見つけることができます。 次に、そのベース名と PG.aIII.mkr.13の情報の組み合わせと、すべてのアイコンの格納情報から、目的のアイコン・ファイルを見つけだせます。

[電卓]アクションのアイコン名は `Dtcalc`ですが、これはファイル名全体ではありません。 アイコン・ファイル名はアイコンのサイズに基づきます。 PG.aIII.mkr.13は、デスクトップ・アイコンのサイズとファイル名の命名規則を示します。

### アイコンのサイズとファイル名

`アイコンのサイズ` | `ビットマップ名` | `ピックスマップ名`
16 × 16 (極小) | name`.t.bm` | name`.t.pm`
24 × 24 (小) | name`.s.bm` | name`.s.pm`
32 × 32 (中) | name`.m.bm` | name`.m.pm`
48 × 48 (大) | name`.l.bm` | name`.l.pm`

デスクトップ・アイコン・ファイルの詳細については、共通デスクトップ環境 上級ユーザおよびシステム管理者ガイドの「デスクトップのアイコンの作成」を参照してください。

ビットマップの場合、マスクとして使われる追加のファイルがあり、そのファイルの拡張子`_m.bm`で終わります。 したがって、各サイズのアイコンに対して合計3個のファイルがあります。 次に、電卓のアイコン・ファイルを示します。

    Dtcalc.t.bm

    Dtcalc.t.pm

    Dtcalc.t_m.bm

    Dtcalc.m.bm

    Dtcalc.m.pm

    Dtcalc.m_m.bm

    Dtcalc.l.bm

    Dtcalc.l.pm

    Dtcalc.l_m.bm

電卓には小型アイコン(`Dtcalc.s.bm`, `Dtcalc.s.pm`,`Dtcalc.s_m.bm`)がない点に注意してください。

`DtActionIcon()`はベース名だけを返します。 電卓の場合は`Dtcalc`です。 種類(ピックスマップまたはビットマップ)とサイズ(極小、小、中、大)を選んで、使用可能な拡張子をベース名に追加してください。 また、ファイルがどこにあるかを知っておいてください。

### アクションのローカライズ・ラベルを取り出すには

1. アクションのローカライズ・ラベルを取り出すには、 `DtActionLabel()`関数を使用します。

       char *DtActionLabel(char *actionName)

アクション定義にはラベルを入れることができます。 ラベルは、label_textフィールドを使用して定義されます。

    ACTION action_name
    {

       LABEL label_text
       …

    }

このラベルは、グラフィック・コンポーネント(ファイル・マネージャやアプリケーション・マネージャなど)中でアクションのアイコンにラベルを付けるために使用されます。 アクション定義にlabel_textフィールドがない場合には、 action_nameが使用されます。

label_text文字列の値は、エンドユーザがアクションを見分けられるように、すべてのインタフェース・コンポーネントによって使用されなければなりません。

`DtActionLabel()`関数は、 actionNameという名前のアクションのアクション定義の中のlabel_textフィールドの値を返します。 label_textフィールドがない場合には、この関数はactionNameを返します。

### アクションの実行

アプリケーションがデスクトップ・サービス・ライブラリを初期化した後は、アクションを実行することができます。

### アクションを実行するには

1. アクションを実行するには `DtActionInvoke`関数を使用します。

       DtActionInvokeID (widget, action, args, argCount, termOpts, execHost,
                              contexDir, useIndicator, statusUpdateCb, client_data)

`DtActionInvoke()`は、アクション・データベースから、指定されたアクション名に一致するエントリを探して、指定されたクラス、型、およびカウントの引数を受け入れます。 アクションを実行する前に、アプリケーションはデータベースを初期化し、読み込まなければならないので注意してください。

## actions.cのリスト

    /*
     * (c) Copyright 1993, 1994 Hewlett-Packard Company
     * (c) Copyright 1993, 1994 International Business Machines Corp.
     * (c) Copyright 1993, 1994 Sun Microsystems, Inc.
     * (c) Copyright 1993, 1994 Novell, Inc.
     */

    #include <Xm/XmAll.h>
    #include <Dt/Dt.h>
    #include <Dt/Action.h>

    #define ApplicationClass “Dtaction“

    static Widget shell;
    static XtAppContext appContext;
    static Widget actionText;
    static Widget fileText;

    static void CreateWidgets(Widget);
    static void InvokeActionCb(Widget, XtPointer, XtPointer);
    static void InvokeAction(char*, char*);
    static void DbReloadProc(XtPointer);

    void main(int argc, char **argv)
    {
        Arg args[20];
        int n=0;
        int numArgs = 0;

        shell = XtAppInitialize(&appContext, ApplicationClass, NULL, 0,

            &argc, argv, NULL, args, n);

        CreateWidgets(shell);

     if (DtInitialize(XtDisplay(shell), shell, argv[0],

      ApplicationClass)==False) {
            /* DtInitialize() has already logged an appropriate error msg */
            exit(-1);
        }

        /* Load the filetype/action databases */
        DtDbLoad();

        /* Notice changes to the database without needing to restart application */
        DtDbReloadNotify(DbReloadProc, NULL);

        XtRealizeWidget(shell);
        XmProcessTraversal(actionText, XmTRAVERSE_CURRENT);

        XtAppMainLoop(appContext);
    }

    static void CreateWidgets(Widget shell)
    {
        Widget messageBox, workArea, w;
        Arg args[20];
        int n;
        XmString labelString;

        labelString = XmStringCreateLocalized(“Invoke“);

        n = 0;
        XtSetArg(args[n], XmNdialogType, XmDIALOG_TEMPLATE); n++;
        XtSetArg(args[n], XmNokLabelString, labelString); n++;
        messageBox = XmCreateMessageBox(shell, “messageBox“, args, n);
        XtManageChild(messageBox);
        XmStringFree(labelString);
        XtAddCallback(messageBox, XmNokCallback, InvokeActionCb, NULL);

     n = 0;
        XtSetArg(args[n], XmNorientation, XmVERTICAL); n++;
        XtSetArg(args[n], XmNpacking, XmPACK_COLUMN); n++;
        XtSetArg(args[n], XmNnumColumns, 2); n++;
        XtSetArg(args[n], XmNentryAlignment, XmALIGNMENT_END); n++;
        workArea = XmCreateWorkArea(messageBox, “workArea“, args, n);
        XtManageChild(workArea);

        labelString = XmStringCreateLocalized(“Invoke Action:“);
        n = 0;
        XtSetArg(args[n], XmNlabelString, labelString); n++;
        w = XmCreateLabel(workArea, “actionLabel“, args, n);
        XtManageChild(w);
        XmStringFree(labelString);

        labelString = XmStringCreateLocalized(“On File:“);
        n = 0;
        XtSetArg(args[n], XmNlabelString, labelString); n++;
        w = XmCreateLabel(workArea, “fileLabel“, args, n);
        XtManageChild(w);
        XmStringFree(labelString);

        n = 0;
        XtSetArg(args[n], XmNcolumns, 12); n++;
        actionText = XmCreateTextField(workArea, “actionText“, args, n);
        XtManageChild(actionText);

        n = 0;
        XtSetArg(args[n], XmNcolumns, 12); n++;
        fileText = XmCreateTextField(workArea, “fileText“, args, n);
        XtManageChild(fileText);
    }

    static void DbReloadProc(XtPointer cd)
    {
        /* Pick up any dynamic changes to the database files */
        DtDbLoad();
    }

    static void InvokeActionCb(Widget w, XtPointer cd, XtPointer cb)
    {
        char *action;
        char *file;

        action = XmTextFieldGetString(actionText);

        if (action == NULL) return;
        if (strlen(action) == 0) {
            XtFree(action);
            return;
        }

        file = XmTextFieldGetString(fileText);

        InvokeAction(action, file);

        XtFree(action);
        XtFree(file);

        XmTextFieldSetString(actionText, ““);
        XmTextFieldSetString(fileText, ““);

        XmProcessTraversal(actionText, XmTRAVERSE_CURRENT);
    }

    static void InvokeAction(char *action, char *file)
    {
        DtActionArg *ap = NULL;

    int nap = 0;
        DtActionInvocationID actionId;

        /* If a file was specified, build the file argument list */

    printf(“%s(%s)\n“,action,file);
        if (file != NULL && strlen(file) != 0) {
            ap = (DtActionArg*) XtCalloc(1, sizeof(DtActionArg));
            ap[0].argClass = DtACTION_FILE;
            ap[0].u.file.name = file;
            nap = 1;
        }

        /* Invoke the specified action */

     actionId = DtActionInvoke(shell,action,ap,nap,NULL,NULL,NULL,True,NULL,NULL);
    }