1MODULE oocXYplane;
2(*
3Module XYplane provides some basic facilities for graphics programming. Its
4interface is kept as simple as possible and is therefore more suited for
5programming exercises than for serious graphics applications.
6
7XYplane provides a Cartesian plane of pixels that can be drawn and erased. The
8plane is mapped to some location on the screen. The variables X and Y indicate
9its lower left corner, W its width and H its height. All variables are
10read-only.
11*)
12
13IMPORT
14  Out := Console, C := oocC, X11 := oocX11, Xu := oocXutil, SYSTEM;
15
16
17CONST
18  erase* = 0;
19  draw* = 1;
20  (*sizeSet = MAX (SET)+1;*)
21  sizeSet = 32; (* in ooc SET is always 32 bit *)
22
23TYPE string = ARRAY 32 OF CHAR;
24
25VAR
26  X-, Y-, W-, H-: INTEGER;
27
28  display: X11.DisplayPtr;
29  window: X11.Window;
30  fg, bg: X11.GC;
31
32  initialized: BOOLEAN;  (* first call to Open sets this to TRUE *)
33  image: X11.XImagePtr;
34  map: POINTER TO ARRAY OF ARRAY OF SET;
35
36
37
38PROCEDURE -aincludexlib      "#include <X11/Xlib.h>";
39PROCEDURE -aincludexutil     "#include <X11/Xutil.h>";
40PROCEDURE -aincludexresource "#include <X11/Xresource.h>";
41
42
43PROCEDURE Error (msg: ARRAY OF CHAR);
44  BEGIN
45    Out.String ("Error: ");
46    Out.String (msg);
47    Out.Ln;
48    HALT (1)
49  END Error;
50
51PROCEDURE Clear*;
52(* Erases all pixels in the drawing plane.  *)
53  VAR
54    x, y: INTEGER;
55  BEGIN
56    X11.XFillRectangle (display, window, bg, 0, 0, W+1, H+1);
57    FOR y := 0 TO SHORT (LEN (map^, 0))-1 DO
58      FOR x := 0 TO SHORT (LEN (map^, 1))-1 DO
59        map[y, x] := {}
60      END
61    END;
62    X11.XFlush (display)
63  END Clear;
64
65PROCEDURE Dot* (x, y, mode: INTEGER);
66(* Dot(x, y, m) draws or erases the pixel at the coordinates (x, y) relative to
67   the lower left corner of the plane. If m=draw the pixel is drawn, if m=erase
68   the pixel is erased.  *)
69  VAR
70    dummy: C.int;
71  BEGIN
72    IF (x >= X) & (x < X+W) & (y >= Y) & (y < Y+H) THEN
73      dummy := image. f. putpixel(image, x, H-1-y, mode);
74      CASE mode OF
75      | draw:
76        X11.XDrawPoint (display, window, fg, x, H-1-y)
77      | erase:
78        X11.XDrawPoint (display, window, bg, x, H-1-y)
79      ELSE
80      END;
81      X11.XFlush (display);
82    END
83  END Dot;
84
85PROCEDURE IsDot* (x, y: INTEGER): BOOLEAN;
86(* IsDot(x, y) returns TRUE if the pixel at the coordinates (x, y) relative to
87   the lower left corner of the plane is drawn, otherwise it returns FALSE. *)
88  BEGIN
89    IF (x < X) OR (x >= X+W) OR (y < Y) OR (y >= Y+H) THEN
90      RETURN FALSE
91    ELSE
92      RETURN (image. f. getpixel (image, x, H-1-y) # erase)
93    END
94  END IsDot;
95
96PROCEDURE Key* (): CHAR;
97(* Reads the keyboard. If a key was pressed prior to invocation, its
98   character value is returned, otherwise the result is 0X.  *)
99  CONST
100    sizeBuffer = 16;
101  VAR
102    event: X11.XEvent;
103    buffer: ARRAY sizeBuffer OF C.char;
104    keySym: X11.KeySym;
105    numChars: C.int;
106    nl : C.longint;
107
108  PROCEDURE Redraw (x0, y0, w0, h0: INTEGER);
109    BEGIN
110      (* clip width and height to size of initial window *)
111      IF (x0+w0 > W) THEN
112        w0 := W-x0
113      END;
114      IF (y0+h0 > H) THEN
115        h0 := H-y0
116      END;
117      IF (w0 > 0) & (h0 > 0) THEN
118        X11.XPutImage (display, window, fg, image, x0, y0, x0, y0, w0, h0)
119      END
120    END Redraw;
121
122  BEGIN
123    WHILE initialized &
124          (X11.XEventsQueued (display, X11.QueuedAfterReading) > 0) DO
125      X11.XNextEvent (display, event);
126      nl := 0;
127      IF (event. type = X11.KeyPress) THEN
128        numChars := Xu.XLookupString (
129          (*event. xkey, buffer, sizeBuffer, keySym, NIL);*)
130          event, buffer, sizeBuffer, keySym, nl);
131        IF (numChars > 0) THEN
132          RETURN SYSTEM.VAL (CHAR, buffer[0])
133        END
134      ELSIF (event. type = X11.Expose) THEN
135        Redraw (SHORT (event. xexpose. x), SHORT (event. xexpose. y),
136                SHORT (event. xexpose. width), SHORT (event. xexpose. height))
137      END
138    END;
139    RETURN 0X
140  END Key;
141
142PROCEDURE Open*;
143(* Initializes the drawing plane.  *)
144  VAR
145    screen:  C.int;
146    parent:  X11.Window;
147    bgColor: C.longint;
148    fgColor: C.longint;
149    gcValue: X11.XGCValues;
150    event:   X11.XEvent;
151    x, y:    INTEGER;
152    tmpstr:  string;
153    scrn :   C.int;
154    vis :    X11.VisualPtr;
155  BEGIN
156    IF ~initialized THEN
157      initialized := TRUE;
158
159      tmpstr[0] := 0X;
160      (*display := X11.XOpenDisplay (NIL);*)
161      display := X11.XOpenDisplay(tmpstr);
162      (*display := X11.OpenDisplay (NIL);*)
163      IF (display = NIL) THEN
164        Error("Couldn't open display")
165      ELSE
166        screen := X11.XDefaultScreen(display);
167        X := 0; Y := 0;
168        W := SHORT (X11.XDisplayWidth (display, screen));
169        H := SHORT (X11.XDisplayHeight(display, screen));
170        (* adjust ratio W:H to 3:4 [for no paritcular reason] *)
171        IF (W > 3*H DIV 4) THEN
172          W := 3*H DIV 4
173        END;
174        parent  := X11.XRootWindow(display, screen);
175        fgColor := X11.XBlackPixel(display, screen);
176        bgColor := X11.XWhitePixel(display, screen);
177        window  := X11.XCreateSimpleWindow(display, parent, 0, 0,
178                                           W, H, 0, 0, bgColor);
179        X11.XStoreName(display, window, "XYplane");
180        X11.XSelectInput(display, window, X11.KeyPressMask+X11.ExposureMask);
181        X11.XMapWindow(display, window);
182        X11.XFlush (display);
183        (*tmpint := W + ((*sizeSet*)32-1);
184	tmpint := tmpint DIV 32(*sizeSet*);*)
185        NEW (map, H, (W+(sizeSet-1)) DIV sizeSet);
186        (*NEW (map, H, tmpint);*)
187        FOR y := 0 TO SHORT (LEN (map^, 0))-1 DO
188          FOR x := 0 TO SHORT (LEN (map^, 1))-1 DO
189            map[y, x] := {}
190          END
191        END;
192
193	      scrn  := X11.XDefaultScreen(display);
194        vis   := X11.XDefaultVisual(display, scrn);
195	      image := X11.XCreateImage (display,
196                  (*X11.XDefaultVisual (display, X11.XDefaultScreen (display)),*)
197                  vis,
198                  (*1, X11.XYBitmap, 0, SYSTEM.ADR (map^), W, H, sizeSet, 0);*)
199                  1, X11.ZPixmap, 0, SYSTEM.VAL(C.address,SYSTEM.ADR(map^)), W, H, (*sizeSet*)32, 0);
200
201        (* wait until the window manager gives its ok to draw things *)
202        X11.XMaskEvent(display, X11.ExposureMask, event);
203
204        (* create graphic context to draw resp. erase a point *)
205        gcValue. foreground := fgColor;
206        gcValue. background := bgColor;
207        fg := X11.XCreateGC (display, parent,
208                             X11.GCForeground+X11.GCBackground, gcValue);
209        gcValue. foreground := bgColor;
210        gcValue. background := fgColor;
211        bg := X11.XCreateGC (display, parent,
212                             X11.GCForeground+X11.GCBackground, gcValue)
213      END
214    END
215  END Open;
216
217PROCEDURE Close*;
218
219   BEGIN
220  (*    X11.XDestroyImage(image);
221      X11.XDestroyWindow(display, window);*)
222      X11.XCloseDisplay(display);
223
224   END Close;
225
226
227BEGIN
228  initialized := FALSE;
229  X := 0; Y := 0; W := 0; H := 0;
230  image := NIL; map := NIL
231END oocXYplane.
232