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