1 | /* |
---|
2 | * @(#) vermiculate.c |
---|
3 | * @(#) Copyright (C) 2001 Tyler Pierce (tyler@alumni.brown.edu) |
---|
4 | * The full program, with documentation, is available at: |
---|
5 | * http://freshmeat.net/projects/fdm |
---|
6 | * |
---|
7 | * Permission to use, copy, modify, distribute, and sell this software and its |
---|
8 | * documentation for any purpose is hereby granted without fee, provided that |
---|
9 | * the above copyright notice appear in all copies and that both that |
---|
10 | * copyright notice and this permission notice appear in supporting |
---|
11 | * documentation. No representations are made about the suitability of this |
---|
12 | * software for any purpose. It is provided "as is" without express or |
---|
13 | * implied warranty. |
---|
14 | */ |
---|
15 | |
---|
16 | #include <stdio.h> |
---|
17 | #include <stdlib.h> |
---|
18 | #include <string.h> |
---|
19 | #include <ctype.h> |
---|
20 | #include <unistd.h> |
---|
21 | #include <sys/time.h> |
---|
22 | #include <math.h> |
---|
23 | |
---|
24 | #ifdef VERMICULATE_STANDALONE |
---|
25 | #include "yarandom.h" |
---|
26 | #include "usleep.h" |
---|
27 | #include <X11/Xlib.h> |
---|
28 | #include <X11/Xutil.h> |
---|
29 | #include <X11/Xatom.h> |
---|
30 | #include <X11/Xresource.h> |
---|
31 | #else |
---|
32 | #include "screenhack.h" |
---|
33 | #include "config.h" |
---|
34 | #endif /* VERMICULATE_STANDALONE */ |
---|
35 | |
---|
36 | #define degs 360 |
---|
37 | #define degs2 (degs/2) |
---|
38 | #define degs4 (degs/4) |
---|
39 | #define degs8 (degs/8) |
---|
40 | #define dtor 0.0174532925 /* pi / degs2; */ |
---|
41 | #define thrmax 120 |
---|
42 | #define tailmax (thrmax * 2 + 1) |
---|
43 | #define tmodes '7' |
---|
44 | #define ymax (hei - 1) |
---|
45 | #define ymin 0 |
---|
46 | #define xmax (wid - 1) |
---|
47 | #define xmin 0 |
---|
48 | #define rlmax 200 |
---|
49 | #define SPEEDINC 10 |
---|
50 | #define SPEEDMAX 1000 |
---|
51 | #define wraparound(VAL,LOWER,UPPER) { \ |
---|
52 | if (VAL >= UPPER) \ |
---|
53 | VAL -= UPPER - LOWER; \ |
---|
54 | else if (VAL < LOWER) \ |
---|
55 | VAL += UPPER - LOWER; } |
---|
56 | #define arrcpy(DEST,SRC) memcpy (DEST, SRC, sizeof(DEST)) |
---|
57 | |
---|
58 | typedef double real; |
---|
59 | typedef unsigned char banktype[thrmax]; |
---|
60 | |
---|
61 | typedef struct linedata |
---|
62 | { |
---|
63 | int deg, spiturn, turnco, turnsize; |
---|
64 | unsigned char col; |
---|
65 | Bool dead; |
---|
66 | |
---|
67 | char orichar; |
---|
68 | real x, y; |
---|
69 | int tmode, tsc, tslen, tclim, otslen, ctinc, reclen, recpos, circturn, prey, |
---|
70 | slice; |
---|
71 | int xrec[rlmax + 1], yrec[rlmax + 1]; |
---|
72 | int turnseq[50]; |
---|
73 | Bool filled, killwalls, vhfollow, |
---|
74 | selfbounce, tailfollow, realbounce, little; |
---|
75 | } |
---|
76 | linedata; |
---|
77 | |
---|
78 | #ifdef VERMICULATE_STANDALONE |
---|
79 | static XEvent myevent; |
---|
80 | static Bool use_root = False; |
---|
81 | static unsigned char rgb[256][3]; |
---|
82 | |
---|
83 | #else |
---|
84 | char *progclass = "Vermiculate"; |
---|
85 | |
---|
86 | char *defaults[] = { |
---|
87 | ".ticks: 20000", |
---|
88 | 0 |
---|
89 | }; |
---|
90 | |
---|
91 | XrmOptionDescRec options[] = { |
---|
92 | {"-speed", ".speed", XrmoptionSepArg, 0}, |
---|
93 | {"-instring", ".instring", XrmoptionSepArg, 0}, |
---|
94 | {0, 0, 0, 0} |
---|
95 | }; |
---|
96 | #endif /* VERMICULATE_STANDALONE */ |
---|
97 | |
---|
98 | static Display *mydpy; |
---|
99 | static Window mywindow; |
---|
100 | static GC mygc; |
---|
101 | static Colormap mycmap; |
---|
102 | static XWindowAttributes xgwa; |
---|
103 | static Bool neednewkey = True; |
---|
104 | static XColor mycolors[tailmax]; |
---|
105 | |
---|
106 | static int hei = 500, wid = 500, speed = 100; |
---|
107 | static Bool erasing = True; |
---|
108 | static char *instring = 0; |
---|
109 | static int max_ticks; |
---|
110 | |
---|
111 | static struct stringAndSpeed |
---|
112 | { |
---|
113 | char *str; |
---|
114 | int speed; |
---|
115 | } |
---|
116 | sampleStrings[] = |
---|
117 | { |
---|
118 | { "]]]]]]]]7ces123400-9-8#c123456#s9998880004#ma3#car9ma6#c-#r1", 600} , |
---|
119 | { "bmarrrr#c1234#lc5678#lyet]", 600} , |
---|
120 | { "AEBMN222222223#CAR9CAD4CAOV", 150} , |
---|
121 | { "mn333#c23#f1#]]]]]]]]]]]3bc9#r9#c78#f9#ma4#", 600} , |
---|
122 | { "AEBMN22222#CAD4CAORc1#f2#c1#r6", 100} , |
---|
123 | /* { "mn6666666#c1i#f1#y2#sy2#vyety1#ry13i#l", 40} , */ |
---|
124 | { "aebmnrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr#", 500} , |
---|
125 | { "bg+++++++++++++++++++++++#mnrrrrrrrrrrrrrrrrrrrrrrr#y1#k", 500} , |
---|
126 | { "BMN22222223#CAD4CAOVYAS", 150} , |
---|
127 | /* { "aebmnrrrrrrrrrrrrrrrr#yaryakg--#", 100} , */ |
---|
128 | { "mn6rrrrrrrrrrrrrrr#by1i#lcalc1#fnyav", 200 } , |
---|
129 | { "mn1rrrrrrrrrrrrrrr#by1i#lcalc1#fn", 200 } |
---|
130 | }; |
---|
131 | |
---|
132 | static real sinof[degs], cosof[degs], tanof[degs]; |
---|
133 | static unsigned char *point; |
---|
134 | |
---|
135 | static linedata thread[thrmax]; |
---|
136 | static banktype bank; |
---|
137 | static int bankt, boxw, boxh, curviness, gridden, ogd, bordcorn; |
---|
138 | static unsigned char bordcol, threads; |
---|
139 | static char ch, boolop; |
---|
140 | |
---|
141 | static Bool |
---|
142 | wasakeypressed (void) |
---|
143 | { |
---|
144 | if (!neednewkey || *instring != 0) |
---|
145 | return True; |
---|
146 | else |
---|
147 | #ifdef VERMICULATE_STANDALONE |
---|
148 | return !(neednewkey = |
---|
149 | !XCheckWindowEvent (mydpy, mywindow, KeyPressMask, &myevent)); |
---|
150 | #else |
---|
151 | return False; |
---|
152 | #endif /* VERMICULATE_STANDALONE */ |
---|
153 | } |
---|
154 | |
---|
155 | static char |
---|
156 | readkey (void) |
---|
157 | { |
---|
158 | char readkey_result; |
---|
159 | if (*instring == 0) |
---|
160 | { |
---|
161 | #ifdef VERMICULATE_STANDALONE |
---|
162 | char key_buffer[1]; |
---|
163 | KeySym key_sym; |
---|
164 | if (neednewkey) |
---|
165 | XWindowEvent (mydpy, mywindow, KeyPressMask, &myevent); |
---|
166 | XLookupString (&myevent.xkey, key_buffer, 1, &key_sym, NULL); |
---|
167 | readkey_result = key_sym; |
---|
168 | #else |
---|
169 | readkey_result = '#'; |
---|
170 | #endif /* VERMICULATE_STANDALONE */ |
---|
171 | neednewkey = True; |
---|
172 | } |
---|
173 | else |
---|
174 | { |
---|
175 | readkey_result = *instring; |
---|
176 | instring++; |
---|
177 | }; |
---|
178 | return toupper (readkey_result); |
---|
179 | } |
---|
180 | |
---|
181 | static unsigned int |
---|
182 | random1 (unsigned int i) |
---|
183 | { |
---|
184 | return (ya_random () % i); |
---|
185 | } |
---|
186 | |
---|
187 | static void |
---|
188 | waitabit (void) |
---|
189 | { |
---|
190 | static int cyc = 0; |
---|
191 | cyc += threads; |
---|
192 | while (cyc > speed) |
---|
193 | { |
---|
194 | usleep (10000); |
---|
195 | cyc -= speed; |
---|
196 | } |
---|
197 | } |
---|
198 | |
---|
199 | static void |
---|
200 | clearscreen (void) |
---|
201 | { |
---|
202 | XClearWindow (mydpy, mywindow); |
---|
203 | memset (point, 0, wid * hei); |
---|
204 | } |
---|
205 | |
---|
206 | static void |
---|
207 | sp (int x, int y, int c) |
---|
208 | { |
---|
209 | XSetForeground (mydpy, mygc, mycolors[c].pixel); |
---|
210 | XDrawPoint (mydpy, mywindow, mygc, x, y); |
---|
211 | point[(wid * y) + x] = c; |
---|
212 | } |
---|
213 | |
---|
214 | static int |
---|
215 | gp (int x, int y) |
---|
216 | { |
---|
217 | return point[(wid * y) + x]; |
---|
218 | } |
---|
219 | |
---|
220 | static void |
---|
221 | redraw (int x, int y, int width, int height) |
---|
222 | { |
---|
223 | int xc, yc; |
---|
224 | for (xc = x; xc <= x + width - 1; xc++) |
---|
225 | for (yc = y; yc <= y + height - 1; yc++) |
---|
226 | if (point[wid * yc + xc] != 0) |
---|
227 | sp (xc, yc, point[wid * yc + xc]); |
---|
228 | } |
---|
229 | |
---|
230 | static void |
---|
231 | palupdate (Bool forceUpdate) |
---|
232 | { |
---|
233 | if (forceUpdate || *instring == 0) |
---|
234 | { |
---|
235 | #ifdef VERMICULATE_STANDALONE |
---|
236 | int colnum; |
---|
237 | for (colnum = 0; colnum < tailmax; colnum++) |
---|
238 | { |
---|
239 | mycolors[colnum].red = rgb[colnum][0] << 10; |
---|
240 | mycolors[colnum].green = rgb[colnum][1] << 10; |
---|
241 | mycolors[colnum].blue = rgb[colnum][2] << 10; |
---|
242 | mycolors[colnum].flags = DoRed | DoBlue | DoGreen; |
---|
243 | XAllocColor (mydpy, mycmap, &mycolors[colnum]); |
---|
244 | }; |
---|
245 | #endif /* VERMICULATE_STANDALONE */ |
---|
246 | redraw (xmin, ymin, wid, hei); |
---|
247 | } |
---|
248 | } |
---|
249 | |
---|
250 | static void |
---|
251 | randpal (void) |
---|
252 | { |
---|
253 | #ifdef VERMICULATE_STANDALONE |
---|
254 | int co, ro; |
---|
255 | for (co = 1; co <= 255; co++) |
---|
256 | for (ro = 0; ro <= 2; ro++) |
---|
257 | if (co > tailmax) |
---|
258 | rgb[co][ro] = random1 (20); |
---|
259 | else |
---|
260 | rgb[co][ro] = random1 (64); |
---|
261 | for (ro = 0; ro <= 2; ro++) |
---|
262 | rgb[0][ro] = 0; |
---|
263 | #else |
---|
264 | int ncolors = tailmax - 1; |
---|
265 | make_random_colormap (mydpy, |
---|
266 | xgwa.visual, |
---|
267 | mycmap, &mycolors[1], &ncolors, True, True, 0, True); |
---|
268 | if (ncolors < tailmax - 1) |
---|
269 | { |
---|
270 | int c; |
---|
271 | for (c = 1; c < tailmax; c++) |
---|
272 | mycolors[c].pixel = WhitePixel (mydpy, DefaultScreen (mydpy)); |
---|
273 | } |
---|
274 | #endif /* VERMICULATE_STANDALONE */ |
---|
275 | } |
---|
276 | |
---|
277 | static void |
---|
278 | gridupdate (Bool interruptible) |
---|
279 | { |
---|
280 | int x, y; |
---|
281 | if (gridden > 0) |
---|
282 | for (x = 0; x <= xmax && !(wasakeypressed () && interruptible); x += boxw) |
---|
283 | for (y = 0; y <= ymax; y += boxh) |
---|
284 | { |
---|
285 | if (random1 (15) < gridden) |
---|
286 | { |
---|
287 | #define lesser(A,B) ( ((A)<(B)) ? (A) : (B) ) |
---|
288 | int max = lesser (x + boxw, xmax); |
---|
289 | int xc; |
---|
290 | for (xc = x; xc <= max; xc++) |
---|
291 | sp (xc, y, 1); |
---|
292 | } |
---|
293 | if (random1 (15) < gridden) |
---|
294 | { |
---|
295 | int max = lesser (y + boxh, ymax); |
---|
296 | int yc; |
---|
297 | for (yc = y; yc <= max; yc++) |
---|
298 | sp (x, yc, 1); |
---|
299 | } |
---|
300 | } |
---|
301 | } |
---|
302 | |
---|
303 | static void |
---|
304 | bordupdate (void) |
---|
305 | { |
---|
306 | int xbord, ybord; |
---|
307 | |
---|
308 | if (bordcorn == 0 || bordcorn == 1) |
---|
309 | ybord = ymin; |
---|
310 | else |
---|
311 | ybord = ymax; |
---|
312 | if (bordcorn == 0 || bordcorn == 3) |
---|
313 | xbord = xmin; |
---|
314 | else |
---|
315 | xbord = xmax; |
---|
316 | { |
---|
317 | int x, y; |
---|
318 | for (x = xmin; x <= xmax; x++) |
---|
319 | sp (x, ybord, bordcol); |
---|
320 | for (y = ymin; y <= ymax; y++) |
---|
321 | sp (ybord, y, bordcol); |
---|
322 | } |
---|
323 | } |
---|
324 | |
---|
325 | static Bool |
---|
326 | inbank (unsigned char thr) |
---|
327 | { |
---|
328 | int c; |
---|
329 | if (bankt > 0) |
---|
330 | for (c = 1; c <= bankt; c++) |
---|
331 | if (bank[c - 1] == thr) |
---|
332 | return True; |
---|
333 | return False; |
---|
334 | } |
---|
335 | |
---|
336 | static void |
---|
337 | pickbank (void) |
---|
338 | { |
---|
339 | unsigned char thr = 1; |
---|
340 | #ifdef VERMICULATE_STANDALONE |
---|
341 | int co, ro; |
---|
342 | unsigned char orgb[256][3]; |
---|
343 | |
---|
344 | arrcpy (orgb, rgb); |
---|
345 | for (co = 2; co <= tailmax; co++) |
---|
346 | for (ro = 0; ro <= 2; ro++) |
---|
347 | rgb[co][ro] = 25; |
---|
348 | #endif /* VERMICULATE_STANDALONE */ |
---|
349 | bankt = 0; |
---|
350 | ch = '\0'; |
---|
351 | do |
---|
352 | { |
---|
353 | while (inbank (thr)) |
---|
354 | thr = thr % threads + 1; |
---|
355 | #ifdef VERMICULATE_STANDALONE |
---|
356 | for (co = 1; co <= threads; co++) |
---|
357 | { |
---|
358 | for (ro = 0; ro <= 2; ro++) |
---|
359 | rgb[co + 1][ro] = 25; |
---|
360 | if (inbank (co)) |
---|
361 | for (ro = 0; ro <= 1; ro++) |
---|
362 | rgb[co + 1][ro] = 60; |
---|
363 | } |
---|
364 | for (ro = 0; ro <= 2; ro++) |
---|
365 | rgb[thr + 1][ro] = 60; |
---|
366 | #endif /* VERMICULATE_STANDALONE */ |
---|
367 | palupdate (False); |
---|
368 | ch = readkey (); |
---|
369 | palupdate (False); |
---|
370 | switch (ch) |
---|
371 | { |
---|
372 | case '+': |
---|
373 | case '-': |
---|
374 | do |
---|
375 | { |
---|
376 | if (ch == '+') |
---|
377 | thr++; |
---|
378 | else |
---|
379 | thr--; |
---|
380 | wraparound (thr, 1, threads + 1); |
---|
381 | } |
---|
382 | while (inbank (thr)); |
---|
383 | break; |
---|
384 | case ' ': |
---|
385 | bank[++bankt - 1] = thr; |
---|
386 | break; |
---|
387 | case '1': case '2': case '3': |
---|
388 | case '4': case '5': case '6': |
---|
389 | case '7': case '8': case '9': |
---|
390 | |
---|
391 | bank[++bankt - 1] = ch - '0'; |
---|
392 | if (bank[bankt - 1] > threads) |
---|
393 | bankt--; |
---|
394 | break; |
---|
395 | case 'I': |
---|
396 | { |
---|
397 | banktype tbank; |
---|
398 | int tbankt = 0; |
---|
399 | int c; |
---|
400 | for (c = 1; c <= threads; c++) |
---|
401 | if (!inbank (c)) |
---|
402 | tbank[++tbankt - 1] = c; |
---|
403 | bankt = tbankt; |
---|
404 | arrcpy (bank, tbank); |
---|
405 | } |
---|
406 | break; |
---|
407 | case 'T': |
---|
408 | ch = readkey (); |
---|
409 | switch (ch) |
---|
410 | { |
---|
411 | case '1': case '2': case '3': |
---|
412 | case '4': case '5': case '6': |
---|
413 | case '7': case '8': case '9': |
---|
414 | |
---|
415 | { |
---|
416 | int c; |
---|
417 | for (c = 1; c <= threads; c++) |
---|
418 | if (thread[c - 1].tmode == ch - '0') |
---|
419 | bank[++bankt - 1] = c; |
---|
420 | } |
---|
421 | break; |
---|
422 | } |
---|
423 | break; |
---|
424 | case 'A': |
---|
425 | for (bankt = 1; bankt <= threads; bankt++) |
---|
426 | bank[bankt - 1] = bankt; |
---|
427 | bankt = threads; |
---|
428 | break; |
---|
429 | case 'E': |
---|
430 | for (bankt = 1; bankt <= thrmax; bankt++) |
---|
431 | bank[bankt - 1] = bankt; |
---|
432 | bankt = thrmax; |
---|
433 | break; |
---|
434 | } |
---|
435 | } |
---|
436 | while (!(bankt >= threads || ch == 'N' || ch == '\15' || ch == '#')); |
---|
437 | if (bankt == 0 && ch != 'N') |
---|
438 | { |
---|
439 | bankt = 1; |
---|
440 | bank[0] = thr; |
---|
441 | } |
---|
442 | #ifdef VERMICULATE_STANDALONE |
---|
443 | arrcpy (rgb, orgb); |
---|
444 | #endif /* VERMICULATE_STANDALONE */ |
---|
445 | palupdate (False); |
---|
446 | } |
---|
447 | |
---|
448 | static void |
---|
449 | bankmod (Bool * Bool_) |
---|
450 | { |
---|
451 | switch (boolop) |
---|
452 | { |
---|
453 | case 'T': |
---|
454 | *Bool_ = !*Bool_; |
---|
455 | break; |
---|
456 | case 'Y': |
---|
457 | *Bool_ = True; |
---|
458 | break; |
---|
459 | case 'N': |
---|
460 | *Bool_ = False; |
---|
461 | break; |
---|
462 | } |
---|
463 | } |
---|
464 | |
---|
465 | static void |
---|
466 | newonscreen (unsigned char thr) |
---|
467 | { |
---|
468 | linedata *LP = &thread[thr - 1]; |
---|
469 | LP->filled = False; |
---|
470 | LP->dead = False; |
---|
471 | LP->reclen = (LP->little) ? |
---|
472 | random1 (10) + 5 : random1 (rlmax - 30) + 30; |
---|
473 | LP->deg = random1 (degs); |
---|
474 | LP->y = random1 (hei); |
---|
475 | LP->x = random1 (wid); |
---|
476 | LP->recpos = 0; |
---|
477 | LP->turnco = 2; |
---|
478 | LP->turnsize = random1 (4) + 2; |
---|
479 | } |
---|
480 | |
---|
481 | static void |
---|
482 | firstinit (unsigned char thr) |
---|
483 | { |
---|
484 | linedata *LP = &thread[thr - 1]; |
---|
485 | LP->col = thr + 1; |
---|
486 | LP->prey = 0; |
---|
487 | LP->tmode = 1; |
---|
488 | LP->slice = degs / 3; |
---|
489 | LP->orichar = 'R'; |
---|
490 | LP->spiturn = 5; |
---|
491 | LP->selfbounce = False; |
---|
492 | LP->realbounce = False; |
---|
493 | LP->vhfollow = False; |
---|
494 | LP->tailfollow = False; |
---|
495 | LP->killwalls = False; |
---|
496 | LP->little = False; |
---|
497 | LP->ctinc = random1 (2) * 2 - 1; |
---|
498 | LP->circturn = ((thr % 2) * 2 - 1) * ((thr - 1) % 7 + 1); |
---|
499 | LP->tsc = 1; |
---|
500 | LP->tslen = 6; |
---|
501 | LP->turnseq[0] = 6; |
---|
502 | LP->turnseq[1] = -6; |
---|
503 | LP->turnseq[2] = 6; |
---|
504 | LP->turnseq[3] = 6; |
---|
505 | LP->turnseq[4] = -6; |
---|
506 | LP->turnseq[5] = 6; |
---|
507 | LP->tclim = (unsigned char) (((real) degs) / 2 / 12); |
---|
508 | } |
---|
509 | |
---|
510 | static void |
---|
511 | maininit (void) |
---|
512 | { |
---|
513 | if (!instring) |
---|
514 | { |
---|
515 | int n = random1 (sizeof (sampleStrings) / sizeof (sampleStrings[0])); |
---|
516 | instring = sampleStrings[n].str; |
---|
517 | speed = sampleStrings[n].speed; |
---|
518 | } |
---|
519 | boxh = 10; |
---|
520 | boxw = 10; |
---|
521 | gridden = 0; |
---|
522 | bordcorn = 0; |
---|
523 | threads = 4; |
---|
524 | curviness = 30; |
---|
525 | bordcol = 1; |
---|
526 | ogd = 8; |
---|
527 | ch = '\0'; |
---|
528 | erasing = True; |
---|
529 | { |
---|
530 | unsigned char thr; |
---|
531 | for (thr = 1; thr <= thrmax; thr++) |
---|
532 | { |
---|
533 | firstinit (thr); |
---|
534 | newonscreen (thr); |
---|
535 | } |
---|
536 | } |
---|
537 | { |
---|
538 | int d; |
---|
539 | for (d = degs - 1; d >= 0; d--) |
---|
540 | { |
---|
541 | sinof[d] = sin (d * dtor); |
---|
542 | cosof[d] = cos (d * dtor); |
---|
543 | if (d % degs4 == 0) |
---|
544 | tanof[d] = tanof[d + 1]; |
---|
545 | else |
---|
546 | tanof[d] = tan (d * dtor); |
---|
547 | } |
---|
548 | } |
---|
549 | randpal (); |
---|
550 | } |
---|
551 | |
---|
552 | static Bool |
---|
553 | move (unsigned char thr) |
---|
554 | { |
---|
555 | linedata *LP = &thread[thr - 1]; |
---|
556 | if (LP->dead) |
---|
557 | return (False); |
---|
558 | if (LP->prey == 0) |
---|
559 | switch (LP->tmode) |
---|
560 | { |
---|
561 | case 1: |
---|
562 | LP->deg += random1 (2 * LP->turnsize + 1) - LP->turnsize; |
---|
563 | break; |
---|
564 | case 2: |
---|
565 | if (LP->slice == degs || LP->slice == degs2 || LP->slice == degs4) |
---|
566 | { |
---|
567 | if (LP->orichar == 'D') |
---|
568 | { |
---|
569 | if (LP->deg % degs4 != degs8) |
---|
570 | LP->deg = degs4 * random1 (4) + degs8; |
---|
571 | } |
---|
572 | else if (LP->orichar == 'V') |
---|
573 | if (LP->deg % degs4 != 0) |
---|
574 | LP->deg = degs4 * random1 (4); |
---|
575 | } |
---|
576 | if (random1 (100) == 0) |
---|
577 | { |
---|
578 | if (LP->slice == 0) |
---|
579 | LP->deg = LP->deg - degs4 + random1 (degs2); |
---|
580 | else |
---|
581 | LP->deg += (random1 (2) * 2 - 1) * LP->slice; |
---|
582 | } |
---|
583 | break; |
---|
584 | case 3: |
---|
585 | LP->deg += LP->circturn; |
---|
586 | break; |
---|
587 | case 4: |
---|
588 | if (abs (LP->spiturn) > 11) |
---|
589 | LP->spiturn = 5; |
---|
590 | else |
---|
591 | LP->deg += LP->spiturn; |
---|
592 | if (random1 (15 - abs (LP->spiturn)) == 0) |
---|
593 | { |
---|
594 | LP->spiturn += LP->ctinc; |
---|
595 | if (abs (LP->spiturn) > 10) |
---|
596 | LP->ctinc *= -1; |
---|
597 | } |
---|
598 | break; |
---|
599 | case 5: |
---|
600 | LP->turnco = abs (LP->turnco) - 1; |
---|
601 | if (LP->turnco == 0) |
---|
602 | { |
---|
603 | LP->turnco = curviness + random1 (10); |
---|
604 | LP->circturn *= -1; |
---|
605 | } |
---|
606 | LP->deg += LP->circturn; |
---|
607 | break; |
---|
608 | case 6: |
---|
609 | if (abs (LP->turnco) == 1) |
---|
610 | LP->turnco *= -1 * (random1 (degs2 / abs (LP->circturn)) + 5); |
---|
611 | else if (LP->turnco == 0) |
---|
612 | LP->turnco = 2; |
---|
613 | else if (LP->turnco > 0) |
---|
614 | { |
---|
615 | LP->turnco--; |
---|
616 | LP->deg += LP->circturn; |
---|
617 | } |
---|
618 | else |
---|
619 | LP->turnco++; |
---|
620 | break; |
---|
621 | case 7: |
---|
622 | LP->turnco++; |
---|
623 | if (LP->turnco > LP->tclim) |
---|
624 | { |
---|
625 | LP->turnco = 1; |
---|
626 | LP->tsc = (LP->tsc % LP->tslen) + 1; |
---|
627 | } |
---|
628 | LP->deg += LP->turnseq[LP->tsc - 1]; |
---|
629 | break; |
---|
630 | } |
---|
631 | else |
---|
632 | { |
---|
633 | int desdeg; |
---|
634 | real dy, dx; |
---|
635 | if (LP->tailfollow || LP->prey == thr) |
---|
636 | { |
---|
637 | dx = thread[LP->prey - 1].xrec[thread[LP->prey - 1].recpos] - LP->x; |
---|
638 | dy = thread[LP->prey - 1].yrec[thread[LP->prey - 1].recpos] - LP->y; |
---|
639 | } |
---|
640 | else |
---|
641 | { |
---|
642 | dx = thread[LP->prey - 1].x - LP->x; |
---|
643 | dy = thread[LP->prey - 1].y - LP->y; |
---|
644 | } |
---|
645 | desdeg = |
---|
646 | (LP->vhfollow) ? |
---|
647 | ((fabs (dx) > fabs (dy)) ? |
---|
648 | ((dx > 0) ? |
---|
649 | 0 * degs4 |
---|
650 | : |
---|
651 | 2 * degs4) |
---|
652 | : |
---|
653 | ((dy > 0) ? |
---|
654 | 1 * degs4 |
---|
655 | : |
---|
656 | 3 * degs4)) |
---|
657 | : |
---|
658 | ((dx > 0) ? |
---|
659 | ((dy > 0) ? |
---|
660 | 1 * degs8 : 7 * degs8) : ((dy > 0) ? 3 * degs8 : 5 * degs8)); |
---|
661 | if (desdeg - desdeg % degs4 != LP->deg - LP->deg % degs4 |
---|
662 | || LP->vhfollow) |
---|
663 | { |
---|
664 | if (!LP->vhfollow) |
---|
665 | { |
---|
666 | /* Using atan2 here doesn't seem to slow things down: */ |
---|
667 | desdeg = atan2 (dy, dx) / dtor; |
---|
668 | wraparound (desdeg, 0, degs); |
---|
669 | } |
---|
670 | if (abs (desdeg - LP->deg) <= abs (LP->circturn)) |
---|
671 | LP->deg = desdeg; |
---|
672 | else |
---|
673 | LP->deg += |
---|
674 | (desdeg > LP->deg) ? |
---|
675 | ((desdeg - LP->deg > degs2) ? |
---|
676 | -abs (LP->circturn) : abs (LP->circturn)) |
---|
677 | : ((LP->deg - desdeg > degs2) ? |
---|
678 | abs (LP->circturn) : -abs (LP->circturn)); |
---|
679 | } |
---|
680 | else |
---|
681 | LP->deg += |
---|
682 | (tanof[LP->deg] > |
---|
683 | dy / dx) ? -abs (LP->circturn) : abs (LP->circturn); |
---|
684 | } |
---|
685 | |
---|
686 | wraparound (LP->deg, 0, degs); |
---|
687 | { |
---|
688 | unsigned char oldcol; |
---|
689 | real oldy = LP->y, oldx = LP->x; |
---|
690 | LP->x += cosof[LP->deg]; |
---|
691 | wraparound (LP->x, xmin, xmax + 1); |
---|
692 | LP->y += sinof[LP->deg]; |
---|
693 | wraparound (LP->y, ymin, ymax + 1); |
---|
694 | #define xi ((int) LP->x) |
---|
695 | #define yi ((int) LP->y) |
---|
696 | |
---|
697 | oldcol = gp (xi, yi); |
---|
698 | if (oldcol != 0) |
---|
699 | { |
---|
700 | Bool vertwall = False, horiwall = False; |
---|
701 | if (oldcol == 1 && ((LP->killwalls && gridden > 0) || LP->realbounce)) |
---|
702 | { |
---|
703 | vertwall = (gp (xi, (int) oldy) == 1); |
---|
704 | horiwall = (gp ((int) oldx, yi) == 1); |
---|
705 | } |
---|
706 | if (oldcol == 1 && LP->realbounce && (vertwall || horiwall)) |
---|
707 | { |
---|
708 | if (vertwall) |
---|
709 | LP->deg = -LP->deg + degs2; |
---|
710 | else |
---|
711 | LP->deg = -LP->deg; |
---|
712 | } |
---|
713 | else |
---|
714 | { |
---|
715 | if ((oldcol != LP->col && LP->realbounce) |
---|
716 | || (oldcol == LP->col && LP->selfbounce)) |
---|
717 | LP->deg += degs4 * (random1 (2) * 2 - 1); |
---|
718 | else if (oldcol != LP->col) |
---|
719 | LP->deg += degs2; |
---|
720 | } |
---|
721 | if (LP->killwalls && gridden > 0 && oldcol == 1) |
---|
722 | { |
---|
723 | if (vertwall && xi + 1 <= xmax) |
---|
724 | { |
---|
725 | int yy; |
---|
726 | for (yy = yi - yi % boxh; |
---|
727 | yy <= yi - yi % boxh + boxh && yy <= ymax; yy++) |
---|
728 | if (gp (xi + 1, yy) != 1 || yy == ymax) |
---|
729 | sp (xi, yy, 0); |
---|
730 | } |
---|
731 | if (horiwall && yi + 1 <= ymax) |
---|
732 | { |
---|
733 | int xx; |
---|
734 | for (xx = xi - xi % boxw; |
---|
735 | xx <= xi - xi % boxw + boxw && xx <= xmax; xx++) |
---|
736 | if (gp (xx, yi + 1) != 1 || xx == xmax) |
---|
737 | sp (xx, yi, 0); |
---|
738 | } |
---|
739 | } |
---|
740 | if (oldcol != LP->col || LP->selfbounce) |
---|
741 | { |
---|
742 | LP->x = oldx; |
---|
743 | LP->y = oldy; |
---|
744 | } |
---|
745 | wraparound (LP->deg, 0, degs); |
---|
746 | } |
---|
747 | } |
---|
748 | |
---|
749 | sp (xi, yi, LP->col); |
---|
750 | if (LP->filled) |
---|
751 | { |
---|
752 | if (erasing) |
---|
753 | sp (LP->xrec[LP->recpos], LP->yrec[LP->recpos], 0); |
---|
754 | else |
---|
755 | sp (LP->xrec[LP->recpos], LP->yrec[LP->recpos], LP->col + thrmax); |
---|
756 | } |
---|
757 | LP->yrec[LP->recpos] = yi; |
---|
758 | LP->xrec[LP->recpos] = xi; |
---|
759 | if (LP->recpos == LP->reclen - 1) |
---|
760 | LP->filled = True; |
---|
761 | if (LP->filled && !erasing) |
---|
762 | { |
---|
763 | int co = LP->recpos; |
---|
764 | LP->dead = True; |
---|
765 | do |
---|
766 | { |
---|
767 | int nextco = co + 1; |
---|
768 | wraparound (nextco, 0, LP->reclen); |
---|
769 | if (LP->yrec[co] != LP->yrec[nextco] |
---|
770 | || LP->xrec[co] != LP->xrec[nextco]) |
---|
771 | LP->dead = False; |
---|
772 | co = nextco; |
---|
773 | } |
---|
774 | while (!(!LP->dead || co == LP->recpos)); |
---|
775 | } |
---|
776 | LP->recpos++; |
---|
777 | wraparound (LP->recpos, 0, LP->reclen); |
---|
778 | return (!LP->dead); |
---|
779 | } |
---|
780 | |
---|
781 | static void |
---|
782 | vermiculate_main (void) |
---|
783 | { |
---|
784 | int had_instring = (instring != 0); |
---|
785 | int tick = 0; |
---|
786 | Bool halted = False, autopal = False, cleared; |
---|
787 | point = (unsigned char *) malloc (wid * hei); |
---|
788 | maininit (); |
---|
789 | palupdate (True); |
---|
790 | |
---|
791 | do |
---|
792 | { |
---|
793 | clearscreen (); |
---|
794 | { |
---|
795 | unsigned char thr; |
---|
796 | for (thr = 1; thr <= threads; thr++) |
---|
797 | newonscreen (thr); |
---|
798 | } |
---|
799 | if (autopal) |
---|
800 | { |
---|
801 | randpal (); |
---|
802 | palupdate (False); |
---|
803 | } |
---|
804 | bordupdate (); |
---|
805 | gridupdate (False); |
---|
806 | cleared = False; |
---|
807 | do |
---|
808 | { |
---|
809 | while (wasakeypressed ()) |
---|
810 | { |
---|
811 | ch = readkey (); |
---|
812 | switch (ch) |
---|
813 | { |
---|
814 | case 'M': |
---|
815 | ch = readkey (); |
---|
816 | switch (ch) |
---|
817 | { |
---|
818 | case 'A': |
---|
819 | case 'N': |
---|
820 | { |
---|
821 | unsigned char othreads = threads; |
---|
822 | if (ch == 'N') |
---|
823 | threads = 0; |
---|
824 | do |
---|
825 | { |
---|
826 | ch = readkey (); |
---|
827 | switch (ch) |
---|
828 | { |
---|
829 | case '1': case '2': case '3': |
---|
830 | case '4': case '5': case '6': |
---|
831 | case '7': case '8': case '9': |
---|
832 | thread[++threads - 1].tmode = ch - '0'; |
---|
833 | break; |
---|
834 | case 'R': |
---|
835 | thread[++threads - 1].tmode = |
---|
836 | random1 (tmodes - '0') + 1; |
---|
837 | break; |
---|
838 | } |
---|
839 | } |
---|
840 | while (!(ch == '\15' || ch == '#' |
---|
841 | || threads == thrmax)); |
---|
842 | if (threads == 0) |
---|
843 | threads = othreads; |
---|
844 | cleared = True; |
---|
845 | } |
---|
846 | break; |
---|
847 | } |
---|
848 | break; |
---|
849 | case 'C': |
---|
850 | pickbank (); |
---|
851 | if (bankt > 0) |
---|
852 | { |
---|
853 | ch = readkey (); |
---|
854 | switch (ch) |
---|
855 | { |
---|
856 | case 'D': |
---|
857 | ch = readkey (); |
---|
858 | switch (ch) |
---|
859 | { |
---|
860 | case '1': case '2': case '3': |
---|
861 | case '4': case '5': case '6': |
---|
862 | case '7': case '8': case '9': |
---|
863 | /* Careful! The following macro needs to be at the beginning of any |
---|
864 | block in which it's invoked, since it declares variables: */ |
---|
865 | #define forallinbank(LDP) linedata *LDP; int bankc; \ |
---|
866 | for (bankc = 1; \ |
---|
867 | (LDP = &thread[bank[bankc - 1] - 1], \ |
---|
868 | bankc <= bankt); bankc++) |
---|
869 | { |
---|
870 | forallinbank (L) L->slice = degs / (ch - '0'); |
---|
871 | } |
---|
872 | break; |
---|
873 | case 'M': |
---|
874 | { |
---|
875 | forallinbank (L) L->slice = 0; |
---|
876 | } |
---|
877 | break; |
---|
878 | } |
---|
879 | break; |
---|
880 | case 'S': |
---|
881 | { |
---|
882 | forallinbank (L) |
---|
883 | { |
---|
884 | L->otslen = L->tslen; |
---|
885 | L->tslen = 0; |
---|
886 | } |
---|
887 | } |
---|
888 | do |
---|
889 | { |
---|
890 | char oldch = ch; |
---|
891 | ch = readkey (); |
---|
892 | { |
---|
893 | forallinbank (L) |
---|
894 | { |
---|
895 | switch (ch) |
---|
896 | { |
---|
897 | case '0': |
---|
898 | case '1': case '2': case '3': |
---|
899 | case '4': case '5': case '6': |
---|
900 | case '7': case '8': case '9': |
---|
901 | L->tslen++; |
---|
902 | L->turnseq[L->tslen - 1] = ch - '0'; |
---|
903 | if (oldch == '-') |
---|
904 | L->turnseq[L->tslen - 1] *= -1; |
---|
905 | if (bankc % 2 == 0) |
---|
906 | L->turnseq[L->tslen - 1] *= -1; |
---|
907 | break; |
---|
908 | } |
---|
909 | } |
---|
910 | } |
---|
911 | } |
---|
912 | while (!(ch == '\15' || ch == '#' |
---|
913 | || thread[bank[0] - 1].tslen == 50)); |
---|
914 | { |
---|
915 | forallinbank (L) |
---|
916 | { |
---|
917 | int seqSum = 0, c; |
---|
918 | |
---|
919 | if (L->tslen == 0) |
---|
920 | L->tslen = L->otslen; |
---|
921 | for (c = 1; c <= L->tslen; c++) |
---|
922 | seqSum += L->turnseq[c - 1]; |
---|
923 | if (seqSum == 0) |
---|
924 | L->tclim = 1; |
---|
925 | else |
---|
926 | L->tclim = |
---|
927 | (int) (((real) degs2) / abs (seqSum)); |
---|
928 | L->tsc = random1 (L->tslen) + 1; |
---|
929 | } |
---|
930 | } |
---|
931 | break; |
---|
932 | case 'T': |
---|
933 | { |
---|
934 | ch = readkey (); |
---|
935 | { |
---|
936 | forallinbank (L) |
---|
937 | { |
---|
938 | switch (ch) |
---|
939 | { |
---|
940 | case '1': case '2': case '3': |
---|
941 | case '4': case '5': case '6': |
---|
942 | case '7': case '8': case '9': |
---|
943 | L->tmode = ch - '0'; |
---|
944 | break; |
---|
945 | case 'R': |
---|
946 | L->tmode = random1 (tmodes - '0') + 1; |
---|
947 | break; |
---|
948 | } |
---|
949 | } |
---|
950 | } |
---|
951 | } |
---|
952 | break; |
---|
953 | case 'O': |
---|
954 | ch = readkey (); |
---|
955 | { |
---|
956 | forallinbank (L) L->orichar = ch; |
---|
957 | } |
---|
958 | break; |
---|
959 | case 'F': |
---|
960 | { |
---|
961 | banktype fbank; |
---|
962 | arrcpy (fbank, bank); |
---|
963 | { |
---|
964 | int fbankt = bankt; |
---|
965 | int bankc; |
---|
966 | pickbank (); |
---|
967 | for (bankc = 1; bankc <= fbankt; bankc++) |
---|
968 | { |
---|
969 | linedata *L = &thread[fbank[bankc - 1] - 1]; |
---|
970 | if (ch == 'N') |
---|
971 | L->prey = 0; |
---|
972 | else |
---|
973 | L->prey = bank[0 + (bankc - 1) % bankt]; |
---|
974 | } |
---|
975 | } |
---|
976 | } |
---|
977 | break; |
---|
978 | case 'L': |
---|
979 | { |
---|
980 | forallinbank (L) L->prey = bank[bankc % bankt]; |
---|
981 | } |
---|
982 | break; |
---|
983 | case 'R': |
---|
984 | ch = readkey (); |
---|
985 | { |
---|
986 | forallinbank (L) switch (ch) |
---|
987 | { |
---|
988 | case '1': case '2': case '3': |
---|
989 | case '4': case '5': case '6': |
---|
990 | case '7': case '8': case '9': |
---|
991 | L->circturn = 10 - (ch - '0'); |
---|
992 | break; |
---|
993 | case 'R': |
---|
994 | L->circturn = random1 (7) + 1; |
---|
995 | break; |
---|
996 | } |
---|
997 | } |
---|
998 | break; |
---|
999 | } |
---|
1000 | } |
---|
1001 | break; |
---|
1002 | case 'T': |
---|
1003 | case 'Y': |
---|
1004 | case 'N': |
---|
1005 | boolop = ch; |
---|
1006 | pickbank (); |
---|
1007 | if (bankt > 0) |
---|
1008 | { |
---|
1009 | ch = readkey (); |
---|
1010 | { |
---|
1011 | forallinbank (L) |
---|
1012 | { |
---|
1013 | switch (ch) |
---|
1014 | { |
---|
1015 | case 'S': |
---|
1016 | bankmod (&L->selfbounce); |
---|
1017 | break; |
---|
1018 | case 'V': |
---|
1019 | bankmod (&L->vhfollow); |
---|
1020 | break; |
---|
1021 | case 'R': |
---|
1022 | bankmod (&L->realbounce); |
---|
1023 | break; |
---|
1024 | case 'L': |
---|
1025 | bankmod (&L->little); |
---|
1026 | cleared = True; |
---|
1027 | break; |
---|
1028 | case 'T': |
---|
1029 | bankmod (&L->tailfollow); |
---|
1030 | break; |
---|
1031 | case 'K': |
---|
1032 | bankmod (&L->killwalls); |
---|
1033 | break; |
---|
1034 | } |
---|
1035 | } |
---|
1036 | } |
---|
1037 | } |
---|
1038 | break; |
---|
1039 | case 'R': |
---|
1040 | if (bordcol == 1) |
---|
1041 | { |
---|
1042 | bordcol = 0; |
---|
1043 | bordupdate (); |
---|
1044 | bordcorn = (bordcorn + 1) % 4; |
---|
1045 | bordcol = 1; |
---|
1046 | bordupdate (); |
---|
1047 | } |
---|
1048 | break; |
---|
1049 | case '\33': |
---|
1050 | halted = True; |
---|
1051 | break; |
---|
1052 | case '1': case '2': case '3': |
---|
1053 | case '4': case '5': case '6': |
---|
1054 | case '7': case '8': case '9': |
---|
1055 | { |
---|
1056 | int c; |
---|
1057 | for (c = 1; c <= thrmax; c++) |
---|
1058 | thread[c - 1].tmode = ch - '0'; |
---|
1059 | } |
---|
1060 | break; |
---|
1061 | case '\40': |
---|
1062 | cleared = True; |
---|
1063 | break; |
---|
1064 | case 'E': |
---|
1065 | erasing = !erasing; |
---|
1066 | break; |
---|
1067 | case 'P': |
---|
1068 | randpal (); |
---|
1069 | palupdate (True); |
---|
1070 | break; |
---|
1071 | case 'G': |
---|
1072 | { |
---|
1073 | char dimch = 'B'; |
---|
1074 | Bool gridchanged = True; |
---|
1075 | if (gridden == 0) |
---|
1076 | gridden = ogd; |
---|
1077 | do |
---|
1078 | { |
---|
1079 | int msize = 0; |
---|
1080 | if (gridchanged) |
---|
1081 | { |
---|
1082 | clearscreen (); |
---|
1083 | gridupdate (True); |
---|
1084 | } |
---|
1085 | ch = readkey (); |
---|
1086 | gridchanged = True; |
---|
1087 | switch (ch) |
---|
1088 | { |
---|
1089 | case '+': |
---|
1090 | msize = 1; |
---|
1091 | break; |
---|
1092 | case '-': |
---|
1093 | msize = -1; |
---|
1094 | break; |
---|
1095 | case ']': |
---|
1096 | if (gridden < 15) |
---|
1097 | gridden++; |
---|
1098 | break; |
---|
1099 | case '[': |
---|
1100 | if (gridden > 0) |
---|
1101 | gridden--; |
---|
1102 | break; |
---|
1103 | case 'O': |
---|
1104 | ogd = gridden; |
---|
1105 | gridden = 0; |
---|
1106 | break; |
---|
1107 | case 'S': |
---|
1108 | boxw = boxh; |
---|
1109 | case 'W': |
---|
1110 | case 'H': |
---|
1111 | case 'B': |
---|
1112 | dimch = ch; |
---|
1113 | break; |
---|
1114 | default: |
---|
1115 | gridchanged = False; |
---|
1116 | } |
---|
1117 | if (dimch == 'W' || dimch == 'B') |
---|
1118 | boxw += msize; |
---|
1119 | if (dimch == 'H' || dimch == 'B') |
---|
1120 | boxh += msize; |
---|
1121 | if (boxw == 0) |
---|
1122 | boxw = 1; |
---|
1123 | if (boxh == 0) |
---|
1124 | boxh = 1; |
---|
1125 | } |
---|
1126 | while (!(ch == '\15' || ch == '#' || ch == 'O')); |
---|
1127 | cleared = True; |
---|
1128 | } |
---|
1129 | break; |
---|
1130 | case 'A': |
---|
1131 | autopal = !autopal; |
---|
1132 | break; |
---|
1133 | case 'B': |
---|
1134 | bordcol = 1 - bordcol; |
---|
1135 | bordupdate (); |
---|
1136 | break; |
---|
1137 | case '-': |
---|
1138 | speed -= SPEEDINC; |
---|
1139 | if (speed < 1) |
---|
1140 | speed = 1; |
---|
1141 | break; |
---|
1142 | case '+': |
---|
1143 | speed += SPEEDINC; |
---|
1144 | if (speed > SPEEDMAX) |
---|
1145 | speed = SPEEDMAX; |
---|
1146 | break; |
---|
1147 | case '/': |
---|
1148 | if (curviness > 5) |
---|
1149 | curviness -= 5; |
---|
1150 | break; |
---|
1151 | case '*': |
---|
1152 | if (curviness < 50) |
---|
1153 | curviness += 5; |
---|
1154 | break; |
---|
1155 | case ']': |
---|
1156 | if (threads < thrmax) |
---|
1157 | newonscreen (++threads); |
---|
1158 | break; |
---|
1159 | case '[': |
---|
1160 | if (threads > 1) |
---|
1161 | { |
---|
1162 | linedata *L = &thread[threads - 1]; |
---|
1163 | int lastpos = (L->filled) ? L->reclen - 1 : L->recpos; |
---|
1164 | int c; |
---|
1165 | for (c = 0; c <= lastpos; c++) |
---|
1166 | sp (L->xrec[c], L->yrec[c], 0); |
---|
1167 | threads--; |
---|
1168 | } |
---|
1169 | break; |
---|
1170 | } |
---|
1171 | } |
---|
1172 | |
---|
1173 | #ifdef VERMICULATE_STANDALONE |
---|
1174 | { |
---|
1175 | XEvent xe; |
---|
1176 | while (XCheckWindowEvent |
---|
1177 | (mydpy, mywindow, StructureNotifyMask | ExposureMask, &xe)) |
---|
1178 | switch (xe.type) |
---|
1179 | { |
---|
1180 | case ConfigureNotify: |
---|
1181 | wid = xe.xconfigure.width; |
---|
1182 | hei = xe.xconfigure.height; |
---|
1183 | free (point); |
---|
1184 | point = (unsigned char *) malloc (wid * hei); |
---|
1185 | cleared = True; |
---|
1186 | break; |
---|
1187 | case Expose: |
---|
1188 | if (!cleared) |
---|
1189 | redraw (xe.xexpose.x, |
---|
1190 | xe.xexpose.y, xe.xexpose.width, |
---|
1191 | xe.xexpose.height); |
---|
1192 | break; |
---|
1193 | } |
---|
1194 | } |
---|
1195 | #else |
---|
1196 | screenhack_handle_events (mydpy); |
---|
1197 | #endif /* VERMICULATE_STANDALONE */ |
---|
1198 | |
---|
1199 | if (!cleared) |
---|
1200 | { |
---|
1201 | Bool alltrap = True; |
---|
1202 | unsigned char thr; |
---|
1203 | for (thr = 1; thr <= threads; thr++) |
---|
1204 | if (move (thr)) |
---|
1205 | alltrap = False; |
---|
1206 | if (alltrap) /* all threads are trapped */ |
---|
1207 | cleared = True; |
---|
1208 | if (speed != SPEEDMAX) |
---|
1209 | waitabit (); |
---|
1210 | } |
---|
1211 | |
---|
1212 | if (tick++ > max_ticks && !had_instring) |
---|
1213 | { |
---|
1214 | tick = 0; |
---|
1215 | instring = 0; |
---|
1216 | maininit(); |
---|
1217 | cleared = True; |
---|
1218 | autopal = False; |
---|
1219 | } |
---|
1220 | } |
---|
1221 | while (!(halted || cleared)); |
---|
1222 | } |
---|
1223 | while (!halted); |
---|
1224 | } |
---|
1225 | |
---|
1226 | void |
---|
1227 | commonXinit (void) |
---|
1228 | { |
---|
1229 | XSetWindowBackground (mydpy, mywindow, |
---|
1230 | BlackPixel (mydpy, DefaultScreen (mydpy))); |
---|
1231 | { |
---|
1232 | XGetWindowAttributes (mydpy, mywindow, &xgwa); |
---|
1233 | wid = xgwa.width; |
---|
1234 | hei = xgwa.height; |
---|
1235 | mycmap = xgwa.colormap; |
---|
1236 | } |
---|
1237 | { |
---|
1238 | XGCValues mygcv; |
---|
1239 | XGetGCValues (mydpy, XDefaultGC (mydpy, XDefaultScreen (mydpy)), |
---|
1240 | GCForeground, &mygcv); |
---|
1241 | mygc = XCreateGC (mydpy, mywindow, GCForeground, &mygcv); |
---|
1242 | } |
---|
1243 | } |
---|
1244 | |
---|
1245 | #ifdef VERMICULATE_STANDALONE |
---|
1246 | /* Function Name: GetVRoot (slightly changed from the X Windows FAQ) |
---|
1247 | * Description: Gets the root window, even if it's a virtual root |
---|
1248 | * Arguments: the display and the screen |
---|
1249 | * Returns: the root window for the client |
---|
1250 | */ |
---|
1251 | static Window |
---|
1252 | GetVRoot (Display * dpy, int scr) |
---|
1253 | { |
---|
1254 | Window rootReturn, parentReturn, *children; |
---|
1255 | unsigned int numChildren; |
---|
1256 | Window root = RootWindow (dpy, scr); |
---|
1257 | Atom __SWM_VROOT = None; |
---|
1258 | int i; |
---|
1259 | |
---|
1260 | __SWM_VROOT = XInternAtom (dpy, "__SWM_VROOT", False); |
---|
1261 | XQueryTree (dpy, root, &rootReturn, &parentReturn, &children, &numChildren); |
---|
1262 | for (i = 0; i < numChildren; i++) |
---|
1263 | { |
---|
1264 | Atom actual_type; |
---|
1265 | int actual_format; |
---|
1266 | unsigned long int nitems, bytesafter; |
---|
1267 | Window *newRoot = NULL; |
---|
1268 | |
---|
1269 | if (XGetWindowProperty (dpy, children[i], __SWM_VROOT, 0, 1, |
---|
1270 | False, XA_WINDOW, &actual_type, &actual_format, |
---|
1271 | &nitems, &bytesafter, |
---|
1272 | (unsigned char **) &newRoot) == Success |
---|
1273 | && newRoot) |
---|
1274 | { |
---|
1275 | root = *newRoot; |
---|
1276 | break; |
---|
1277 | } |
---|
1278 | } |
---|
1279 | |
---|
1280 | XFree ((char *) children); |
---|
1281 | return root; |
---|
1282 | } |
---|
1283 | |
---|
1284 | int |
---|
1285 | main (int argc, char **argv) |
---|
1286 | { |
---|
1287 | int argnum; |
---|
1288 | if ((mydpy = XOpenDisplay (NULL)) == NULL) |
---|
1289 | { |
---|
1290 | fprintf (stderr, "%s: cannot connect to X server %s\n", argv[0], |
---|
1291 | XDisplayName (NULL)); |
---|
1292 | exit (1); |
---|
1293 | } |
---|
1294 | |
---|
1295 | for (argnum = 1; argnum < argc; argnum++) |
---|
1296 | { |
---|
1297 | if (!strcmp (argv[argnum], "-geometry")) |
---|
1298 | { |
---|
1299 | int x, y; |
---|
1300 | unsigned int uh, uw; |
---|
1301 | XParseGeometry (argv[++argnum], &x, &y, &uw, &uh); |
---|
1302 | hei = (int) uh; |
---|
1303 | wid = (int) uw; |
---|
1304 | } |
---|
1305 | else if (!strcmp (argv[argnum], "-instring")) |
---|
1306 | instring = argv[++argnum]; |
---|
1307 | else if (!strcmp (argv[argnum], "-root")) |
---|
1308 | use_root = True; |
---|
1309 | else if (!strcmp (argv[argnum], "-speed")) |
---|
1310 | speed = atoi (argv[++argnum]); |
---|
1311 | else |
---|
1312 | { |
---|
1313 | fprintf (stderr, |
---|
1314 | "\nvermiculate options are:" |
---|
1315 | "\n -speed NUMBER: set speed, can be from 1 to %d." |
---|
1316 | "\n -root: use root window." |
---|
1317 | "\n -instring STRING: put STRING in kbd buffer." |
---|
1318 | "\n -geometry WIDTHxHEIGHT \n", SPEEDMAX); |
---|
1319 | exit (1); |
---|
1320 | } |
---|
1321 | } |
---|
1322 | |
---|
1323 | if (use_root) |
---|
1324 | mywindow = GetVRoot (mydpy, DefaultScreen (mydpy)); |
---|
1325 | else |
---|
1326 | mywindow = XCreateSimpleWindow (mydpy, DefaultRootWindow (mydpy), 0, 0, |
---|
1327 | wid, hei, 0, 0, BlackPixel (mydpy, |
---|
1328 | DefaultScreen |
---|
1329 | (mydpy))); |
---|
1330 | XStoreName (mydpy, mywindow, "vermiculate"); |
---|
1331 | XMapWindow (mydpy, mywindow); |
---|
1332 | commonXinit (); |
---|
1333 | XSelectInput (mydpy, mywindow, |
---|
1334 | KeyPressMask | ExposureMask | StructureNotifyMask); |
---|
1335 | |
---|
1336 | #undef ya_rand_init |
---|
1337 | ya_rand_init (0); |
---|
1338 | |
---|
1339 | vermiculate_main (); |
---|
1340 | return 0; |
---|
1341 | } |
---|
1342 | |
---|
1343 | #else |
---|
1344 | |
---|
1345 | void |
---|
1346 | screenhack (Display * d, Window w) |
---|
1347 | { |
---|
1348 | mydpy = d; |
---|
1349 | mywindow = w; |
---|
1350 | instring = get_string_resource ("instring", "Instring"); |
---|
1351 | max_ticks = get_integer_resource ("ticks", "Integer"); |
---|
1352 | { |
---|
1353 | int temp = get_integer_resource ("speed", "Speed"); |
---|
1354 | if (temp != 0) |
---|
1355 | speed = temp; |
---|
1356 | } |
---|
1357 | commonXinit (); |
---|
1358 | mycolors[0].pixel = BlackPixel (mydpy, DefaultScreen (mydpy)); |
---|
1359 | vermiculate_main (); |
---|
1360 | } |
---|
1361 | #endif /* VERMICULATE_STANDALONE */ |
---|