この節では、ToolTalk コードがどのように Xedit および Xfontsel アプリケーションに追加されたかを説明します。
省略記号 (. . .) は、コードがスキップされていることを表します。コード例は、挿入された ToolTalk コード行の前後数行だけを示します。
ファイルに追加する必要がある実際の ToolTalk コードは、ボールド体で示します。次にその例を示します。
#include <desktop/tt_c.h> /* ToolTalk のヘッダー */ |
Xedit ファイルに対する変更は、Xedit アプリケーションの変更で説明します。
/*
* 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();
/* フォントを変更する */
#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);
}
}
#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 ファイルに対する変更は、Xfontsel アプリケーションの変更で説明しています。
#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);
}