1 /* -*- Mode: C; tab-width: 4 -*- */
2 /* kumppa ---  */
3 
4 #if 0
5 static const char sccsid[] = "@(#)kumppa.c	5.00 2000/11/01 xlockmore";
6 
7 #endif
8 
9 /*-
10    Copyright (C) Teemu Suutari (temisu@utu.fi) Feb 1998
11 
12    Permission is hereby granted, free of charge, to any person obtaining
13    a copy of this software and associated documentation files (the
14    "Software"), to deal in the Software without restriction, including
15    without limitation the rights to use, copy, modify, merge, publish,
16    distribute, sublicense, and/or sell copies of the Software, and to
17    permit persons to whom the Software is furnished to do so, subject to
18    the following conditions:
19 
20    The above copyright notice and this permission notice shall be included
21    in all copies or substantial portions of the Software.
22 
23    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
26    IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
27    OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
28    ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
29    OTHER DEALINGS IN THE SOFTWARE.
30 
31    Except as contained in this notice, the name of the X Consortium shall
32    not be used in advertising or otherwise to promote the sale, use or
33    other dealings in this Software without prior written authorization
34    from the X Consortium.
35 
36    * Revision History:
37    * 01-Nov-2000: Allocation checks
38    * 16-Jul-1998: xlockmore version by Jouk Jansen <joukj AT hrem.nano.tudelft.nl>
39    * Feb 1998 : original xscreensaver version by Teemu Suutari <temisu@utu.fi>
40  */
41 
42 /*-
43    *** This is contest-version. Don't look any further, code is *very* ugly.
44  */
45 
46 
47 #if 0
48 /* commented out since xlockmore does not support (yet) double buffering */
49 #ifdef HAVE_XDBE_EXTENSION
50 #include <X11/extensions/Xdbe.h>
51 #endif /* HAVE_XDBE_EXTENSION */
52 #endif
53 
54 #ifdef STANDALONE
55 #define MODE_kumppa
56 #define DEFAULTS "*delay: 0 \n" \
57 	"*cycles: 1000 \n" \
58 	".background: black\n" \
59 
60 # define free_kumppa 0
61 # define reshape_kumppa 0
62 # define kumppa_handle_event 0
63 #include "xlockmore.h"		/* in xscreensaver distribution */
64 #else /* STANDALONE */
65 #include "xlock.h"		/* in xlockmore distribution */
66 
67 #endif /* STANDALONE */
68 
69 #ifdef MODE_kumppa
70 
71 #define DEF_COSILINES "True"
72 #define DEF_SPEED "0.1"
73 
74 #if 0
75 #ifdef HAVE_XDBE_EXTENSION
76 #define DEF_USEDOUBLE "False"
77 
78 static Bool usedouble;
79 
80 #endif /* HAVE_XDBE_EXTENSION */
81 #endif
82 
83 static Bool cosilines;
84 static float speed;
85 
86 static XrmOptionDescRec opts[] =
87 {
88 	{(char *) "-speed", (char *) ".kumppa.speed", XrmoptionSepArg, (caddr_t) NULL},
89 #if 0
90 #ifdef HAVE_XDBE_EXTENSION
91 	{(char *) "-dbuf", (char *) ".kumppa.dbuf", XrmoptionNoArg, (caddr_t) "on"},
92 	{(char *) "+dbuf", (char *) ".kumppa.dbuf", XrmoptionNoArg, (caddr_t) "off"},
93 #endif				/* HAVE_XDBE_EXTENSION */
94 #endif
95 	{(char *) "-rrandom", (char *) ".kumppa.rrandom", XrmoptionNoArg, (caddr_t) "on"},
96 	{(char *) "+rrandom", (char *) ".kumppa.rrandom", XrmoptionNoArg, (caddr_t) "off"}
97 };
98 
99 static argtype vars[] =
100 {
101 	{(void *) & speed, (char *) "speed", (char *) "speed", (char *) DEF_SPEED, t_Float},
102 #if 0
103 #ifdef HAVE_XDBE_EXTENSION
104 	{(void *) & usedouble, (char *) "dbuf", (char *) "dbuf", (char *) DEF_USEDOUBLE, t_Bool},
105 #endif				/* HAVE_XDBE_EXTENSION */
106 #endif
107 	{(void *) & cosilines, (char *) "rrandom", (char *) "rrandom", (char *) DEF_COSILINES, t_Bool}
108 };
109 static OptionStruct desc[] =
110 {
111 	{(char *) "-speed num", (char *) "Speed"},
112 #if 0
113 #ifdef HAVE_XDBE_EXTENSION
114 	{(char *) "-/+dbuf", (char *) "turn on/off double buffering"},
115 #endif				/* HAVE_XDBE_EXTENSION */
116 #endif
117 	{(char *) "-/+rrandom", (char *) "turn on/off random"}
118 };
119 
120 ENTRYPOINT ModeSpecOpt kumppa_opts =
121 {sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc};
122 
123 #ifdef USE_MODULES
124 ModStruct   kumppa_description =
125 {"kumppa", "init_kumppa", "draw_kumppa", "release_kumppa",
126  "init_kumppa", "init_kumppa", (char *) NULL, &kumppa_opts,
127  10000, 1, 1000, 1, 64, 1.0, "",
128  "Shows Kumppa", 0, NULL};
129 
130 #endif
131 
132 static const unsigned char colors[96] =
133 {0, 0, 255, 0, 51, 255, 0, 102, 255, 0, 153, 255, 0, 204, 255,
134  0, 255, 255, 0, 255, 204, 0, 255, 153, 0, 255, 102, 0, 255, 51,
135  0, 255, 0, 51, 255, 0, 102, 255, 0, 153, 255, 0, 204, 255, 0,
136  255, 255, 0, 255, 204, 0, 255, 153, 0, 255, 102, 0, 255, 51, 0,
137  255, 0, 0, 255, 0, 51, 255, 0, 102, 255, 0, 153, 255, 0, 204,
138  255, 0, 255, 219, 0, 255, 182, 0, 255, 146, 0, 255, 109, 0, 255,
139  73, 0, 255, 37, 0, 255};
140 
141 static const float cosinus[8][6] =
142 {
143 	{-0.07, 0.12, -0.06, 32, 25, 37},
144 	{0.08, -0.03, 0.05, 51, 46, 32},
145 	{0.12, 0.07, -0.13, 27, 45, 36},
146 	{0.05, -0.04, -0.07, 36, 27, 39},
147 	{-0.02, -0.07, 0.1, 21, 43, 42},
148 	{-0.11, 0.06, 0.02, 51, 25, 34},
149 	{0.04, -0.15, 0.02, 42, 32, 25},
150 	{-0.02, -0.04, -0.13, 34, 20, 15}};
151 
152 static const float acosinus[24] =
153 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
154 
155 static const int   ocoords[8] =
156 {0, 0, 0, 0, 0, 0, 0, 0};
157 
158 typedef struct {
159 	Colormap    cmap;
160 	float      *acosinus;
161 	unsigned long blackpixel, whitepixel, fg, bg;
162 	int         coords[8];
163 	int         ocoords[8];
164 
165 	GC          fgc[33];
166 	GC          cgc;
167 	int         sizx, sizy;
168 	int         midx, midy;
169 
170 	int        *Xrotations;
171 	int        *Yrotations;
172 	int        *Xrottable;
173 	int        *Yrottable;
174 
175 	int        *rotateX;
176 	int        *rotateY;
177 
178 	int         rotsizeX, rotsizeY;
179 	int         stateX, stateY;
180 	int         dir, time;
181 	int         rx, ry;
182 	int         c;
183 	long        c1;
184 	Bool        cosilines;
185 } kumppastruct;
186 
187 static kumppastruct *kumppas = (kumppastruct *) NULL;
188 
189 
190 
191 static int
Satnum(int maxi)192 Satnum(int maxi)
193 {
194 	return (int) (maxi * ((double) NRAND(2500) / 2500.0));
195 }
196 
197 
198 static void
palaRotate(ModeInfo * mi,int x,int y)199 palaRotate(ModeInfo * mi, int x, int y)
200 {
201 	Display    *display = MI_DISPLAY(mi);
202 	Window      window = MI_WINDOW(mi);
203 	int         ax, ay, bx, by, cx, cy;
204 	kumppastruct *s = &kumppas[MI_SCREEN(mi)];
205 
206 	ax = s->rotateX[x];
207 	ay = s->rotateY[y];
208 	bx = s->rotateX[x + 1] + 2;
209 	by = s->rotateY[y + 1] + 2;
210 	cx = s->rotateX[x] + (x - s->rx) - s->dir * (y - s->ry);
211 	cy = s->rotateY[y] + s->dir * (x - s->rx) + (y - s->ry);
212 	if (cx < 0) {
213 		ax -= cx;
214 		cx = 0;
215 	}
216 	if (cy < 0) {
217 		ay -= cy;
218 		cy = 0;
219 	}
220 	if (cx + bx - ax > s->sizx)
221 		bx = ax - cx + s->sizx;
222 	if (cy + by - ay > s->sizy)
223 		by = ay - cy + s->sizy;
224 	if (ax < bx && ay < by) {
225 		if (MI_IS_INSTALL(mi) && MI_NPIXELS(mi) > 2) {
226 			XCopyArea(display, window, window, s->cgc, ax, ay, bx - ax, by - ay, cx, cy);
227 		} else {
228 			XCopyArea(display, window, window, MI_GC(mi), ax, ay, bx - ax, by - ay, cx, cy);
229 		}
230 	}
231 }
232 
233 
234 static void
rotate(ModeInfo * mi)235 rotate(ModeInfo * mi)
236 {
237 	int         x, y;
238 	int         dx, dy;
239 	kumppastruct *s = &kumppas[MI_SCREEN(mi)];
240 
241 	s->rx = s->Xrottable[s->stateX + 1] - s->Xrottable[s->stateX];
242 	s->ry = s->Yrottable[s->stateX + 1] - s->Yrottable[s->stateY];
243 
244 
245 	for (x = 0; x <= s->rx; x++)
246 		s->rotateX[x] = (x) ? s->midx - 1 - s->Xrotations[s->Xrottable[s->stateX + 1] - x] : 0;
247 	for (x = 0; x <= s->rx; x++)
248 		s->rotateX[x + s->rx + 1] = (x == s->rx) ? s->sizx - 1 : s->midx + s->Xrotations[s->Xrottable[s->stateX] + x];
249 	for (y = 0; y <= s->ry; y++)
250 		s->rotateY[y] = (y) ? s->midy - 1 - s->Yrotations[s->Yrottable[s->stateY + 1] - y] : 0;
251 	for (y = 0; y <= s->ry; y++)
252 		s->rotateY[y + s->ry + 1] = (y == s->ry) ? s->sizy - 1 : s->midy + s->Yrotations[s->Yrottable[s->stateY] + y];
253 
254 	x = (s->rx > s->ry) ? s->rx : s->ry;
255 	for (dy = 0; dy < (x + 1) << 1; dy++)
256 		for (dx = 0; dx < (x + 1) << 1; dx++) {
257 			y = (s->rx > s->ry) ? s->ry - s->rx : 0;
258 			if (dy + y >= 0 && dy < (s->ry + 1) << 1 && dx < (s->rx + 1) << 1)
259 				if (dy + y + dx <= s->ry + s->rx && dy + y - dx <= s->ry - s->rx) {
260 					palaRotate(mi, (s->rx << 1) + 1 - dx, dy + y);
261 					palaRotate(mi, dx, (s->ry << 1) + 1 - dy - y);
262 				}
263 			y = (s->ry > s->rx) ? s->rx - s->ry : 0;
264 			if (dy + y >= 0 && dx < (s->ry + 1) << 1 && dy < (s->rx + 1) << 1)
265 				if (dy + y + dx <= s->ry + s->rx && dx - dy - y >= s->ry - s->rx) {
266 					palaRotate(mi, dy + y, dx);
267 					palaRotate(mi, (s->rx << 1) + 1 - dy - y, (s->ry << 1) + 1 - dx);
268 				}
269 		}
270 	s->stateX++;
271 	if (s->stateX == s->rotsizeX)
272 		s->stateX = 0;
273 	s->stateY++;
274 	if (s->stateY == s->rotsizeY)
275 		s->stateY = 0;
276 }
277 
278 static void
free_kumppa_screen(ModeInfo * mi,kumppastruct * s)279 free_kumppa_screen(ModeInfo *mi, kumppastruct *s)
280 {
281 	Display *display = MI_DISPLAY(mi);
282 
283 	if (s == NULL) {
284 		return;
285 	}
286 	if (MI_IS_INSTALL(mi) && MI_NPIXELS(mi) > 2) {
287 		int i;
288 
289 		MI_WHITE_PIXEL(mi) = s->whitepixel;
290 		MI_BLACK_PIXEL(mi) = s->blackpixel;
291 #ifndef STANDALONE
292 		MI_FG_PIXEL(mi) = s->fg;
293 		MI_BG_PIXEL(mi) = s->bg;
294 #endif
295 		if (s->fgc[32] != None) {
296 			XFreeGC(display, s->fgc[32]);
297 			s->fgc[32] = None;
298 		}
299 #if 0
300 		if (mono_p) {
301 			if (s->fgc[1] != None) {
302 				XFreeGC(display, s->fgc[1]);
303 				s->fgc[1] = None;
304 			}
305 		} else
306 #endif
307 		for (i = 0; i < 32; i++) {
308 			if (s->fgc[i] != None) {
309 				XFreeGC(display, s->fgc[i]);
310 				s->fgc[i] = None;
311 			}
312 		}
313 		if (s->cgc != None) {
314 			XFreeGC(display, s->cgc);
315 			s->cgc = None;
316 		}
317 		if (s->cmap != None) {
318 			XFreeColormap(display, s->cmap);
319 			s->cmap = None;
320 		}
321 	}
322 	if (s->acosinus != NULL) {
323 		free(s->acosinus);
324 		s->acosinus = (float *) NULL;
325 	}
326 	if (s->Xrotations != NULL) {
327 		free(s->Xrotations);
328 		s->Xrotations = (int *) NULL;
329 	}
330 	if (s->Yrotations != NULL) {
331 		free(s->Yrotations);
332 		s->Yrotations = (int *) NULL;
333 	}
334 	if (s->Xrottable != NULL) {
335 		free(s->Xrottable);
336 		s->Xrottable = (int *) NULL;
337 	}
338 	if (s->Yrottable != NULL) {
339 		free(s->Yrottable);
340 		s->Yrottable = (int *) NULL;
341 	}
342 	if (s->rotateX != NULL) {
343 		free(s->rotateX);
344 		s->rotateX = (int *) NULL;
345 	}
346 	if (s->rotateY != NULL) {
347 		free(s->rotateY);
348 		s->rotateY = (int *) NULL;
349 	}
350 	s = NULL;
351 }
352 
353 static void
make_rots(ModeInfo * mi,double xspeed,double yspeed)354 make_rots(ModeInfo * mi, double xspeed, double yspeed)
355 {
356 	int         a, b, c, f, g, j, k = 0, l;
357 	double      m, om, ok;
358 	double      d, ix, iy;
359 	int         maxi;
360 	kumppastruct *s = &kumppas[MI_SCREEN(mi)];
361 
362 	Bool       *chks;
363 
364 	s->rotsizeX = (int) (2 / xspeed + 1);
365 	ix = (double) (s->midx + 1) / (double) (s->rotsizeX);
366 	s->rotsizeY = (int) (2 / yspeed + 1);
367 	iy = (double) (s->midy + 1) / (double) (s->rotsizeY);
368 
369 	if (s->Xrotations != NULL)
370 		free(s->Xrotations);
371 	if (s->Yrotations != NULL)
372 		free(s->Yrotations);
373 	if (s->Xrottable != NULL)
374 		free(s->Xrottable);
375 	if (s->Yrottable != NULL)
376 		free(s->Yrottable);
377 
378 	if (((s->Xrotations = (int *) calloc((s->midx + 2),
379 			sizeof (int))) == NULL) ||
380 	    ((s->Yrotations = (int *) calloc((s->midy + 2),
381 			sizeof (int))) == NULL) ||
382 	    ((s->Xrottable = (int *) malloc((s->rotsizeX + 1) *
383 			sizeof (int))) == NULL) ||
384 	    ((s->Yrottable = (int *) malloc((s->rotsizeY + 1) *
385 			sizeof (int))) == NULL) ||
386 	    ((chks = (Bool *) malloc(((s->midx > s->midy) ? s->midx : s->midy) *
387 			sizeof (Bool))) == NULL)) {
388 		free_kumppa_screen(mi, s);
389 		return;
390 	}
391 
392 
393 	maxi = 0;
394 	c = 0;
395 	d = 0;
396 	g = 0;
397 	for (a = 0; a < s->midx; a++)
398 		chks[a] = True;
399 	for (a = 0; a < s->rotsizeX; a++) {
400 		s->Xrottable[a] = c;
401 		f = (int) (d + ix) - g;		/*viivojen lkm. */
402 		g += f;
403 		if (g > s->midx) {
404 			f -= g - s->midx;
405 			g = s->midx;
406 		}
407 		for (b = 0; b < f; b++) {
408 			m = 0;
409 			for (j = 0; j < s->midx; j++) {		/*testi */
410 				if (chks[j]) {
411 					om = 0;
412 					ok = 1;
413 					l = 0;
414 					while (j + l < s->midx && om + 12 * ok > m) {
415 						if (j - l >= 0) {
416 							if (chks[j - l])
417 								om += ok;
418 						} else if (chks[l - j])
419 							om += ok;
420 						if (chks[j + l])
421 							om += ok;
422 						ok /= 1.5;
423 						l++;
424 					}
425 					if (om >= m) {
426 						k = j;
427 						m = om;
428 					}
429 				}
430 			}
431 			chks[k] = False;
432 			l = c;
433 			while (l >= s->Xrottable[a]) {
434 				if (l != s->Xrottable[a])
435 					s->Xrotations[l] = s->Xrotations[l - 1];
436 				if (k > s->Xrotations[l] || l == s->Xrottable[a]) {
437 					s->Xrotations[l] = k;
438 					c++;
439 					l = s->Xrottable[a];
440 				}
441 				l--;
442 			}
443 		}
444 		d += ix;
445 		if (maxi < c - s->Xrottable[a])
446 			maxi = c - s->Xrottable[a];
447 	}
448 	s->Xrottable[a] = c;
449 	if (s->rotateX)
450 		free(s->rotateX);
451 	if ((s->rotateX = (int *) calloc((maxi + 2) << 1,
452 			sizeof (int))) == NULL) {
453 		free_kumppa_screen(mi, s);
454 		free(chks);
455 		return;
456 	}
457 
458 	maxi = 0;
459 	c = 0;
460 	d = 0;
461 	g = 0;
462 	for (a = 0; a < s->midy; a++)
463 		chks[a] = True;
464 	for (a = 0; a < s->rotsizeY; a++) {
465 		s->Yrottable[a] = c;
466 		f = (int) (d + iy) - g;		/*viivojen lkm. */
467 		g += f;
468 		if (g > s->midy) {
469 			f -= g - s->midy;
470 			g = s->midy;
471 		}
472 		for (b = 0; b < f; b++) {
473 			m = 0;
474 			for (j = 0; j < s->midy; j++) {		/*testi */
475 				if (chks[j]) {
476 					om = 0;
477 					ok = 1;
478 					l = 0;
479 					while (j + l < s->midy && om + 12 * ok > m) {
480 						if (j - l >= 0) {
481 							if (chks[j - l])
482 								om += ok;
483 						} else if (chks[l - j])
484 							om += ok;
485 						if (chks[j + l])
486 							om += ok;
487 						ok /= 1.5;
488 						l++;
489 					}
490 					if (om >= m) {
491 						k = j;
492 						m = om;
493 					}
494 				}
495 			}
496 			chks[k] = False;
497 			l = c;
498 			while (l >= s->Yrottable[a]) {
499 				if (l != s->Yrottable[a])
500 					s->Yrotations[l] = s->Yrotations[l - 1];
501 				if (k > s->Yrotations[l] || l == s->Yrottable[a]) {
502 					s->Yrotations[l] = k;
503 					c++;
504 					l = s->Yrottable[a];
505 				}
506 				l--;
507 			}
508 
509 		}
510 		d += iy;
511 		if (maxi < c - s->Yrottable[a])
512 			maxi = c - s->Yrottable[a];
513 	}
514 	s->Yrottable[a] = c;
515 	if (s->rotateY)
516 		free(s->rotateY);
517 	if ((s->rotateY = (int *) calloc((maxi + 2) << 1,
518 			sizeof (int))) == NULL) {
519 		free_kumppa_screen(mi, s);
520 		/* free(chks); */
521 		/* return; */
522 	}
523 
524 	free(chks);
525 }
526 
527 #ifndef STANDALONE
528 extern char *background;
529 extern char *foreground;
530 #endif
531 
532 ENTRYPOINT void
init_kumppa(ModeInfo * mi)533 init_kumppa(ModeInfo * mi)
534 {
535 	Display    *display = MI_DISPLAY(mi);
536 	Window      window = MI_WINDOW(mi);
537 	XGCValues   xgcv;
538 	int         n, i;
539 	kumppastruct *s;
540 	double      rspeed;
541 
542 	MI_INIT(mi, kumppas);
543 	s = &kumppas[MI_SCREEN(mi)];
544 
545 	if (!s->acosinus) {
546 		if (MI_IS_INSTALL(mi) && MI_NPIXELS(mi) > 2) {
547 			XColor      color;
548 
549 #ifndef STANDALONE
550 			s->fg = MI_FG_PIXEL(mi);
551 			s->bg = MI_BG_PIXEL(mi);
552 #endif
553 			s->blackpixel = MI_BLACK_PIXEL(mi);
554 			s->whitepixel = MI_WHITE_PIXEL(mi);
555 			if ((s->cmap = XCreateColormap(display, window,
556 					MI_VISUAL(mi), AllocNone)) == None) {
557 				free_kumppa_screen(mi, s);
558 				return;
559 			}
560 
561 			XSetWindowColormap(display, window, s->cmap);
562 			(void) XParseColor(display, s->cmap, "black", &color);
563 			(void) XAllocColor(display, s->cmap, &color);
564 			MI_BLACK_PIXEL(mi) = color.pixel;
565 			(void) XParseColor(display, s->cmap, "white", &color);
566 			(void) XAllocColor(display, s->cmap, &color);
567 			MI_WHITE_PIXEL(mi) = color.pixel;
568 #ifndef STANDALONE
569 			(void) XParseColor(display, s->cmap, background, &color);
570 			(void) XAllocColor(display, s->cmap, &color);
571 			MI_BG_PIXEL(mi) = color.pixel;
572 			(void) XParseColor(display, s->cmap, foreground, &color);
573 			(void) XAllocColor(display, s->cmap, &color);
574 			MI_FG_PIXEL(mi) = color.pixel;
575 #endif
576 
577 			xgcv.function = GXcopy;
578 			xgcv.foreground = MI_BLACK_PIXEL(mi);
579 			if ((s->fgc[32] = XCreateGC(display, window,
580 					GCForeground | GCFunction,
581 					&xgcv)) == None) {
582 				free_kumppa_screen(mi, s);
583 				return;
584 			}
585 
586 			n = 0;
587 #if 0
588 			if (mono_p) {
589 				s->fgc[0] = s->fgc[32];
590 				xgcv.foreground = MI_BLACK_PIXEL(mi);
591 				if ((s->fgc[1] = XCreateGC(display, window,
592 						GCForeground | GCFunction,
593 						&xgcv)) == None) {
594 					free_kumppa_screen(mi, s);
595 					return;
596 				}
597 				for (i = 0; i < 32; i += 2)
598 					s->fgc[i] = s->fgc[0];
599 				for (i = 1; i < 32; i += 2)
600 					s->fgc[i] = s->fgc[1];
601 			} else
602 #endif
603 				for (i = 0; i < 32; i++) {
604 					color.red = colors[n++] * 256;
605 					color.green = colors[n++] * 256;
606 					color.blue = colors[n++] * 256;
607 					color.flags = DoRed | DoGreen | DoBlue;
608 					(void) XAllocColor(display, s->cmap, &color);
609 					xgcv.foreground = color.pixel;
610 					if ((s->fgc[i] = XCreateGC(display, window,
611 							GCForeground | GCFunction,
612 							&xgcv)) == None) {
613 						free_kumppa_screen(mi, s);
614 						return;
615 					}
616 				}
617 			xgcv.foreground = MI_BLACK_PIXEL(mi);
618 			xgcv.function = GXcopy;
619 			if ((s->cgc = XCreateGC(display, window,
620 					GCForeground | GCFunction,
621 					&xgcv)) == None) {
622 				free_kumppa_screen(mi, s);
623 				return;
624 			}
625 		}
626 		if ((s->acosinus = (float *) malloc(24 *
627 				sizeof (float))) == NULL) {
628 			free_kumppa_screen(mi, s);
629 			return;
630 		}
631 		(void) memcpy(s->acosinus, acosinus, 24 * sizeof (float));
632 		(void) memcpy(s->ocoords, ocoords, 8 * sizeof (int));
633 	}
634 
635 	if (MI_IS_FULLRANDOM(mi)) {
636 		if (NRAND(2) == 1)
637 			s->cosilines = False;
638 		else
639 			s->cosilines = True;
640 	} else {
641 		s->cosilines = cosilines;
642 	}
643 	if (MI_IS_INSTALL(mi) && MI_NPIXELS(mi) > 2) {
644 		XInstallColormap(display, s->cmap);
645 		XSetGraphicsExposures(display, s->cgc, False);
646 	} else {
647 		XSetGraphicsExposures(display, MI_GC(mi), False);
648 		s->c1 = NRAND(MI_NPIXELS(mi));
649 	}
650 	if (MI_CYCLES(mi) < 1)
651 		s->time = 1;
652 	else
653 		s->time = MI_CYCLES(mi) + NRAND(MI_CYCLES(mi));
654 
655 #if 0
656 #ifdef HAVE_XDBE_EXTENSION
657 	if (get_string_resource("dbuf", "String") != NULL && get_string_resource("dbuf", "String")[0] != 0)
658 		usedouble = True;
659 	if (usedouble) {
660 		XdbeQueryExtension(display, &n, &i);
661 		if (n == 0 && i == 0) {
662 			(void) fprintf(stderr, "Double buffer extension not supported!\n");
663 			usedouble = False;
664 		}
665 	}
666 	if (usedouble)
667 		win[1] = XdbeAllocateBackBufferName(display, win[0], XdbeUndefined);
668 #endif /* HAVE_XDBE_EXTENSION */
669 #endif
670 
671 	if (speed < (float) 0.0001 || speed > (float) 0.2) {
672 		(void) fprintf(stderr,
673 			"Speed %g not in valid range! (0.0001 - 0.2), using 0.1\n",
674 			speed);
675 		speed = 0.1;
676 	}
677 	rspeed = (double) speed;
678 	s->sizx = MI_WIDTH(mi);
679 	s->sizy = MI_HEIGHT(mi);
680 	s->midx = s->sizx >> 1;
681 	s->midy = s->sizy >> 1;
682 	s->stateX = 0;
683 	s->stateY = 0;
684 	s->c = 0;
685 	s->dir = (LRAND() & 1) ? -1 : 1;
686 	MI_CLEARWINDOW(mi);
687 	make_rots(mi, rspeed, rspeed);
688 }
689 
690 
691 ENTRYPOINT void
draw_kumppa(ModeInfo * mi)692 draw_kumppa(ModeInfo * mi)
693 {
694 	Display    *display = MI_DISPLAY(mi);
695 	Window      window = MI_WINDOW(mi);
696 	GC          gc;
697 
698 #if 0
699 #ifdef HAVE_XDBE_EXTENSION
700 	XdbeSwapInfo xdswp;
701 
702 #endif /* HAVE_XDBE_EXTENSION */
703 #endif
704 	int         a, b, e;
705 	float       f;
706 	kumppastruct *s;
707 
708 	if (kumppas == NULL)
709 		return;
710 	s = &kumppas[MI_SCREEN(mi)];
711 	if (s->Xrotations == NULL)
712 		return;
713 
714 	MI_IS_DRAWN(mi) = True;
715 
716 #if 0
717 #ifdef HAVE_XDBE_EXTENSION
718 	if (usedouble) {
719 		xdswp.swap_action = XdbeUndefined;
720 		xdswp.swap_window = win[0];
721 	} else
722 #endif /* HAVE_XDBE_EXTENSION */
723 		win[1] = win[0];
724 #endif
725 
726 	if (s->cosilines) {
727 		s->c++;
728 		for (a = 0; a < 8; a++) {
729 			f = 0;
730 			for (b = 0; b < 3; b++) {
731 				s->acosinus[a * 3 + b] += cosinus[a][b];
732 				f += cosinus[a][b + 3] *
733 					sin((double) s->acosinus[a * 3 + b]);
734 			}
735 			s->coords[a] = (int) f;
736 		}
737 		for (a = 0; a < 4; a++) {
738 			if (MI_IS_INSTALL(mi) && MI_NPIXELS(mi) > 2) {
739 #if 0
740 				gc = (mono_p) ? s->fgc[1] : s->fgc[((a << 2) + s->c) & 31];
741 #endif
742 				gc = s->fgc[((a << 2) + s->c) & 31];
743 			} else {
744 				gc = MI_GC(mi);
745 				if (MI_NPIXELS(mi) <= 2)
746 					XSetForeground(display, gc, MI_WHITE_PIXEL(mi));
747 				else
748 					XSetForeground(display, gc, MI_PIXEL(mi, ((((a << 2) + s->c) & 31) * MI_NPIXELS(mi) / 32) % MI_NPIXELS(mi)));
749 			}
750 			XDrawLine(display, window, gc,
751 				  s->midx + s->ocoords[a << 1], s->midy + s->ocoords[(a << 1) + 1],
752 				  s->midx + s->coords[a << 1], s->midy + s->coords[(a << 1) + 1]);
753 			s->ocoords[a << 1] = s->coords[a << 1];
754 			s->ocoords[(a << 1) + 1] = s->coords[(a << 1) + 1];
755 		}
756 
757 	} else {
758 		for (e = 0; e < 8; e++) {
759 			a = Satnum(50);
760 			if (a >= 32)
761 				a = 32;
762 			b = Satnum(32) - 16 + s->midx;
763 			s->c = Satnum(32) - 16 + s->midy;
764 			if (MI_IS_INSTALL(mi) && MI_NPIXELS(mi) > 2) {
765 				gc = s->fgc[a];
766 			} else {
767 				gc = MI_GC(mi);
768 				if (a == 32)
769 					XSetForeground(display, gc, MI_BLACK_PIXEL(mi));
770 				else if (MI_NPIXELS(mi) > 2)
771 					XSetForeground(display, gc, MI_PIXEL(mi, (a * MI_NPIXELS(mi) / 32) % MI_NPIXELS(mi)));
772 				else if (a == 0)
773 					XSetForeground(display, gc, MI_BLACK_PIXEL(mi));
774 				else
775 					XSetForeground(display, gc, MI_WHITE_PIXEL(mi));
776 			}
777 			XFillRectangle(display, window, gc, b, s->c, 2, 2);
778 		}
779 	}
780 	if (MI_IS_INSTALL(mi) && MI_NPIXELS(mi) > 2) {
781 		gc = s->fgc[32];
782 	} else {
783 		gc = MI_GC(mi);
784 		XSetForeground(display, gc, MI_BLACK_PIXEL(mi));
785 	}
786 	XFillRectangle(display, window, gc, s->midx - 2, s->midy - 2, 4, 4);
787 	rotate(mi);
788 #if 0
789 #ifdef HAVE_XDBE_EXTENSION
790 	if (usedouble)
791 		XdbeSwapBuffers(display, &xdswp, 1);
792 #endif /* HAVE_XDBE_EXTENSION */
793 #endif
794 	if (--s->time <= 0) {
795 		if (MI_CYCLES(mi) < 1)
796 			s->time = 1;
797 		else
798 			s->time = MI_CYCLES(mi) + NRAND(MI_CYCLES(mi));
799 		s->dir = s->dir * (-1);
800 	}
801 }
802 
803 ENTRYPOINT void
release_kumppa(ModeInfo * mi)804 release_kumppa(ModeInfo * mi)
805 {
806 
807 	if (kumppas != NULL) {
808 		int         screen;
809 
810 		for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
811 			free_kumppa_screen(mi, &kumppas[screen]);
812 		free(kumppas);
813 		kumppas = (kumppastruct *) NULL;
814 	}
815 }
816 
817 XSCREENSAVER_MODULE ("Kumppa", kumppa)
818 
819 #endif /* MODE_kumppa */
820