解剖しているプログラムはXのアプリケーションですから、当然クライアント/サーバモデルの 上で動作しているのです。
最近、どこへ行っても、「クライアント/サーバ」という言葉をやたらに聞きます。そういう話 を聞いていて、一番感じるのは、言っている本人がその意味を知っているのかなあということです。 流行語だから、おまじないのように使って、知ったかぶりをするための道具にしか思えないことが 多いのです。
コンピュータショーなどに行くと、きっといっぱい「クライアント/サーバ」という「おまじな い」を聞くでしょう。「うちの製品は、クライアント/サーバモデルに基づいて…」というような 説明を始めるでしょうから、「クライアント/サーバとはどういうことですか?」と聞いてみましょ う。ちゃんと説明できる説明員などまずいないでしょう。きっと、会場に無理矢理来させられた技 術者を連れてきて説明をさせると思います。たぶん、教科書どおりの説明はしてくれるでしょう。 そこで、「クライアント/サーバだったら、どういうメリットがあるのですか?何ができるように なったのですか?」と質問してみましょう。この辺までしっかり答えてくれれば素晴らしい。
そういえば、以前、DTPのショーに行ったとき、ちょっと質問したら、「知り過ぎている。あ なたはどこかの大学の方で、冷やかしにいらしているのですか?」と言われたことがありました。 「恐いオネーサマ」もいるので、質問する前に、相手を見てからにするのも忘れないように。
もっと分かりやすく言えば、「一人でやっていた仕事を二人でやるのが、クライアント(王様) /サーバ(召使)モデル」です。多くの場合、一人でやった方が便利ですよね。召使に何かやらせ るには、命令しなければなりません。というより、いろいろな雑用は、王様がすることが禁じられ ていて、いちいち召使にやらせなければいけない世界なのです。ちょっと町をブラブラしようと思っ ても召使がついてくるし、トイレも一人で行ってはいけないような世界なのです。これが「王様/ 召使モデル」なのです。
こういう世界ですから、2者の間で、いっぱい取り決めがあります。「クライアント/サーバモ デル」でなかった時代には単純だったのに、時代が変わり、「クライアント」と「サーバ」の間で、 「通信」により命令を受け、処理をするようになっりました。この通信がすごい「くせ者」で、X のアプリケーション開発者たちは、よく戸惑っています。
何でも通信すると、通信量が非常に増大して、本来の処理より、無駄な通信と、無駄な通信に基 づいた処理がどんどん増大して、コンピュータは無駄な処理のためにあえぎ、しばしばキーボード やマウスが反応しなくなります。
前置きがとても長くなりましたが、今回のプログラムにも、その片鱗が見えています。それは、 各関数の先頭で、
event_is_ascii( event )
event_is_down( event )
event_action( event )
のようなイベントの種類をチェックする関数やマクロがズラズラと並んでいることです。Xウィン
ドでいうイベントとは、「王様/召使いモデル」での、召使が王様に申し上げる「言葉」です。上
の3種の関数やマクロは、この言葉の内容(種別)をチェックしているわけです。不要な発言か、
欲しかった発言かをチェックしているのです。
ここで問題があります。召使が、どうでもよいことをぐちゃぐちゃしゃべったら、うるさくて困 ると思いませんか。必要な時だけしゃべって欲しいものです。上のイベントチェックの並びは、ム ダなものがいっぱい含まれている中から、必要なものを判別している処理です。
イベントは、王様から召使いに対して、最初に、「伝えるべきことのメモ」を渡すことになって います。そのための関数呼びだしが、
xv_set( mac_up_canvas,
WIN_EVENT_PROC, mac_up_event,
WIN_CONSUME_EVENTS,
LOC_WINENTER,
LOC_WINEXIT,
LOC_MOVE,
LOC_DRAG,
KBD_DONE,
KBD_USE,
WIN_MOUSE_BUTTONS,
NULL,
NULL );
です。WIN_CONSUME_EVENTSに続く行が受けつける(王様に知らせる)イベントの種類です。マウス
イベントしか利用しないのだから、WIN_MOUSE_BUTTONS以外の並びは存在するだけ「悪」で、
xv_set( mac_up_canvas,
WIN_EVENT_PROC, mac_up_event,
WIN_CONSUME_EVENTS,
WIN_MOUSE_BUTTONS,
NULL,
NULL );
のように直すべきです。すると、event_is_asciiが不要になります。
さて、元のプログラムはXViewで書かれていたのですが、「XViewを捨てMotifへ移行という時代 の流れ」に沿い、Motifへ移植してしまいました。そういうことで、改定最終案はMotif版をお見せ します(リスト11−4)。
| リスト11−4 修正版(その3)Motifでの実現 |
1 void mac_move_event( w, direction, call_data )
2 Widget w;
3 char direction; /* 'u', 'd', 'l', 'r' */
4 caddr_t call_data;
5 {
6 int mac_step_x, mac_step_y;
7 RECT rectdisp;
8 RECT rectbase;
9 Window win_disp;
10
11 mac_step_x = mac_width / mac_mag;
12 mac_step_y = mac_height / mac_mag;
13
14 switch( direction ) {
15 case 'u': /* up */
16 mac_y -= mac_step_y/2;
17 break;
18 case 'd': /* down */
19 mac_y += mac_step_y/2;
20 break;
21 case 'l': /* left */
22 mac_x -= mac_step_x/2;
23 break;
24 case 'r': /* right */
25 mac_x += mac_step_x/2;
26 break;
27 }
28
29 if ( mac_x > xdot - mac_step_x )
30 mac_x = xdot - mac_step_x;
31 if ( mac_x < 0 )
32 mac_x = 0;
33 if ( mac_y > ydot - mac_step_y )
34 mac_y = ydot - mac_step_y;
35 if ( mac_y < 0 )
36 mac_y = 0;
37
38 mac_posx = mac_x + mac_step_x/2;
39 mac_posy = mac_y + mac_step_y/2;
40 rectdisp.x = 0;
41 rectdisp.y = 0;
42 rectdisp.size_x = mac_width;
43 rectdisp.size_y = mac_height;
44 rectbase.x = mac_x;
45 rectbase.y = mac_y;
46 win_disp = my_canvas_paint_winid( mac_canvas );
47 mac_cur = OFF;
48 disp_data( &rectdisp, &rectbase, mac_mag, &mac_point,
49 mac_image_ad, mac_image->bytes_per_line, ON );
50 XPutImage( motif_display, win_disp, mac_paint_gc, mac_image,
51 rectdisp.x, rectdisp.y,
52 rectdisp.x, rectdisp.y,
53 rectdisp.size_x, rectdisp.size_y );
54 }
|
リスト11−2とかなり似ているでしょう。しかし、いままでは上下左右の4つの関数がありま したが、完全に1つの関数になっています。共通化された関数が直接呼ばれる便利な状況になって います。さらに重要なことは、イベントに関する条件判定が完全になくなったことです。どの向き かは引数で与えられています。 さらに、使用していない変数 x, y, point1, point2も削除しました。目障りだった余分なキャ ストも取り去りました。かなり「すっきり」したでしょう。
もう1つは、データベースのようなもので、複数のコンピュータ上で動いている多数のプログラ ムから自由に呼ばれるが、必ずデータは一元管理しなければならないものです。かな漢字変換サー バもこの類です。
Xウィンドの表示は、Xサーバが担当しています。したがって、Xサーバが動いているところな らどこにでも表示できます。この機能があることで、ウィンド上のアプリケーション開発がずいぶ ん助かっています。デバッガとアプリケーションの表示をしているディスプレイを別にできなかっ たら、ウィンドベースのソフトウェアのデバッグはまず不可能でしょう。こういうとき、X端末が あると、すごーく便利ですよ。