1 /**********************************************************************
2  *
3  * FILENAME:          xoj.c
4  *
5  * COPYRIGHT: Copyright 1994.  Integrated Silicon Systems, Inc.
6  * ALL RIGHTS RESERVED.  DISTRIBUTION OF THIS FILE, OR CODE
7  * COMPILED WITH IT, OR DERIVED FROM IT, IS STRICTLY PROHIBITED.
8  * THIS SOFTWARE IS PROVIDED AS IS--NO WARRANTEE OF FITNESS FOR ANY
9  * PURPOSE IS IMPLIED.
10  *
11  * DESCRIPTION:       OJ Simpson simulator
12  *
13  * EXPORTS:
14  *
15  * NOTES:
16  *
17  * NECESSARY FILES:
18  *
19  * REVISION HISTORY:
20  * $Log$
21  *
22  **********************************************************************/
23 
24 #include <X11/Xlib.h>
25 #include <X11/Xutil.h>
26 #include <X11/Xos.h>
27 
28 typedef unsigned long Pixel;
29 typedef int ErrorHandler();
30 
31 
32 #include "vroot.h"  /* Use this if vroot.h installed in current directory */
33 
34 #include <stdio.h>
35 #include <math.h>
36 #ifndef __STDC__
37 #include <malloc.h>
38 #endif
39 #include <signal.h>
40 #include <limits.h>
41 
42 #include "ojmap.h"
43 
44 
45 
46 Display *display;
47 int screen;
48 Window rootWin;
49 int display_width, display_height;
50 int center_x, center_y;
51 GC gc;
52 char *display_name = NULL;
53 Pixel black, white;
54 
55 int done = 0;
56 int eventBlock = 0;
57 int errorVal = 0;
58 
59 unsigned int borderWidth = 0;
60 
61 Region SubR;
62 Region WindowTops = NULL;
63 int ClearX, ClearY;
64 
65 char *snowColor = "yellow";
66 char *slcColor = "black";
67 char *trColor = "aquamarine";
68 
69 char *blackColor = "black";
70 char *redColor = "red";
71 char *whiteColor = "white";
72 char *bgColor = "none";
73 char *greenColor = "green";
74 char *blueColor = "blue";
75 
76 Pixel redPix;
77 Pixel whitePix;
78 Pixel greenPix;
79 Pixel bluePix;
80 Pixel blackPix;
81 Pixel snowcPix;
82 Pixel bgPix;
83 Pixel trPix;
84 Pixel slcPix;
85 
86 int theDelay = 12500; /* microseconds */
87 int BroncoSpeed = 2;
88 Bronco theBronco;
89 
90 int n_cops = 6;
91 Cop *copcars;
92 Cop *copters;
93 Pixel *newscolors;
94 
95 
96 /* Forward declarations */
97 void SigHandler();
98 void InitCopter();
99 void DrawCopter();
100 void DrawGawk();
101 void EraseCopter();
102 void InitBronco();
103 void DrawBronco();
104 void EraseBronco();
105 void InitCop();
106 void UpdateBronco();
107 void UpdateCopter();
108 void UpdateCop();
109 void DrawCop();
110 void EraseCop();
111 #if !defined(__FreeBSD__) && !defined(__DragonFly__)
112 void usleep();
113 #endif
114 Pixel AllocNamedColor();
115 
116 void
main(ac,av)117 main(ac, av)
118 int ac;
119 char *av[];
120 {
121     XGCValues xgcv;
122     int ax;
123     char *arg;
124     CopMap *np;
125     CopMap *nbp;
126     CopMap *cp;
127     CopMap *cwp;
128     CopMap *lp;
129     BroncoMap *bp;
130     BroncoMap *bwp;
131     GawkMap *gp;
132     GawkShirtMap *gsp;
133     XEvent ev;
134     int needCalc;
135     int i;
136 
137     /* Seed random */
138     srand((int)time((long *)NULL));
139 
140     /*
141        Catch some signals so we can erase any visible snowflakes.
142     */
143     signal(SIGKILL, SigHandler);
144     signal(SIGINT, SigHandler);
145     signal(SIGHUP, SigHandler);
146     signal(SIGTERM, SigHandler);
147 
148     /*
149        Process command line options.
150     */
151     for (ax=1; ax<ac; ax++){
152       arg = av[ax];
153       if (strcmp(arg, "-display") == 0){
154 	display_name = av[++ax];
155       }
156     }
157 
158     /* Open X */
159     display = XOpenDisplay(display_name);
160     if (display == NULL) {
161 	if (display_name == NULL) display_name = (char *)getenv("DISPLAY");
162 	(void) fprintf(stderr, "%s: cannot connect to X server %s\n", av[0],
163 	    display_name ? display_name : "(default)");
164 	exit(1);
165     }
166 
167     screen = DefaultScreen(display);
168     rootWin = RootWindow(display, screen);
169     black = BlackPixel(display, screen);
170     white = WhitePixel(display, screen);
171 
172     display_width = DisplayWidth(display, screen);
173     display_height = DisplayHeight(display, screen) - 120;	/* jck */
174     center_x = display_width / 2;
175     center_y = display_height / 2;
176 
177 
178     /*
179         P I X M A P S
180     */
181 
182 
183     /* Create the news helicopter pixmap */
184     nbp = &newsbPix;
185     nbp->pixmap = XCreateBitmapFromData( display, rootWin, nbp->copBits,
186 				       nbp->width, nbp->height );
187 
188     np = &newsPix;
189     np->pixmap = XCreateBitmapFromData( display, rootWin, np->copBits,
190 				       np->width, np->height );
191 
192     /* Create the cop car pixmap */
193     cp = &copPix;
194     cp->pixmap = XCreateBitmapFromData( display, rootWin, cp->copBits,
195 				       cp->width, cp->height );
196 
197     cwp = &copwhitePix;
198     cwp->pixmap = XCreateBitmapFromData( display, rootWin, cwp->copBits,
199 				       cwp->width, cwp->height );
200 
201     lp = &lightPix;
202     lp->pixmap = XCreateBitmapFromData( display, rootWin, lp->copBits,
203 				       lp->width, lp->height );
204 
205     /* Allocate structures for cop cars */
206     copcars = (Cop *)malloc( sizeof(Cop) * n_cops );
207     copters = (Cop *)malloc( sizeof(Cop) * n_cops );
208     newscolors = (Pixel *)malloc( sizeof(Pixel) * n_cops );
209 
210     /* Pixmap for bronco */
211     bp = &broncoPix;
212     bp->pixmap = XCreateBitmapFromData( display, rootWin, bp->broncoBits,
213 				       bp->width, bp->height );
214 
215     bwp = &broncoblackPix;
216     bwp->pixmap = XCreateBitmapFromData( display, rootWin, bwp->broncoBits,
217 				       bwp->width, bwp->height );
218 
219 
220     /* Pixmap for onlookers */
221     gp = &gawkPix;
222     gp->pixmap = XCreateBitmapFromData( display, rootWin, gp->gawkBits,
223 				       gp->width, gp->height );
224     gsp = &gawkShirtPix;
225     gsp->pixmap = XCreateBitmapFromData( display, rootWin, gsp->gawkShirtBits,
226 				       gsp->width, gsp->height );
227 
228     /* Allocate colors just once */
229     newscolors[0] = redPix =   AllocNamedColor(redColor, black);
230     newscolors[1] = whitePix = AllocNamedColor(whiteColor, black);
231     newscolors[2] = greenPix = AllocNamedColor(greenColor, black);
232     newscolors[3] = bluePix = AllocNamedColor(blueColor, black);
233     newscolors[4] = blackPix = AllocNamedColor(blackColor, black);
234     newscolors[5] = snowcPix = AllocNamedColor(snowColor, white);
235 	trPix = AllocNamedColor(trColor, black);
236     slcPix = AllocNamedColor(slcColor, black);
237 
238     gc = XCreateGC(display, rootWin, 0L, &xgcv);
239     XSetForeground(display, gc, blackPix);
240     XSetFillStyle(display, gc, FillStippled);
241 
242     /* Set the background color, if specified */
243     if(strcmp(bgColor,"none") != 0) {
244       bgPix = AllocNamedColor(bgColor, white);
245 
246       XSetWindowBackground(display, rootWin, bgPix);
247       XClearWindow(display, rootWin);
248       XFlush(display);
249     }
250 
251     /* People */
252     DrawGawk();
253 
254     /* Initialize all cop cars */
255     for (i=0; i< n_cops; i++) {
256 		InitCop(i);
257 		InitCopter(i);
258 	}
259 
260     InitBronco();
261 
262     /* Notify if part of the root window changed */
263     XSelectInput(display, rootWin, ExposureMask | SubstructureNotifyMask);
264 
265     needCalc = 0;
266 /*    if (!NoKeepSnow) needCalc = CalcWindowTops(); */
267 
268 
269     /*
270      *  M A I N   L O O P
271      */
272     while (!done) {
273 
274 /*      SnowTicks--;
275       if (SnowTicks == 0) SnowTicks = ULONG_MAX; */
276 
277       /* X event ? */
278       /* Handle all the expose events and redo CalcWindowTops after */
279       while (XPending(display)) {
280         XNextEvent(display, &ev);
281 
282       }  /* while Xpending */
283 
284       /* If things have changed while we were away... */
285 /*      if (needCalc) needCalc = CalcWindowTops(); */
286 
287 
288       /*
289        *  Update
290        */
291 
292       for (i=0; i< n_cops; i++) {
293 		UpdateCop(i);
294 		UpdateCopter(i);
295 	  }
296 
297       /* The bronco */
298       XSetForeground(display, gc, slcPix);
299       UpdateBronco();
300 
301       /* Sleep a bit */
302       usleep(theDelay);
303     }
304 
305     XClearWindow(display, rootWin);
306 
307     XCloseDisplay(display);
308 
309     exit(0);
310 }
311 
312 /* Initialize the i'th copter */
InitCopter(i)313 void InitCopter( i )
314 int i;
315 {
316   copters[i].x = (i%2 ? 0 : 300);
317   copters[i].y = copcars[i].y + 5;
318 
319   copters[i].xStep = BroncoSpeed;
320   copters[i].yStep = 1;
321 }
322 
323 /* Initialize the i'th cop car */
InitCop(i)324 void InitCop( i )
325 int i;
326 {
327   copcars[i].x = 100;
328   copcars[i].y = RandInt( display_height / 2 / n_cops - 32 ) +
329                      i * (display_height/ 2 / n_cops ) + 100;	/* jck */
330 
331   copcars[i].xStep = BroncoSpeed;
332   copcars[i].yStep = 0;
333 
334   /* Color of flashing light */
335   copcars[i].color = i % 2;
336 }
337 
338 
339 /* Update position of cop i */
UpdateCop(i)340 void UpdateCop( i )
341 int i;
342 {
343   EraseCop(i);
344 
345   /* Move forward */
346   copcars[i].x = copcars[i].x + copcars[i].xStep;
347 
348   /* Cop cars stay at the same height */
349 
350   if (copcars[i].x >= display_width)
351   {
352 	InitCop(i);
353 	copcars[i].x = 0;
354   }
355 
356   copcars[i].color = 1 - copcars[i].color;
357 
358   DrawCop(i);
359 }
360 
361 /* Update position of copter i */
UpdateCopter(i)362 void UpdateCopter( i )
363 int i;
364 {
365   EraseCopter(i);
366 
367    /* Copters move around!  - dennisf@denix.elk.miles.com */
368    copters[i].x += theBronco.xStep;  /* keep up with theBronco */
369    if (RandInt(10) > 3) copters[i].x += copters[i].xStep;
370    if (copters[i].x < 0) copters[i].x = display_width;
371    if (copters[i].x > display_width) copters[i].x = 0;
372    if (RandInt(10) > 8) copters[i].xStep = -copters[i].xStep;
373 
374    if (RandInt(10) > 3) copters[i].y += copters[i].yStep;
375    if (copters[i].y < 0) copters[i].y = display_height;
376    if (copters[i].y > display_height) copters[i].y = 0;
377    if (RandInt(10) > 8) copters[i].yStep = -copters[i].yStep;
378 
379   DrawCopter(i);
380 }
381 
382 
383 /* Redraw cop number i */
384 void
DrawCop(i)385 DrawCop( i )
386 int i;
387 {
388   XSetForeground( display, gc, blackPix );
389   XSetStipple(display, gc, copPix.pixmap);
390   XSetTSOrigin(display, gc, copcars[i].x, copcars[i].y);
391   XFillRectangle(display, rootWin, gc,
392          copcars[i].x, copcars[i].y,
393          copPix.width, copPix.height );
394 
395   XSetForeground( display, gc, whitePix );
396   XSetStipple(display, gc, copwhitePix.pixmap);
397   XSetTSOrigin(display, gc, copcars[i].x, copcars[i].y);
398   XFillRectangle(display, rootWin, gc,
399          copcars[i].x, copcars[i].y,
400          copwhitePix.width, copwhitePix.height );
401 
402   /* Flash the lights red & blue, alternatingly */
403   if ( copcars[i].color == 0 ){
404     XSetForeground( display, gc, redPix );
405   }
406   else{
407     XSetForeground( display, gc, bluePix );
408   }
409 
410   XSetStipple(display, gc, lightPix.pixmap);
411   XSetTSOrigin(display, gc, copcars[i].x, copcars[i].y);
412   XFillRectangle(display, rootWin, gc,
413          copcars[i].x, copcars[i].y,
414          lightPix.width, lightPix.height );
415 
416 
417 }
418 
419 /* Redraw cop number i */
420 void
DrawCopter(i)421 DrawCopter( i )
422 int i;
423 {
424   XSetForeground( display, gc, newscolors[i] );
425   XSetStipple(display, gc, (i % 2 ? newsPix.pixmap : newsbPix.pixmap));
426   XSetTSOrigin(display, gc, copters[i].x, copters[i].y);
427   XFillRectangle(display, rootWin, gc,
428          copters[i].x, copters[i].y,
429          newsPix.width, newsPix.height );
430 }
431 
432 
433 /* Redraw onlookers */
434 void
DrawGawk()435 DrawGawk( )
436 {
437   int gawkx,gawky,i,gawk_max;
438   int ngawk = 40;
439   int gawkyarr[2];
440 
441   gawk_max = display_height + 120;
442   gawkyarr[0] = gawk_height + 5;
443   gawkyarr[1] = gawk_max/2 + gawk_height + 5;
444 
445 
446   for (i=0;i<ngawk;i++) {
447      gawkx = RandInt(display_width);
448      /*gawkers will be placed randomly over 20 pixels */
449      gawky = gawkyarr[i % 2] + ( (((i % 2) * 2) - 1) * (int) (5.0 * exp(3.5 * RandInt(100)/100)) );
450 /*
451      gawky = gawkyarr[i % 2]+ RandInt(20);
452 /**/
453      XSetForeground( display, gc, blackPix );
454      XSetStipple(display, gc, gawkPix.pixmap);
455      XSetTSOrigin(display, gc, gawkx, gawky);
456      XFillRectangle(display, rootWin, gc,
457             gawkx, gawky,
458             gawkPix.width, gawkPix.height );
459 
460      XSetForeground( display, gc, newscolors[RandInt(5)] );
461      XSetStipple(display, gc, gawkShirtPix.pixmap);
462      XSetTSOrigin(display, gc, gawkx, gawky);
463      XFillRectangle(display, rootWin, gc,
464             gawkx, gawky,
465             gawkShirtPix.width, gawkShirtPix.height );
466   }
467 }
468 
469 /* Erase copter i */
470 void
EraseCopter(i)471 EraseCopter( i )
472 {
473   if (copters[i].x >= 0)
474       XClearArea(display, rootWin,
475                  copters[i].x , copters[i].y,
476                  newsPix.width, newsPix.height, False);
477 }
478 
479 /* Erase cop i */
480 void
EraseCop(i)481 EraseCop( i )
482 {
483   if (copcars[i].x >= 0)
484       XClearArea(display, rootWin,
485                  copcars[i].x , copcars[i].y,
486                  copPix.width, copPix.height, False);
487 }
488 
489 
490 
491 /*
492    Give birth to a Bronco. (What a conception)
493 */
494 void
InitBronco()495 InitBronco()
496 {
497   theBronco.x = 200;
498   theBronco.y = RandInt(display_height / 3)+80;
499   theBronco.xStep = BroncoSpeed;
500   theBronco.yStep = 1;
501 }
502 
503 
504 
505 /*
506   Update Bronco
507 */
508 void
UpdateBronco()509 UpdateBronco()
510 {
511   EraseBronco();
512 
513   /* Move forward */
514   theBronco.x = theBronco.x + theBronco.xStep;
515 
516   /* Move down */
517   if (RandInt(10) > 3) theBronco.y = theBronco.y + theBronco.yStep;
518   if (theBronco.y < 0) theBronco.y = 0;
519   if (RandInt(100) > 80) theBronco.yStep = -theBronco.yStep;
520 
521   if (RandInt(100) > 95) DrawGawk();
522 
523   if (theBronco.x >= display_width) theBronco.x = 0;
524 
525   DrawBronco();
526 }
527 
528 
529 
530 
531 /*
532   Draw Bronco
533 */
534 void
DrawBronco()535 DrawBronco()
536 {
537   XSetForeground( display, gc, whitePix );
538   XSetStipple(display, gc, broncoPix.pixmap);
539   XSetTSOrigin(display, gc, theBronco.x, theBronco.y);
540   XFillRectangle(display, rootWin, gc,
541          theBronco.x, theBronco.y,
542          broncoPix.width, broncoPix.height );
543 
544   XSetForeground( display, gc, blackPix );
545   XSetStipple(display, gc, broncoblackPix.pixmap);
546   XSetTSOrigin(display, gc, theBronco.x, theBronco.y);
547   XFillRectangle(display, rootWin, gc,
548          theBronco.x, theBronco.y,
549          broncoblackPix.width, broncoblackPix.height );
550 
551 }
552 
553 /*
554   Erase Bronco
555 */
556 void
EraseBronco()557 EraseBronco()
558 {
559   if (theBronco.x >= 0)
560       XClearArea(display, rootWin,
561                  theBronco.x , theBronco.y,
562                  broncoPix.width, broncoPix.height, False);
563 }
564 
565 
566 
567 void
SigHandler(sig)568 SigHandler(sig)
569 int sig;
570 {
571   printf("Caught Signal [%d]\n", sig);
572   if (sig != SIGHUP)
573 	done = 1;
574 }
575 
576 
577 /*
578    Generate random integer between 0 and maxVal-1.
579 */
580 int
RandInt(maxVal)581 RandInt(maxVal)
582 int maxVal;
583 {
584 	return rand() % maxVal;
585 }
586 
587 
588 /*
589  * sleep for a number of micro-seconds
590  */
591 #if !defined(__FreeBSD__) && !defined(__DragonFly__)
usleep(usec)592 void usleep(usec)
593 unsigned long usec;
594 {
595 #ifdef SVR3
596     poll((struct poll *)0, (size_t)0, usec/1000);   /* ms resolution */
597 #else
598     struct timeval t;
599     t.tv_usec = usec%(unsigned long)1000000;
600     t.tv_sec = usec/(unsigned long)1000000;
601     select(0, (void *)0, (void *)0, (void *)0, &t);
602 #endif
603 }
604 #endif
605 
606 
607 
608 
609 /*
610    Allocate a color by name.
611 */
612 Pixel
AllocNamedColor(colorName,dfltPix)613 AllocNamedColor(colorName, dfltPix)
614 char *colorName;
615 Pixel dfltPix;
616 {
617 	Pixel pix;
618 	XColor scrncolor;
619 	XColor exactcolor;
620 
621 	if (XAllocNamedColor(display, DefaultColormap(display, screen),
622 		colorName, &scrncolor, &exactcolor)) {
623 		pix = scrncolor.pixel;
624 	}
625 	else {
626 		pix = dfltPix;
627 	}
628 
629 	return pix;
630 }
631