『Cプログラミング診断室』目次次(第13章 計算は自分で Xウィンドウの日本語化)

第13章 計算は自分で

廃棄処分


■廃棄処分■

ところで、このソフトに対する当社の仕事は、XViewで書かれた(うっかりXViewで書いてしまっ た)ソフトを、Motifに移してしまうことでした。そうそう、うちではSunViewをMotifへ移すとか、 XViewをMotifへ移すとかという仕事も多いのです。こういうことをやっていると複数のウィンドウ システムについて詳しくなってしまいます。最初は、こんなところまで同じように動作させるなん て不可能ではといっていたようなことでも、まあ慣れてくれば移植してしまうのは可能なんですね。 ただし、SunView,XView,Motifという3種のウィンドウシステムの用語をごちゃまぜで話せるよう になります。いや、頭が混乱して、3言語ゴチャゴチャでしか話せなくなります。同様の概念が、 ウィンドウシステムごとに用語が違ったり、働きが微妙に違ったりで、困ったものです。

最終目標は、このプログラムに手を入れることではなく、できるだけ早期にMotif上に移植する ことです。画面回り以外は、特別に何も書き換えなくても動作します。ある程度の細工は必要です が、まあソースに手を加える必要はまずありません。

しかし、ウィンドウ回りはそのままでは絶対に動かないので、大幅な変更が必要です。今回の移 植は、Xウィンドウという点でベースは同じだったので、本当はそれほど難しい仕事ではなかった のです。難しかったのは、プログラムのDirtyさだったのです。

全てのウィンドウがこんな感じで書かれていたので、移植に対する最初の問題は、この訳の分か らない膨大なリストをどう処理するかでした。

答は簡単なのです。画面の生成部分は「廃棄処分」にしました。残ったのは、関数名と大域変数 くらいでした。ちゃんとした仕様書がなかったので、各関数の機能だけを理解し、ウィンドウのデ ザインはMotifの豊富なカスタマイズ機能をフルに発揮し、Cプログラムをゴチャゴチャ書くので はなく、可能な限りXのリソース機能を使いました。要するに、Xが持っているデータベース機能 を存分に利用し、可能な限りさぼりました。

困ったことは、元のプログラムが、何事もさぼらず、訳の分からぬことを書いているので、それ を外す作業、そして正しく外せたかの確認作業が中心でした。

■Motif版■

この関数を、当社の新人にMotif化させたプログラムがリスト13−2です。0xFFFFを並べた行 もなければ、面倒な座標計算も一切していません。そのままに近い形で置き換えているだけですが、 長さは約1/4に減っています。

リスト13−2 修正版(Motif版)

     1	void    rgb_info_init( )
     2	{
     3	        int             i, line = 0;
     4	        Dimension       width, height;
     5	        char            name[80];
     6	        Arg             args[10];
     7	        Widget          basepanel, subpanel, board, rowcol;
     8	        Widget          canvas, frame, draw;
     9	        static  ButtonData      data[] = {
    10	                { NULL, rgb_info_before_plane, },
    11	                { NULL, rgb_info_next_plane, },
    12	                { &rgb_info_quit_button, (XtCallbackProc)rgb_info_quit, },
    13	        };
    14	
    15	        rgb_info_frame = CreateShellDefaultDecorations( "rgb_info", APP_CLASS_NAME );
    16	        basepanel = MakeRowColumn( "basepanel", rgb_info_frame );
    17	
    18	        board = MakeBulletinBoard( "board", basepanel );
    19	        image_set = MakeDrawingArea( "image", board );
    20	
    21	        subpanel = MakeRowColumn( "subpanel", basepanel );
    22	
    23	        sprintf( name, "line%d", ++line );
    24	        rowcol = MakeRowColumn( name, subpanel );
    25	
    26	        MakeLabelGadget( "label", rowcol );
    27	        rgb_info_disp1 = MakeLabel( "label1", rowcol );
    28	        rgb_info_disp2 = MakeLabel( "label2", rowcol );
    29	
    30	        sprintf( name, "line%d", ++line );
    31	        rowcol = MakeRowColumn( name, subpanel );
    32	
    33	        MakeLabelGadget( "label", rowcol );
    34	        for ( i = 0; i < XtNumber( rgb_info_disp3 ); ++i ) {
    35	                sprintf( name, "label%d", i + 1 );
    36	                rgb_info_disp3[i] = MakeLabel( name, rowcol );
    37	        }
    38	
    39	        sprintf( name, "line%d", ++line );
    40	        rowcol = MakeRowColumn( name, subpanel );
    41	
    42	        MakeLabelGadget( "label", rowcol );
    43	        for ( i = 0; i < XtNumber( rgb_info_disp3 ); ++i ) {
    44	                sprintf( name, "label%d", i + 1 );
    45	                rgb_info_disp4[i] = MakeLabel( name, rowcol );
    46	        }
    47	
    48	        sprintf( name, "line%d", ++line );
    49	        rowcol = MakeRowColumn( name, subpanel );
    50	
    51	        rgb_info_plane = MakeLabel( "label1", rowcol );
    52	        MakeLabel( "label2", rowcol );
    53	        rgb_info_num = MakeLabel( "label3", rowcol );
    54	
    55	        sprintf( name, "line%d", ++line );
    56	        rowcol = MakeRowColumn( name, subpanel );
    57	
    58	        canvas = XtCreateManagedWidget( "canvas", xmFormWidgetClass,       rowcol, NULL, 0 );
    59	        frame  = XtCreateManagedWidget( "frame",  xmFrameWidgetClass,      canvas, NULL, 0 );
    60	        draw   = XtCreateManagedWidget( "draw",   xmDrawingAreaWidgetClass, frame, NULL, 0 );
    61	        rgb_info_scroll = MakeScrollBar( "scroll", rowcol );
    62	
    63	        rgb_info_canvas = alloc_canvas( canvas, frame, draw, rgb_info_scroll, NULL );
    64	
    65	        XtAddCallback( rgb_info_scroll, XmNvalueChangedCallback,  scrolled, NULL );
    66	        XtAddCallback( rgb_info_scroll, XmNincrementCallback,     scrolled, NULL );
    67	        XtAddCallback( rgb_info_scroll, XmNdecrementCallback,     scrolled, NULL );
    68	        XtAddCallback( rgb_info_scroll, XmNpageIncrementCallback, scrolled, NULL );
    69	        XtAddCallback( rgb_info_scroll, XmNpageDecrementCallback, scrolled, NULL );
    70	        XtAddCallback( rgb_info_scroll, XmNtoTopCallback,         scrolled, NULL );
    71	        XtAddCallback( rgb_info_scroll, XmNtoBottomCallback,      scrolled, NULL );
    72	        XtAddCallback( rgb_info_scroll, XmNdragCallback,          scrolled, NULL );
    73	
    74	        MakeFormPushButton( "form", subpanel, data, XtNumber( data ) );
    75	
    76	        XtRealizeWidget( rgb_info_frame );
    77	
    78	        rgb_info_color  = pixelcolortable;
    79	        i = 0;
    80	        XtSetArg( args[i], XmNwidth, &width ); ++i;
    81	        XtSetArg( args[i], XmNheight, &height ); ++i;
    82	        XtGetValues( my_canvas_paint_window( rgb_info_canvas ), args, i );
    83	        rgb_info_pixmap = XCreatePixmap( motif_display, my_canvas_paint_winid( rgb_info_canvas ),
    84	                                         width, height, DefaultDepth( motif_display, 0 ) );
    85	        rgb_info_xwin = (Xv_Window)my_canvas_paint_window( rgb_info_canvas );
    86	        rgb_info_gc = XCreateGC( motif_display, my_canvas_paint_winid( rgb_info_canvas ), 0, 0 );
    87	        XSetFont( motif_display, rgb_info_gc, XLoadFont( motif_display, "fixed" ) );
    88	        XSetForeground( motif_display, rgb_info_gc, 0xffffffff );
    89	        XSetBackground( motif_display, rgb_info_gc, 0 );
    90	        backing_store_canvas( rgb_info_canvas );
    91	
    92	        make_colorbox( image_set );
    93	}

意味不明の計算と、マクロになっていた多数の文字列に相当する部分は、リソースファイルとし て実現しました。このファイルは、

  rgb_info*.line1.orientation:          HORIZONTAL
  rgb_info*.line1.label.labelString:    色
のような行がいっぱい並んだテキストファイルです。":"の左側で「どのデータ」かを指定し、右 側に「その値」を書きます。1行目のように、予約語や数値を書いている行もあります。2行目の ように左側がlabelStringのところは、右側には文字列を指定します。この文字列は、ウィンドウ 上の指定位置にそのまま表示されます。漢字で書けば、そのまま漢字で表示されます。

このファイルはテキストファイルなので、エディタで簡単に修正できます。line1なんていう名 前(正確にはウィジェットインスタンス名)を使わず、もっと意味のあるものにしたかったのです が、移植なので、プログラムの意味を理解して作業をしている訳ではなし、とりあえず識別できる ようにと、こんな安直な名前にしておきました。まあ、今後の開発をする人が正式の名前にしてく れるといいのですが、さてどうなるのでしょう。

関数化できる部分をもっと関数化するとか、いっそのこと全面的に書き換えてしまうとかすれば もっとすっきりします。でも、このソフト、表示以外の部分にもいっぱい病根があったので、ユー ザインターフェイスだけ良くしてもアンバランスになってしまうので、このレベルの書き換えで止 めておきました。何事も「バランス」が重要ですからね。

■英語化■

このソフトを載せた巨大なシステムは、最初は日本語だけをサポートしていました。文字入力は あまりないソフトですが、実際に操作する作業者はコンピュータとはほとんど縁のない、別の分野 の職人というか、オペレーターです。ですから、日本で売るときは日本語で、海外で売るときは英 語でと切り替える必要が出てきたのです。

リスト中の、属性名が STRING(S) に続く属性値として文字列が一杯あるソフトでしたので、複 数言語に対応するとなると、オリジナルのままを踏襲すると、日本語版は日本語のヘッダーファイ ルを、英語版は英語のヘッダーファイルをインクルードした状態でコンパイルし、それぞれ別のも のとして実行形式を作らねばならなかったのです。

ところが、Motifへの移植に際して、きちんとサボったため、ソースについての詳しい知識がまっ たく無くても簡単に変更できるように変身したのです。

ウィンドウ上に表示される日本語文字列に対応するリソースファイルの漢字部分

  rgb_info*.line1.label.labelString: 色
  rgb_info*.line1.label.labelString: Color   
のように書き換えてしまえば、海外でも使えるソフトになってしまいます。じつに簡単なんです。 文字列長が変化しても、ある程度はMotifが自動調整してくれます。

このファイルについてのドキュメントは書きましたが、英語化の説明は全然しなかったのです。 しかし、お客さま自身でちょこちょこっと英語に書き換えて英語化のテストをしていました。

これも、「廃棄処分」と「さぼり」の効果ですが、お客の側で簡単に英語化できるようなものに してしまったのは「経営上の誤りか」と悩んでおります。


Copyright1996 Hirofumi Fujiwara. No reproduction or republication without written permission
『Cプログラミング診断室』目次次(第13章 計算は自分で Xウィンドウの日本語化)