リスト6−5 ビット処理のマクロ定義 |
1 /********************************************************************************/ 2 /* ATTRIBUTES MODIFIED FLAGS */ 3 /********************************************************************************/ 4 5 #define MODIFIED_FLAGS_LEN 4 6 7 /********************** common window modified flags *************************/ 8 9 #define WIN_FONT_MODIFIED (0x00000001) 10 #define WIN_CLIENT_DATA_MODIFIED (0x00000002) 11 #define WIN_BELOW_MODIFIED (0x00000004) 12 #define WIN_X_MODIFIED (0x00000008) 13 #define WIN_Y_MODIFIED (0x00000010) 14 #define WIN_VERTICAL_SCROLLBAR_MODIFIED (0x00000020) 15 #define WIN_LEFT_MARGIN_MODIFIED (0x00000040) 16 #define WIN_TOP_MARGIN_MODIFIED (0x00000080) 17 #define WIN_CURSOR_MODIFIED (0x00000100) 18 19 #define WIN_MODIFIED(_bitmask,_flags) _flags[0] |= _bitmask 20 21 #define WIN_FONT_modified(_flags) \ 22 WIN_MODIFIED(WIN_FONT_MODIFIED,_flags) 23 #define WIN_CLIENT_DATA_modified(_flags) \ 24 WIN_MODIFIED(WIN_CLIENT_DATA_MODIFIED,_flags) 25 #define WIN_BELOW_modified(_flags) \ 26 WIN_MODIFIED(WIN_BELOW_MODIFIED,_flags) 27 #define WIN_X_modified(_flags) \ 28 WIN_MODIFIED(WIN_X_MODIFIED,_flags) 29 #define WIN_Y_modified(_flags) \ 30 WIN_MODIFIED(WIN_Y_MODIFIED,_flags) 31 #define WIN_VERTICAL_SCROLLBAR_modified(_flags) \ 32 WIN_MODIFIED(WIN_VERTICAL_SCROLLBAR_MODIFIED,_flags) 33 #define WIN_LEFT_MARGIN_modified(_flags) \ 34 WIN_MODIFIED(WIN_LEFT_MARGIN_MODIFIED,_flags) 35 #define WIN_TOP_MARGIN_modified(_flags) \ 36 WIN_MODIFIED(WIN_TOP_MARGIN_MODIFIED,_flags) 37 #define WIN_CURSOR_modified(_flags) \ 38 WIN_MODIFIED(WIN_CURSOR_MODIFIED,_flags) 39 40 #define isWIN_MODIFIED(_bitmask,_flags) ((_flags[0] & (_bitmask))==(_bitmask)) 41 42 #define isWIN_FONT_modified(_flags) \ 43 isWIN_MODIFIED(WIN_FONT_MODIFIED,_flags) 44 #define isWIN_CLIENT_DATA_modified(_flags) \ 45 isWIN_MODIFIED(WIN_CLIENT_DATA_MODIFIED,_flags) 46 #define isWIN_BELOW_modified(_flags) \ 47 isWIN_MODIFIED(WIN_BELOW_MODIFIED,_flags) 48 #define isWIN_X_modified(_flags) \ 49 isWIN_MODIFIED(WIN_X_MODIFIED,_flags) 50 #define isWIN_Y_modified(_flags) \ 51 isWIN_MODIFIED(WIN_Y_MODIFIED,_flags) 52 #define isWIN_VERTICAL_SCROLLBAR_modified(_flags) \ 53 isWIN_MODIFIED(WIN_VERTICAL_SCROLLBAR_MODIFIED,_flags) 54 #define isWIN_LEFT_MARGIN_modified(_flags) \ 55 isWIN_MODIFIED(WIN_LEFT_MARGIN_MODIFIED,_flags) 56 #define isWIN_TOP_MARGIN_modified(_flags) \ 57 isWIN_MODIFIED(WIN_TOP_MARGIN_MODIFIED,_flags) 58 #define isWIN_CURSOR_modified(_flags) \ 59 isWIN_MODIFIED(WIN_CURSOR_MODIFIED,_flags) 60 61 /************************* FRAME modified flags *************************/ 62 63 /************************* まだまだ続きます *************************/ |
リスト6−6 swin_attr_set(マクロ利用版) | |
1 /** 2 ** set attribute 3 **/ 4 void 5 win_attr_set( win, ap, modified_flags ) 6 myWindow *win; 7 va_list ap; 8 unsigned long *modified_flags; 9 { 10 myFrame *frame; 11 myPanel *panel; 12 myCanvas *canvas; 13 int attr; 14 va_short itemp; 15 short *pointer, *oldpointer; 16 myPanel_Item_Choice *point; 17 int size, len; 18 char *ctemp; 19 myWindow *owner = win->parent; 20 int type = win->win_type; 21 22 panel = (myPanel*)win; 23 canvas = (myCanvas*)win; 24 frame = (myFrame*)win; 25 26 while ( (attr = va_arg( ap, int )) != 0 ) { 27 28 switch ( attr ) { 29 30 /***************** window attribute *****************/ 31 case WIN_FONT: 32 win->win_font = va_arg(ap, myPixfont *); 33 WIN_FONT_modified(modified_flags); 34 break; 35 case WIN_CLIENT_DATA: 36 win->win_client_data = va_arg( ap, caddr_t ); 37 WIN_CLIENT_DATA_modified(modified_flags); 38 break; 39 case WIN_BELOW: 40 win->win_below = va_arg( ap, myWindow* ); 41 WIN_BELOW_modified(modified_flags); 42 break; 43 case WIN_X: 44 win->win_x = va_arg( ap, int ); 45 WIN_X_modified(modified_flags); 46 break; 47 case WIN_Y: 48 win->win_y = va_arg( ap, int ); 49 WIN_Y_modified(modified_flags); 50 break; 51 case WIN_VERTICAL_SCROLLBAR: 52 win->win_vertical_scrollbar = va_arg( ap, Scrollbar ); 53 WIN_VERTICAL_SCROLLBAR_modified(modified_flags); 54 break; 55 case WIN_LEFT_MARGIN: 56 win->win_left_margin = va_arg( ap, int ); 57 WIN_LEFT_MARGIN_modified(modified_flags); 58 break; 59 case WIN_TOP_MARGIN: 60 win->win_top_margin = va_arg( ap, int ); 61 WIN_TOP_MARGIN_modified(modified_flags); 62 break; 63 case WIN_CURSOR: 64 win->win_cursor = va_arg( ap, caddr_t ); 65 WIN_CURSOR_modified(modified_flags); 66 break; 67 68 /****** まだまだ case は続きます ******/ 69 70 default: 71 fprintf(stderr,"Not supported attr %d in win_attr_set/window.c",attr); 72 va_arg( ap, int ); 73 break; 74 } 75 } 76 } |
関数win_attr_setの可変引数apに適当な定数があると、その定数に従って、その次に整数や文字 列など決まったものが来ます。(printfの引数のように、引数の個数が可変な関数の作り方は、こ こでは特に説明しませんが、絶対にマスターすべきです。)この、可変引数から、指定の型の引数 を参照するにはva_argマクロを使います。そして、その値を適当な変数内部に保管し、WIN_FONT_ modifiedのようなマクロで定数WIN_FONTを記憶する仕掛になっています。つまり、
window_create( FRAME, WIN_WIDTH, 500, WIN_HEIGHT, 400, FRAME_LABEL, "browser", 0 );のとき、定数WIN_WIDTH,WIN_HEIGHT,FRAME_LABELがあり、それらの値は500,400,"browser"であっ たことを記憶します。そして後で、window_createでどんな値が指定されていたかを調べながら適 当な処理をします。
ここで言う定数(ウィンド属性)は、50個程度もあり、個数が多いため、各定数を1ビットに割 当てています。この定数を示す名前も実はマクロですが、そのマクロ名に_MODIFIEDを付加したも のでビット位置を示し、_modifiedを付加したもので対応ビットをオンにし、さらに先頭にisを付 加したもので、対応ビットのオンオフを取り出すように細工をしています。オンオフを入れる配列 が第3引数のmodified_flagsで、配列のサイズはヘッダーファイル中でMODIFIED_FLAGS_LENで4に なっています。
リスト6−5は、見るからに息苦しいコーディングと思いませんか。ビットを指定するのに、 (0x00000001)のようなビットマスクを延々と書かれるのも嫌です。 属性は4種に大別し、それぞれを分けて書いています。今のところ、とりあえずサポートの必要 あるものに限っているので、どれも32個を越えてはいませんが、もし越えてしまうと変更が必要で す。
ビット単位でオンオフを記憶させたい時には、ビットフィールドを使うのが常識です。構造体の 1要素のビット長を明示することで、簡単に作れます。リスト6−7に、win_attributes型を宣言 しました。これで、面倒で邪魔なマクロを全部きれいに消し去ることができます。何も気にせず、 自然体で書くことができます。
利用する方を書き換えたのがリスト6−8です。マクロでないと大変だと思いこみ、いっぱいマ クロを用意していますが、全然必要ないことが分かるでしょう。
リスト6−7 構造体 | |
1 /********************************************************************************/ 2 /* ATTRIBUTES MODIFIED FLAGS */ 3 /********************************************************************************/ 4 5 typedef struct { 6 unsigned int win_font : 1; 7 unsigned int win_client_data : 1; 8 unsigned int win_below : 1; 9 unsigned int win_x : 1; 10 unsigned int win_y : 1; 11 unsigned int win_vertical_scrollbar : 1; 12 unsigned int win_left_margin : 1; 13 unsigned int win_top_margin : 1; 14 unsigned int win_cursor : 1; 15 16 /*********** まだまだ続きます *********/ 17 18 } win_attributes; |
リスト6−8 swin_attr_set(構造体利用版) | |
1 /********************************************************************************/ 2 /* set attribute */ 3 /********************************************************************************/ 4 void 5 win_attr_set( win, ap, modified_flags ) 6 myWindow *win; 7 va_list ap; 8 win_attributes *modified_flags; 9 { 10 myFrame *frame; 11 myPanel *panel; 12 myCanvas *canvas; 13 int attr; 14 va_short itemp; 15 short *pointer, *oldpointer; 16 myPanel_Item_Choice *point; 17 int size, len; 18 char *ctemp; 19 myWindow *owner = win->parent; 20 int type = win->win_type; 21 22 panel = (myPanel*)win; 23 canvas = (myCanvas*)win; 24 frame = (myFrame*)win; 25 26 while ( (attr = va_arg( ap, int )) != 0 ) { 27 28 switch ( attr ) { 29 30 /***************** window attribute *****************/ 31 case WIN_FONT: 32 win->win_font = va_arg(ap, myPixfont *); 33 modified_flags->win_font = 1; 34 break; 35 case WIN_CLIENT_DATA: 36 win->win_client_data = va_arg( ap, caddr_t ); 37 modified_flags->win_client_data = 1; 38 break; 39 case WIN_BELOW: 40 win->win_below = va_arg( ap, myWindow* ); 41 modified_flags->win_below = 1; 42 break; 43 case WIN_X: 44 win->win_x = va_arg( ap, int ); 45 modified_flags->win_x = 1; 46 break; 47 case WIN_Y: 48 win->win_y = va_arg( ap, int ); 49 modified_flags->win_y = 1; 50 break; 51 case WIN_VERTICAL_SCROLLBAR: 52 win->win_vertical_scrollbar = va_arg( ap, Scrollbar ); 53 modified_flags->wom_vertical_scrollbar = 1; 54 break; 55 case WIN_LEFT_MARGIN: 56 win->win_left_margin = va_arg( ap, int ); 57 modified_flags->win_left_margin = 1; 58 break; 59 case WIN_TOP_MARGIN: 60 win->win_top_margin = va_arg( ap, int ); 61 modified_flags->win_top_margin = 1; 62 break; 63 case WIN_CURSOR: 64 win->win_cursor = va_arg( ap, caddr_t ); 65 modified_flags->win_cursor = 1; 66 break; 67 68 /****** まだまだ case は続きます ******/ 69 70 default: 71 fprintf(stderr,"Not supported attr %d in win_attr_set/window.c",attr); 72 va_arg( ap, int ); 73 break; 74 } 75 } 76 } |
ずいぶん面倒なマクロを定義し、ごたごたと書いていたことが、いかにムダで、不自然だったか 理解できたでしょうか。