ToolTalk ユーザーズガイド

付録 B ToolTalk サービスのデモンストレーション

この付録では、ToolTalk サービスが、アプリケーションと他のアプリケーションとの通信をどのように可能にしているのかを簡単なデモンストレーションによって示します。

簡易化されたアプリケーション間通信

ToolTalk サービスは、アプリケーション統合用関数の完全なセットを提供します。ToolTalk サービスによって提供された機能を使うことで、既存のアプリケーションは互いに「話す」ことができます。

ToolTalk のデモンストレーションは簡単です。簡単なテキストエディタを使いながら、ロードされたファイル内に表示されているフォントを変更するためにフォント名の選択をインタフェースに尋ねます。ToolTalk のデモンストレーションは、次のような X11R4 からの 2 つのアプリケーションから成ります。

この付録では、これら 2 つのアプリケーションが連携できるように変更する方法を概説します。アプリケーションへの ToolTalk コードの追加では、ToolTalk コードがどのようにソースコードファイルに取り組まれているかを示します。

連携機能の追加

ツールが連携できるようになる前に、.c、個々のアプリケーションの Makefile、および Xedit アプリケーションのヘッダーファイルを変更する必要があります。さらに Xfontsel アプリケーションの ToolTalk プロセス型 (ptype) を宣言するための新しいファイルを作成する必要もあります。

「vi」などの標準エディタを使い、これらを変更して ptype ファイルを作成してください。

Xedit アプリケーションの変更

Xedit アプリケーションを変更し、Xfontsel アプリケーションと通信できるようにするには、次のファイルを変更する必要があります。

Xedit は、ToolTalk デモンストレーションのために、ToolTalk ヘッダーファイルと xedit.c ファイル内の新しい ToolTalk コマンドについて知る必要があります。xedit.h ファイルでの変更方法は、例 B–1にコメントとともに示します。

次に、ToolTalk セッションを設定してフォント変更用のボタンを作成し、Xedit が ToolTalk メッセージを受信し処理できるように Xedit.c ファイルにコードを追加する必要があります。これらのファイルでの変更方法は、例 B–2にコメントとともに示されています。

commands.c ファイルにコードを追加して、フォント変更の完了時に応答を送る、または操作の異常終了時に通知するように、Xedit が Xfontsel アプリケーションに指示できるようにします。また、Xedit が何の操作を実行してほしいかを Xfontsel に知らせるコードを追加する必要もあります。これらのファイルへの変更方法は、例 B–3 にコメントとともに示されています。

Xedit プログラムへの最後の変更は、ToolTalk ライブラリを使用するように Makefile を変更します。これを行うために、次のように -ltt オプションを追加します。

 LOCAL_LIBRARIES = -ltt $(XAWLIB) $(XMULIB) $(XTOOLLIB) $(XLIB)

Xedit ファイルに対して指示された変更を行なった後、Xedit プログラムをコンパイルします。

Xfontsel アプリケーションの変更

Xfontsel アプリケーションを変更し、Xedit アプリケーションと通信できるようにするには、次のファイルを変更する必要があります。

また、Xfontsel アプリケーション用の ToolTalk ptype を宣言するための新しいファイルを作成する必要があります。

Xfontsel は、ToolTalk デモンストレーションのために、次のことを知る必要があります。

また Xfontsel は、フォントを変更するための適用ボタンとコマンドボックスを表示する必要があります。さらに、ToolTalk コールバックメッセージをいつ送信するかと、どのように ToolTalk セッションに参加するかを Xfontsel に知らせるために、コードを追加する必要があります。例 B–4でコメントとともに示しているように、Xfontsel.c ファイルが変更されます。

次に、ToolTalk ライブラリを使用する Xfontsel プログラムの Makefile を変更します。これを行うために、次のように -ltt オプションを追加します。

 LOCAL_LIBRARIES = -ltt $(XAWLIB) $(XMULIB) $(XTOOLLIB) $(XLIB)

ToolTalk 型機構は、ToolTalk サービスのルートメッセージを助けるように設計されています。最初にプロセス型 (ptype) を定義し、次にその ptype を ToolTalk 型コンパイラの tt_type_comp でコンパイルします。ToolTalk デモンストレーションについては、次に示すように Xfontsel アプリケーション用の ptype ファイルを作成する必要があります。


注 –

directory_name は、変更された Xfontsel ファイルが入っているディレクトリへのパス名です。


ptype xfontsel {				/* Process type identifier */
	start “/directory_name/xfontsel”; /* Start string */


 handle:	 			/* Receiving process */
		/* A signature is divided
 	 * into two parts by the => as follows:
		 * Part 1 specifies how the message is to be matched;
		 * Part 2 specifies what is to be taken when
 	 	 * a match occurs.
 		 */
 session GetFontName(out string fontname) => start;


} 

ツールが ptype を宣言すると、その ptype 内で表示されたメッセージパターンが自動的に登録されます。ToolTalk は、受信するメッセージをそれらの登録されたパターンと照合します。これらの静的メッセージパターンは、そのツールが ToolTalk サービスとの通信を終了するまで有効です。

ptype ファイルを作成した後、その ptype をインストールする必要があります。これを行うために、次のように ToolTalk 型コンパイラを実行します。

 machine_name% tt_type_comp xfontsel.ptype

xfontsel.ptype は、ユーザーの ptype ファイル名です。

Xfontsel ファイルに対して指示された変更を行い、ptype ファイルを作成し、その ptype をインストール後に Xfontsel プログラムをコンパイルします。

ツールコミュニケーション

ToolTalk 技術がどのように動作するかを見てみましょう。

  1. Xedit アプリケーションを開始します。

    次のコマンドを入力し、Xedit を開始します。

     machine_name% xedit
    

    図 B–1 のような画面が表示されます。

    図 B–1 Xedit 画面

    Graphic

  2. ファイルを読み込みます。

    Xedit 画面に読み込んだファイルが表示されます。

  3. 表示されたフォントを変更します。

    1. Xedit 画面上で「changefont」ボタンをクリックします。

      Xfontsel 画面が表示されます。

    2. Xfontsel 画面上で新しいフォントを選択します。

    3. Xfontsel 画面上で「apply」ボタンをクリックします。

      フォントが変更された Xedit 画面が表示されます。

アプリケーションへの ToolTalk コードの追加

この節では、ToolTalk コードがどのように Xedit および Xfontsel アプリケーションに追加されたかを説明します。

 #include <desktop/tt_c.h> 
/* ToolTalk のヘッダー */

Xedit ファイルへの ToolTalk コードの追加

Xedit ファイルに対する変更は、Xedit アプリケーションの変更で説明します。


例 B–1 Xedit.h ファイルの変更

 /*
 *	rcs_id[] = “$XConsortium: xedit.h,v 1.18 89/07/21 19:52:58 kit Exp $”;
 */

...

 #include <X11/Xaw/Viewport.h>
 #include <X11/Xaw/Cardinals.h>

 /*
 * ToolTalk のデモンストレーション用に、以下のインクルード行を追加する
 */
 #include <desktop/tt_c.h>	
 /* ToolTalk のヘッダ */

 extern struct _app_resources {
 Boolean enableBackups;
 char *backupNamePrefix;
 char *backupNameSuffix;

...

 /* xedit.c に外部宣言 */

 extern void Feep();
 /*
 * ToolTalk のデモンストレーション用に、以下の外部宣言を追加する
 */
 extern void processToolTalkMessage(); /* ToolTalk メッセージの処理 */
 extern void dieFromToolTalkError(); 
		/* エラーが発生した場合は異常終了する */
 extern Display *CurDpy;
  /* 表示 */

...

  /* commands.c に外部宣言 */

...

 extern void DoChangeFont();
 		/* フォントを変更する */ 


例 B–2 変更された Xedit.c ファイル

#if (!defined(lint) && !defined(SABER)) \
 static char Xrcsid[] = “$XConsortium: \
 xedit.c,v 1.23 89/12/07 \
 19:19:17 kit Exp $”;
 #endif 			/* lint && SABER */

...

 void main(argc, argv)
 int argc;
 char **argv;
 {
 Widget top;
 String filename = NULL;
 static void makeButtonsAndBoxes();

 /*
  * ToolTalk のデモンストレーション用に、
  * 以下の行を追加する
  */
 int ttmark;
/* ToolTalk のマーク */
 int ttfd;
/* ToolTalk のファイル記述子 */
 char *procid;	
/* プロセス識別子 */
 Tt_status ttrc;
/* ToolTalk の状態 */

 top = XtInitialize( “xedit”, \ 
“Xedit”, NULL, 0, &argc, argv);

...

XtRealizeWidget(top);
XDefineCursor(XtDisplay(top),XtWindow(top), \
XCreateFontCursor( XtDisplay(top), \ 
XC_left_ptr));
 /*
  * ToolTalk のデモンストレーション用に、
  * ToolTalk セッションをスタックの最初に
  * 作成して、デフォルトセッションとして
  * 設定するために、以下の行を追加する
  */
 ttmark = tt_mark();
 ttrc = tt_default_session_set( 
	/* 最上位ウィンドウを表示している .. */
 tt_X_session( 	
 /* .. X サーバーの .. */
 DisplayString( 
 /* .. X セッションに ..*/
 XtDisplay(top))));
 /* .. デフォルトセッションを設定する ... */
 /*
  * デフォルトセッションがない場合は異常終了する
  */
 dieFromToolTalkError( \
 “tt_default_session_set”,ttrc);  
 procid = tt_open();	
 	/* ToolTalk の初期化 */
		/*
		 * プロセス識別子がない場合は異常終了する
 	 */
 dieFromToolTalkError(“tt_open” \
,tt_ptr_error(procid));
 ttfd = tt_fd();	
		/* ToolTalk のファイル記述子 */
 	/*
		 * ファイル記述子がない場合は異常終了する
		 */
dieFromToolTalkError(“tt_fd”, \
tt_int_error(ttfd)); 
		/*
		 * ファイル記述子を起動する
 	 */
XtAddInput(ttfd, (XtPointer)XtInputReadMask, \
 processToolTalkMessage, 0);

 XtMainLoop();
 }

...

 MakeCommandButton(b_row, “load”, DoLoad);
 /*
  * ToolTalk のデモンストレーション用に、
  * フォント変更用コマンドのボタンを作成するために、* 
  * 次の行を追加する
  */
 MakeCommandButton(b_row, “changefont”, \ 
 DoChangeFont);	
 filenamewindow = MakeStringBox(b_row, \ 
“filename”, filename);
 }
 XtCreateManagedWidget(“bc_label”, 
 labelWidgetClass, outer, NULL, ZERO);

...

 void Feep()
 {
 XBell(CurDpy, 0);
 /*
  * ToolTalk のデモンストレーション用に、
  * 着信メッセージを受信して処理するために、
  * 以下の行を追加する
  */
 }


 void processToolTalkMessage()
		/* ToolTalk メッセージを処理する */
 {
 	int ttmark;	 		
  /* ToolTalk のマーク */
 	Tt_message incoming;						
		/* 着信メッセージ */

 	ttmark = tt_mark(); 				
		/* ToolTalk のマーク */

 	incoming = tt_message_receive();
		/* 着信メッセージを受信 */
 	/*
 	 * コールバックがメッセージを処理しなければならないので、
 	 * 返されたメッセージを取得してはならない
 	 */
 	if (incoming == 0) return;	
		/* 着信メッセージを戻す */

	if (tt_is_err(tt_ptr_error(incoming))) {
 		dieFromToolTalkError(“tt_message_receive”,
 				 tt_ptr_error(incoming));
 	}
 
 	/*
 	 * これは、認識していないメッセージである。
 	 * 開始の要求または通知があった場合に、異常終了する
 	 */

 	if (tt_message_class(incoming) == TT_REQUEST ||
 	 tt_message_status(incoming) ==
   TT_WRN_START_MESSAGE) {
 		tt_message_fail(incoming);
 	}
 	tt_message_destroy(incoming);
			/* メッセージの削除 */
 	tt_release(ttmark);	
 		/* 領域の解放 */
 }

 void dieFromToolTalkError(procname, errid)
 char *procname;
 Tt_status errid;
 	/* エラーが発生した場合は異常終了する */
 {
 	/*
 	 * 警告または TT_OK を無視してはならない
 	 */

  if (tt_is_err(errid)) {
 		fprintf(stderr,”%s returned ToolTalk 
   error: %s\n”,
 			procname, tt_status_message(errid));
 		exit(1);
 	}
 }


例 B–3 変更された commands.c ファイル

#if (!defined(lint) && !defined(SABER))
static char Xrcsid[] = “$XConsortium: 
commands.c,v 1.27 89/12/10
 				17:08:26 rws Exp $”;
#endif /* lint && SABER */

...

#ifdef USG
int rename (from, to)
 char *from, *to;
{
 (void) unlink (to);
 if (link (from, to) == 0) {
 unlink (from);
 return 0;
 } else {
 return -1;
 }
}
#endif

/*
 * ToolTalk のデモンストレーション用に、
 * 操作が成功したか失敗したかについて
 * Xfontsel がコールバックを送信するよう
 * 以下の行を追加する
 */
static Tt_callback_action FinishChangeFont(m,p)
/* ToolTalk メッセージコールバック */
 Tt_message m;
 	/* ToolTalk メッセージ */
 Tt_pattern p;	
 	/* ToolTalk パターン */
{
	static XFontStruct *fs;
			/* フォントの構造体 */
	int ttmark;	
			/* ToolTalk のマーク */
	
	ttmark = tt_mark();	
			/* ToolTalk のマーク */
 	/*
		 * 操作に失敗すると、ユーザーに通知する
		 */
 if (TT_FAILED==tt_message_state(m)) {
		XeditPrintf(“Font change failed\n”);
		tt_message_destroy(m);	 
			/* メッセージの削除 */
	} else if (TT_HANDLED==tt_message_state(m)) {
		XFontStruct *newfs;
		/* 新しいフォントを読み込む */
 	newfs = 
XLoadQueryFont(CurDpy,tt_message_arg_val(m,0));
 	/* 新しいフォントが正常の場合、古いフォントがあれば
		 * 読み込みを解除して、新しいフォントを使用する
 	 */
		if (newfs) {
			if (fs) {
 			XUnloadFont(CurDpy, fs->fid);
			}
			XtVaSetValues(textwindow, XtNfont, newfs, 0);
			fs = newfs;
		}
		tt_message_destroy(m);	
			/* メッセージの削除 */
 }
	tt_release(ttmark);	
 			/* マークの解放 */
		/*
		 * 送信側に操作の終了を通知するために、
 	 * コールバックを処理する
		 */
	return TT_CALLBACK_PROCESSED; 	
}

void
DoChangeFont()		
/* フォントの変更 */
{
	Tt_message m;
		/* ToolTalk のメッセージ */
	Tt_status ttrc;			
		/* ToolTalk の状態 */

	 /*
		 * 要求を作成
		 */
	m = tt_prequest_create(TT_SESSION, 
  “GetFontName”); 
		/*
		 * メッセージに引数を追加
 	 */
	tt_message_arg_add(m,TT_OUT,”string”,
   (char *)NULL);
		/*
		 * 変更の終了を通知するため、コールバックを追加する
 	 */
	tt_message_callback_add(m,FinishChangeFont);
 	/*
		 * メッセージの送信
		 */
	ttrc = tt_message_send(m);
		/*
		 * エラーが発生した場合は異常終了する
 	 */
	dieFromToolTalkError(“tt_message_send”,ttrc);
}



void DoSave()
{

Xfontsel ファイルへの ToolTalk コードの追加

Xfontsel ファイルに対する変更は、Xfontsel アプリケーションの変更で説明しています。


例 B–4 変更された Xfontsel.c ファイル

#ifndef lint
static char Xrcsid[] = “$XConsortium:
 xfontsel.c,v 1.16 89/12/12 14:10:48 rws
 Exp $”;
#endif

...

#include <X11/Xaw/Viewport.h>
#include <X11/Xmu/Atoms.h>

/*
 * ToolTalk のデモンストレーション用に、ToolTalk
 * のヘッダーファイルをインクルードするために  
 * 以下の行を追加する
 */
#include <desktop/tt_c.h>	
/* ToolTalk のヘッダーファイル */

#define MIN_APP_DEFAULTS_VERSION 1

...

void SetCurrentFont();
Boolean IsXLFDFontName();

/*
 * ToolTalk のデモンストレーション用に、
 * Xfontsel に ToolTalk メッセージの処理方法を
 * 通知するために、以下の行を追加する
 */
void dieFromToolTalkError(); 
 /* エラーが発生した場合は異常終了する */
void processToolTalkMessage();
 /* ToolTalk メッセージの処理 */
void ReplyToMessage();	
 	/* ToolTalk メッセージへの応答 */
Tt_message replymsg; 										

typedef void (*XtProc)();

...

int matchingFontCount;
static Boolean anyDisabled = False;
Widget ownButton;
/*
 * ToolTalk のデモンストレーション用に、
 * フォントを変更する適用ボタンを追加するために、
 * 次の行を追加する
 */
Widget applyButton;
		/* 適用ボタンを追加 */
Widget fieldBox;
/*
 * ToolTalk のデモンストレーション用に、
 * フォントを変更するコマンドボックスを追加するために、
 * 次の行を追加する
 */
Widget commandBox;		
		/* commandBox を拡大 */
Widget countLabel;

...

void main(argc, argv)
 unsigned int argc;
 char **argv;
{
 Widget topLevel, pane;

/*
 * ToolTalk のデモンストレーション用に、
 * 以下の行を追加する
 */
 int ttmark, ttfd;
		/* ToolTalk マークと ToolTalk ファイル記述子 */
 char *procid;	
 	/* プロセス識別子 */
 Tt_status ttrc;
 	/* ToolTalk の状態 */

 topLevel = XtInitialize( NULL, 
 “XFontSel”, options, XtNumber(options),
 		 &argc, argv );

...

 pane = XtCreateManagedWidget(“pane”
,panedWidgetClass,topLevel,NZ);
 {
/*
 * ToolTalk のデモンストレーション用に、  
 * コマンドボックスのウィジェットを拡大して、
 * Widget commandBox、fieldBox、
 * currentFontName、viewPort の行を
 * 以下のように変更する 
 */
	Widget
 /* commandBox, fieldBox, currentFontName,*/ viewPort;

	commandBox = XtCreateManagedWidget(“commandBox
 ”,formWidgetClass,pane,NZ);
 {

...

	 ownButton =
		XtCreateManagedWidget(“ownButton”
,toggleWidgetClass,commandBox,NZ);
/*
 * ToolTalk のデモンストレーション用に、
 * フォントを変更する適用ボタンを以下の行に追加する
 */
	 applyButton =		
	 XtVaCreateManagedWidget(“applyButton”,
 				commandWidgetClass,
					commandBox,
		 		XtNlabel, “apply”,
					XtNfromHoriz, ownButton,
 				XtNleft, XtChainLeft,
					XtNright, XtChainLeft,
 				0);

	 countLabel =
		XtCreateManagedWidget(“countLabel”
,labelWidgetClass,commandBox,NZ);

	 XtAddCallback(quitButton, XtNcallback, Quit,
 NULL);
  XtAddCallback(ownButton,XtNcallback,
  OwnSelection,(XtPointer)True);
/*
 * ToolTalk のデモンストレーション用に、
 * 適用ボタンが押されたことを Xedit に通知するために
 * 以下の行を追加する
 */
	 XtAddCallback(applyButton, 
  XtNcallback,ReplyToMessage, NULL);
	}

	fieldBox = XtCreateManagedWidget(“fieldBox”,
 boxWidgetClass, pane, NZ);

...

 {
 int f;
	for (f = 0; f < FIELD_COUNT; f++) 
currentFont.value_index[f] = -1;
 }

 /*
  * ToolTalk のデモンストレーション用に、
  * ToolTalk セッションをスタックの最初に
  * 作成して、デフォルトセッションとして設定するために、
  * 以下の行を追加する
  */
 ttmark = tt_mark();
 ttrc = tt_default_session_set( 
		/* 最上位ウィンドウを表示している */
 tt_X_session(
		 /* X サーバーの */
 DisplayString(
 		/* X セッションに */
 XtDisplay(top))));
 		/* デフォルトセッションを設定 */
	  /*
	   * デフォルトセッションがない場合は異常終了する
    */
 dieFromToolTalkError(“tt_default_session_set”
,ttrc);
 procid = tt_open();
	/*
	 * プロセス識別子がない場合は異常終了する
  */
 dieFromToolTalkError(“tt_open”
,tt_ptr_error(procid));
 ttfd = tt_fd();
	/*
	 * ToolTalk ファイル記述子がない場合は異常終了する
  */
 dieFromToolTalkError(“tt_fd”
,tt_int_error(ttfd));
 ttrc = tt_ptype_declare(“xfontsel”);
	/*
  * ptype が宣言されていない場合は異常終了する
	 */
 dieFromToolTalkError(“tt_ptype_declare”
,tt_int_error(ttfd));
 ttrc = tt_session_join(tt_default_session());
	/*
  * セッションを結合できない場合は異常終了する
	 */
 dieFromToolTalkError(“tt_session_join”,ttrc);
 /*
	  * 入力の追加
	 */
 XtAddInput(ttfd, (XtPointer)XtInputReadMask,
 processToolTalkMessage, 0);

 XtAppMainLoop(appCtx);							

 tt_close();	 				
			/* ToolTalk セッションを終了する */
 tt_release(ttmark);									
			/* 領域の解放 */
}

...
 	Boolean field_bits[FIELD_COUNT];
		int max_field;
 	if (*fontName == DELIM) field++;
/*
 * ToolTalk のデモンストレーション用に、
 * BSD の代わりに標準ルーチンを使用して
 * bzero 以下のように読み込むために
 * bzero( field_bits, sizeof(field_bits) );
 * の行を変更する
 */
		memset( field_bits, 0, sizeof(field_bits) );
		if (Matches(pattern, fontName++, field_bits, 
   &max_field)) {

...

	 XtDisownSelection(w, XA_PRIMARY, time);
	XtSetSensitive(currentFontName, False);
 }

/*
 * ToolTalk のデモンストレーション用に、
 * 以下の行を追加する
 */
}

void dieFromToolTalkError(procname, errid)
/* エラーが発生した場合は異常終了する */
 char *procname;
 	/* プロセス名 */
 Tt_status errid;
 	/* エラー識別子 */
{
	/*
	 * 警告または TT_OK を無視してはならない
	 */

	if (tt_is_err(errid)) {
		fprintf(stderr,”%s returned ToolTalk error:
 %s\n”,
			procname, tt_status_message(errid));
 	exit(1);
	}
}

void processToolTalkMessage()
	/* プロセスメッセージ */
{
	int ttmark;	
		/* ToolTalk マーク */
	Tt_message incoming;				
			/* 着信メッセージ */

	ttmark = tt_mark();

	incoming = tt_message_receive(); 
	/* メッセージを受信 */
 /*
  * ファイル記述子が使用可能であっても、
	 * 実際には ToolTalk のメッセージがない場合も
  * あり得る
	 */
	if (incoming == 0) return;

	if (tt_is_err(tt_ptr_error(incoming))) {
		dieFromToolTalkError(“tt_message_receive”,
 			 tt_ptr_error(incoming));
	}
	
 if (0==strcmp(tt_message_op(incoming),”
  GetFontName”)) {
		/*
		 * これは、予想していたメッセージである。
 	 * すでに使用中の場合はそのメッセージを拒否する。
		 * そうでない場合は、適用ボタンを有効にする
 	 */
		if (replymsg) {
			tt_message_reject(incoming);
 		tt_message_destroy(incoming);
			tt_release(ttmark);
 		return;
		}
		XtVaSetValues(applyButton, XtNsensitive, 
   TRUE, 0);
		replymsg = incoming;
		tt_release(ttmark);
 	return;
	}

	/*
  * これは認識していないメッセージである。
	 * 開始の要求または通知があった場合に異常終了する
  */

	if (tt_message_class(incoming) == TT_REQUEST ||
	 tt_message_status(incoming) == 
  TT_WRN_START_MESSAGE) {
		tt_message_fail(incoming);
	}
	tt_message_destroy(incoming);
	tt_release(ttmark);
}

/*
 * 適用ボタンが押されると呼び出される。
 * 未応答のメッセージに応答して、適用ボタンをオフにする
 */

/* 使用済み引数 */
void ReplyToMessage(w, msg, wdata)
 Widget w;
 caddr_t msg;
 caddr_t wdata;
{

	tt_message_arg_val_set(replymsg, 0, 
currentFontNameString);
	tt_message_reply(replymsg);
	tt_message_destroy(replymsg);
	replymsg = 0;
	XtVaSetValues(applyButton, XtNsensitive, FALSE,
 0);
}