Listing 6

001  #include <stdio.h>
002  #include <stdlib.h>
003  #include <stdarg.h>
004  #include "utility.h"
005  #include "obj.h"
006
007  /* methods for graphical_object, circle, double_circle, square */
008  #define INIT 0
009  #define DRAW 1
010  #define MOVE 2
011
012  /********************************************************/
013  /* CLASS GRAPHICAL OBJECT */
014
015  struct graph_obj_s {
016      int y;
017      int x;
018  };
019
020  typedef struct graph_obj_s GRAPH_OBJ_T;
021  #define GRAPH_OBJ_SIZE sizeof(GRAPH_OBJ_T)
022  #define GRAPH_OBJ_OFFSET 0
023
024  /* graph_obj_init(object, y_position, x_position); */
025  void graph_obj_init(OBJECT *obj, va_list arg_ptr)
026  {
027      GRAPH_OBJ_T *g;
028      g = (GRAPH_OBJ_T *)((unsigned char *)obj->data +
029        GRAPH_OBJ_OFFSET);
030      g->y = va_arg(arg_ptr, int);
031      g->x = va_arg(arg_ptr, int);
032  }
033
034  /* graph_obj_move(object, distance_y, distance_x); */
035  void graph_obj_move(OBJECT *obj, va_list arg_ptr)
036  {
037      GRAPH_OBJ_T *g;
038      g = (GRAPH_OBJ_T *)((unsigned char *)obj->data +
039        GRAPH_OBJ_OFFSET);
040      message(obj, DRAW, g_black);
041      g->y += va_arg(arg_ptr, int);
042      g->x += va_arg(arg_ptr, int);
043      message(obj, DRAW, g_white);
044  }
045
046  /********************************************************/
047  /* CLASS CIRCLE */
048
049  struct circle_s {
050      int radius;
051  };
052
053  typedef struct circle_s CIRCLE_T;
054  #define CIRCLE_SIZE sizeof(CIRCLE_T) + GRAPH_OBJ_SIZE
055  #define CIRCLE_OFFSET sizeof(GRAPH_OBJ_T)
056
057  /* circle_init(object, y_position, x_position, radius); */
058  void circle_init(OBJECT *obj, va_list arg_ptr)
059  {
060      CIRCLE_T *c;
061      graph_obj_init(obj, arg_ptr);
062      (void)va_arg(arg_ptr, int);
063      (void)va_arg(arg_ptr, int);
064      c = (CIRCLE_T *)((unsigned char *)obj->data + CIRCLE_OFFSET);
065      c->radius = va_arg(arg_ptr, int);
066      message(obj, DRAW, g_white);
067  }
068
069  /* circle_draw(object, color); */
070  void circle_draw(OBJECT *obj, va_list arg_ptr)
071  {
072      int color;
073      CIRCLE_T *c;
074      GRAPH_OBJ_T *g;
075      c = (CIRCLE_T *)((unsigned char *)obj->data + CIRCLE_OFFSET);
076      g = (GRAPH_OBJ_T *)((unsigned char *)obj->data +
077        GRAPH_OBJ_OFFSET);
078      color = va_arg(arg_ptr, int);
079      /* g_circle(g->y, g->x, c->radius, va_arg(arg_ptr, int)); */
080      g_circle(g->y, g->x, c->radius, color);
081  }
082
083  /********************************************************/
084  /* CLASS SQUARE (very similar to CIRCLE) */
085
086  struct square_s {
087      int size;
088  };
089
090  typedef struct square_s SQUARE_T;
091  #define SQUARE_SIZE sizeof(SQUARE_T) + GRAPH_OBJ_SIZE
092  #define SQUARE_OFFSET sizeof(GRAPH_OBJ_T)
093
094  /* square_init(object, y_position, x_position, size); */
095  void square_init(OBJECT *obj, va_list arg_ptr)
096  {
097      SQUARE_T *s;
098      graph_obj_init(obj, arg_ptr);
099      (void)va_arg(arg_ptr, int);
100      (void)va_arg(arg_ptr, int);
101      s = (SQUARE_T *)((unsigned char *)obj->data + SQUARE_OFFSET);
102      s->size = va_arg(arg_ptr, int);
103      message(obj, DRAW, g_white);
104  }
105
106  /* square_draw(object, color); */
107  void square_draw(OBJECT *obj, va_list arg_ptr)
108  {
109      SQUARE_T *s;
110      GRAPH_OBJ_T *g;
111      s = (SQUARE_T *)((unsigned char *)obj->data + SQUARE_OFFSET);
112      g = (GRAPH_OBJ_T *)((unsigned char *)obj->data +
113        GRAPH_OBJ_OFFSET);
114      g_square(g->y, g->x, s->size, va_arg(arg_ptr, int));
115  }
116
117  /********************************************************/
118  /* CLASS DOUBLE CIRCLE (sub-class of CIRCLE) */
119
120  #define DOUBLE_CIRCLE_SIZE CIRCLE_SIZE
121
122  /* double_circle_draw(object, color); */
123  void double_circle_draw(OBJECT *obj, va_list arg_ptr)
124  {
125      int color;
126      CIRCLE_T *c;
127      GRAPH_OBJ_T *g;
128      c = (CIRCLE_T *)((unsigned char *)obj->data + CIRCLE_OFFSET);
129      g = (GRAPH_OBJ_T *)((unsigned char *)obj->data +
130        GRAPH_OBJ_OFFSET);
131      color = va_arg(arg_ptr, int);
132      g_circle(g->y, g->x, c->radius, color);
133      g_circle(g->y, g->x, c->radius - 2, color);
134  }
135
136  /********************************************************/
137
138  int main(int argc, char **argv);
139  int main(int argc, char **argv)
140  {
141      int x;
142
143      CLASS graph_obj;
144      CLASS circle;
145      CLASS square;
146      CLASS double_circle;
147
148      OBJECT c1;
149      OBJECT s1;
150      OBJECT dc1;
151
152      g_init();
153
154      /* make class graphical object */
155      new_class(&graph_obj, NULL, 3, GRAPH_OBJ_SIZE);
156      reg_method(&graph_obj, INIT, graph_obj_init);
157      reg_method(&graph_obj, MOVE, graph_obj_move);
158
159      /* make class circle */
160      new_class(&circle, &graph_obj, 3, CIRCLE_SIZE);
161      reg_method(&circle, INIT, circle_init);
162      reg_method(&circle, DRAW, circle_draw);
163
164      /* make class square */
165      new_class(&square, &graph_obj, 3, SQUARE_SIZE);
166      reg_method(&square, INIT, square_init);
167      reg_method(&square, DRAW, square_draw);
168
169      /* make class double_circle */
170      new_class(&double_circle, &circle, 3, DOUBLE_CIRCLE_SIZE);
171      reg_method(&double_circle, DRAW, double_circle_draw);
172
173      /* make a circle object */
174      new_object(&c1, &circle);
175      message(&c1, INIT, 40, 40, 20);
176
177      /* make a square object */
178      new object(&s1, &square);
179      message(&s1, INIT, 40, 100, 20);
180
181      /* make a double circle object */
182      new_object(&dc1, &double_circle);
183      message(&dc1, INIT, 40, 160, 20);
184
185      for (x = 0; x < 100; ++x) {
186          message(&c1, MOVE, 1, 1);
187          message(&s1, MOVE, 1, 0);
188          message(&dc1, MOVE, 0, -1);
189      }
190
191      free_object(&c1);
192      free_object(&s1);
193      free_object(&dc1);
194
195      free_class(&graph_obj);
196      free_class(&circle);
197      free_class(&square);
198      free_class(&double_circle);
199
200      cleanup();
201
202      return (0);
203  }