1 /* -*- Mode: C; tab-width: 4 -*- */
2 /* tik_tak --- Rotating objects inspired by the Belgium television program *
3  * TIKTAK */
4 
5 #if 0
6 static const char sccsid[] = "@(#)tik_tak.c	5.00 2000/11/01 xlockmore";
7 
8 #endif
9 
10 /*-
11  * Copyright (c) 1999 by Jouk Jansen <joukj AT hrem.nano.tudelft.nl>
12  *
13  * Permission to use, copy, modify, and distribute this software and its
14  * documentation for any purpose and without fee is hereby granted,
15  * provided that the above copyright notice appear in all copies and that
16  * both that copyright notice and this permission notice appear in
17  * supporting documentation.
18  *
19  * This file is provided AS IS with no warranties of any kind.  The author
20  * shall have no liability with respect to the infringement of copyrights,
21  * trade secrets or any patents by this file or any part thereof.  In no
22  * event will the author be liable for any lost revenue or profits or
23  * other special, indirect and consequential damages.
24  *
25  * The author should like to be notified if changes have been made to the
26  * routine.  Response will only be guaranteed when a VMS version of the
27  * program is available.
28  *
29  * A rotating polygon-mode. This mode is inspired (but different) by some
30  * parts of the Belgium television program, TIKTAK, intended for babies.
31  *
32  * Revision History:
33  * 01-Nov-2000: Allocation checks
34  * 16-Sep-1999: Added shells and stars
35  * 08-Sep-1999: Created
36  *
37  * TODO list :
38  *   -make the objects move hormonically around the centre
39  *   -Create run-time options
40  */
41 
42 #ifdef STANDALONE
43 # define MODE_tik_tak
44 # define DEFAULTS "*delay: 60000 \n" \
45 	"*count: -20 \n" \
46 	"*cycles: 200 \n" \
47 	"*size: -1000 \n" \
48 	"*ncolors: 64 \n" \
49 	"*fullrandom: True \n" \
50 	"*verbose: False \n" \
51 
52 # define free_tik_tak 0
53 # define reshape_tik_tak 0
54 # define tik_tak_handle_event 0
55 #include "xlockmore.h"		/* in xscreensaver distribution */
56 #else /* STANDALONE */
57 # include "xlock.h"		/* in xlockmore distribution */
58 # include "color.h"
59 #endif /* STANDALONE */
60 
61 #ifdef MODE_tik_tak
62 
63 #define DEF_NUM_OBJECT 4
64 
65 #define DEF_CYCLE "True"
66 
67 static Bool cycle_p;
68 
69 static XrmOptionDescRec opts[] =
70 {
71 	{(char *) "-cycle", (char *) ".tik_tak.cycle", XrmoptionNoArg, (caddr_t) "on"},
72 	{(char *) "+cycle", (char *) ".tik_tak.cycle", XrmoptionNoArg, (caddr_t) "off"}
73 };
74 
75 static argtype vars[] =
76 {
77 	{(void *) & cycle_p, (char *) "cycle", (char *) "Cycle", (char *) DEF_CYCLE, t_Bool}
78 };
79 static OptionStruct desc[] =
80 {
81 	{(char *) "-/+cycle", (char *) "turn on/off colour cycling"}
82 };
83 
84 ENTRYPOINT ModeSpecOpt tik_tak_opts =
85 {sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc};
86 
87 #ifdef USE_MODULES
88 ModStruct   tik_tak_description =
89 {"tik_tak", "init_tik_tak", "draw_tik_tak", "release_tik_tak",
90  "refresh_tik_tak", "init_tik_tak", (char *) NULL, &tik_tak_opts,
91  60000, -20, 200, -1000, 64, 1.0, "",
92  "Shows rotating polygons", 0, NULL};
93 
94 #endif
95 
96 #define PI_RAD (M_PI / 180.0)
97 
98 typedef struct {
99 	unsigned long colour;
100         Bool        inner;
101 	float       angle, velocity_a, angle1, velocity_a1;
102 	float       size_mult, size_mult1;
103 	int         num_point, size_ob;
104 	int         num_point1, size_ob1;
105 	XPoint      *xy , *xy1;
106 } tik_takobject;
107 
108 typedef struct {
109 	Bool        painted;
110 	int         win_width, win_height, num_object, x0, y0;
111 	tik_takobject *object;
112 	GC          gc;
113 	Colormap    cmap;
114 	XColor     *colors;
115 	int         ncolors;
116 	Bool        cycle_p, mono_p, no_colors;
117 	unsigned long blackpixel, whitepixel, fg, bg;
118 	int         direction;
119 } tik_takstruct;
120 
121 static tik_takstruct *tik_taks = (tik_takstruct *) NULL;
122 
123 static void
tik_tak_setupobject(ModeInfo * mi,tik_takobject * object0)124 tik_tak_setupobject( ModeInfo * mi , tik_takobject * object0)
125 {
126 	tik_takstruct *tiktak = &tik_taks[MI_SCREEN(mi)];
127 	int         x_0=tiktak->x0 , y_0=tiktak->y0 , i;
128    float curangle;
129 
130    for (i = 0; i <= object0->num_point; i++)
131      {
132 	object0->xy[i].x = object0->xy[i+object0->num_point+1].x;
133 	object0->xy[i].y = object0->xy[i+object0->num_point+1].y;
134      }
135    for (i = 0; i < object0->num_point; i++)
136      {
137 	object0->size_ob = (int) (object0->size_ob * object0->size_mult);
138 	object0->size_mult = 1.0 / object0->size_mult;
139 	curangle = object0->angle + i * 360.0 * PI_RAD /
140 	  (float) object0->num_point;
141 	object0->xy[i+object0->num_point+1].x = x_0 +
142 	  (int) (object0->size_ob * cos(curangle)) +
143 	  (int) (object0->size_ob * sin(curangle));
144 	object0->xy[i+object0->num_point+1].y = y_0 +
145 	  (int) (object0->size_ob * cos(curangle)) -
146 	  (int) (object0->size_ob * sin(curangle));
147      }
148    object0->xy[object0->num_point*2+1].x = object0->xy[object0->num_point+1].x;
149    object0->xy[object0->num_point*2+1].y = object0->xy[object0->num_point+1].y;
150 
151    if ( object0->inner )
152      {
153 	for (i = 0; i <= object0->num_point1; i++)
154 	  {
155 	     object0->xy1[i].x = object0->xy1[i+object0->num_point1+1].x;
156 	     object0->xy1[i].y = object0->xy1[i+object0->num_point1+1].y;
157 	  }
158 
159 	for (i = 0; i < object0->num_point1; i++)
160 	  {
161 	     object0->size_ob1 = (int) (object0->size_ob1 * object0->size_mult1);
162 	     object0->size_mult1 = 1.0 / object0->size_mult1;
163 	     curangle = object0->angle1 + i * 360.0 * PI_RAD /
164 	       (float) object0->num_point1;
165 	     object0->xy1[i+object0->num_point1+1].x = x_0 +
166 	       (int) (object0->size_ob1 * cos(curangle)) +
167 	       (int) (object0->size_ob1 * sin(curangle));
168 	     object0->xy1[i+object0->num_point1+1].y = y_0 +
169 	       (int) (object0->size_ob1 * cos(curangle)) -
170 	       (int) (object0->size_ob1 * sin(curangle));
171 	  }
172 	object0->xy1[object0->num_point1*2+1].x =
173 	  object0->xy1[object0->num_point1+1].x;
174 	object0->xy1[object0->num_point1*2+1].y =
175 	  object0->xy1[object0->num_point1+1].y;
176      }
177 }
178 
179 static void
tik_tak_reset_object(tik_takobject * object0)180 tik_tak_reset_object( tik_takobject * object0)
181 {
182    int i;
183 
184    for (i = 0; i <= object0->num_point; i++)
185      {
186 	object0->xy[i].x = object0->xy[object0->num_point+1].x;
187 	object0->xy[i].y = object0->xy[object0->num_point+1].y;
188      }
189 
190    if ( object0->inner )
191      {
192 	for (i = 0; i <= object0->num_point1; i++)
193 	  {
194 	     object0->xy1[i].x = object0->xy1[object0->num_point1+1].x;
195 	     object0->xy1[i].y = object0->xy1[object0->num_point1+1].y;
196 	  }
197      }
198 }
199 
200 static void
tik_tak_drawobject(ModeInfo * mi,tik_takobject * object0)201 tik_tak_drawobject(ModeInfo * mi, tik_takobject * object0 )
202 {
203 	Display    *display = MI_DISPLAY(mi);
204 	Window      window = MI_WINDOW(mi);
205 	tik_takstruct *tiktak = &tik_taks[MI_SCREEN(mi)];
206 
207    XFillPolygon(display, window, tiktak->gc, object0->xy ,
208 		object0->num_point * 2 + 2 , Complex , CoordModeOrigin);
209    if ( object0->inner )
210      XFillPolygon(display, window, tiktak->gc, object0->xy1 ,
211 		  object0->num_point1 * 2 + 2 , Complex , CoordModeOrigin);
212 }
213 
214 static void
free_tik_tak_screen(ModeInfo * mi,tik_takstruct * tiktak)215 free_tik_tak_screen(ModeInfo *mi, tik_takstruct *tiktak)
216 {
217 	Display    *display = MI_DISPLAY(mi);
218 
219 	if (tiktak == NULL) {
220 		return;
221 	}
222 	if (MI_IS_INSTALL(mi) && MI_NPIXELS(mi) > 2) {
223 		MI_WHITE_PIXEL(mi) = tiktak->whitepixel;
224 		MI_BLACK_PIXEL(mi) = tiktak->blackpixel;
225 #ifndef STANDALONE
226 		MI_FG_PIXEL(mi) = tiktak->fg;
227 		MI_BG_PIXEL(mi) = tiktak->bg;
228 #endif
229 		if (tiktak->colors != NULL) {
230 #ifdef STANDALONE
231 			Screen *screen = MI_SCREENPTR(mi);
232 #endif
233 			if (tiktak->ncolors && !tiktak->no_colors)
234 				free_colors(
235 #ifdef STANDALONE
236 					screen,
237 #else
238 					display,
239 #endif
240 					tiktak->cmap, tiktak->colors, tiktak->ncolors);
241 			free(tiktak->colors);
242 			tiktak->colors = (XColor *) NULL;
243 		}
244 		if (tiktak->cmap != None) {
245 			XFreeColormap(display, tiktak->cmap);
246 			tiktak->cmap = None;
247 		}
248 	}
249 	if (tiktak->gc != None) {
250 		XFreeGC(display, tiktak->gc);
251 		tiktak->gc = None;
252 	}
253 	if (tiktak->object != NULL) {
254 		int i;
255 
256 		for (i = 0; i < tiktak->num_object; i++) {
257 			tik_takobject *object0;
258 
259 			object0 = &tiktak->object[i];
260 		 	if (object0->xy1 != NULL)
261 				free(object0->xy1);
262 			if (object0->xy != NULL)
263 				free(object0->xy);
264 		}
265 		free(tiktak->object);
266 		tiktak->object = (tik_takobject *) NULL;
267 	}
268 	tiktak = NULL;
269 }
270 
271 #ifndef STANDALONE
272 extern char *background;
273 extern char *foreground;
274 #endif
275 
276 ENTRYPOINT void
init_tik_tak(ModeInfo * mi)277 init_tik_tak(ModeInfo * mi)
278 {
279 	Display    *display = MI_DISPLAY(mi);
280 	Window      window = MI_WINDOW(mi);
281 	int         i, max_objects, size_object;
282 	tik_takstruct *tiktak;
283 
284 /* initialize */
285 	MI_INIT(mi, tik_taks);
286 	tiktak = &tik_taks[MI_SCREEN(mi)];
287 
288 	if (tiktak->gc == None) {
289 		if (MI_IS_INSTALL(mi) && MI_NPIXELS(mi) > 2) {
290 			XColor      color;
291 
292 #ifndef STANDALONE
293 			tiktak->fg = MI_FG_PIXEL(mi);
294 			tiktak->bg = MI_BG_PIXEL(mi);
295 #endif
296 			tiktak->blackpixel = MI_BLACK_PIXEL(mi);
297 			tiktak->whitepixel = MI_WHITE_PIXEL(mi);
298 			if ((tiktak->cmap = XCreateColormap(display, window,
299 					MI_VISUAL(mi), AllocNone)) == None) {
300 				free_tik_tak_screen(mi, tiktak);
301 				return;
302 			}
303 			XSetWindowColormap(display, window, tiktak->cmap);
304 			(void) XParseColor(display, tiktak->cmap, "black", &color);
305 			(void) XAllocColor(display, tiktak->cmap, &color);
306 			MI_BLACK_PIXEL(mi) = color.pixel;
307 			(void) XParseColor(display, tiktak->cmap, "white", &color);
308 			(void) XAllocColor(display, tiktak->cmap, &color);
309 			MI_WHITE_PIXEL(mi) = color.pixel;
310 #ifndef STANDALONE
311 			(void) XParseColor(display, tiktak->cmap, background, &color);
312 			(void) XAllocColor(display, tiktak->cmap, &color);
313 			MI_BG_PIXEL(mi) = color.pixel;
314 			(void) XParseColor(display, tiktak->cmap, foreground, &color);
315 			(void) XAllocColor(display, tiktak->cmap, &color);
316 			MI_FG_PIXEL(mi) = color.pixel;
317 #endif
318 			tiktak->colors = (XColor *) NULL;
319 			tiktak->ncolors = 0;
320 		}
321 		if ((tiktak->gc = XCreateGC(display, MI_WINDOW(mi),
322 			     (unsigned long) 0, (XGCValues *) NULL)) == None) {
323 			free_tik_tak_screen(mi, tiktak);
324 			return;
325 		}
326 	}
327 /* Clear Display */
328 	MI_CLEARWINDOW(mi);
329 	tiktak->painted = False;
330 	XSetFunction(display, tiktak->gc, GXxor);
331 
332 
333 /*Set up tik_tak data */
334 	tiktak->direction = (LRAND() & 1) ? 1 : -1;
335 	tiktak->win_width = MI_WIDTH(mi);
336 	tiktak->win_height = MI_HEIGHT(mi);
337 	tiktak->num_object = MI_COUNT(mi);
338         tiktak->x0 = tiktak->win_width / 2;
339         tiktak->y0 = tiktak->win_height / 2;
340 	max_objects = MI_COUNT(mi);
341 	if (tiktak->num_object == 0) {
342 		tiktak->num_object = DEF_NUM_OBJECT;
343 		max_objects = DEF_NUM_OBJECT;
344 	} else if (tiktak->num_object < 0) {
345 		max_objects = -tiktak->num_object;
346 		tiktak->num_object = NRAND(-tiktak->num_object) + 1;
347 	}
348 	if (tiktak->object == NULL)
349 		if ((tiktak->object = (tik_takobject *) calloc(max_objects,
350 				sizeof (tik_takobject))) == NULL) {
351 			free_tik_tak_screen(mi, tiktak);
352 			return;
353 		}
354 	size_object = MIN( tiktak->win_width , tiktak->win_height) / 3;
355 	if ( abs( MI_SIZE(mi) ) > size_object) {
356 	   if ( MI_SIZE( mi ) < 0 )
357 	     {
358 		size_object = -size_object;
359 	     }
360 	} else {
361 	  size_object = MI_SIZE(mi);
362 	}
363 	if (MI_IS_INSTALL(mi) && MI_NPIXELS(mi) > 2) {
364 #ifdef STANDALONE
365 		Screen *screen = MI_SCREENPTR(mi);
366 #endif
367 /* Set up colour map */
368 		if (tiktak->colors != NULL) {
369 			if (tiktak->ncolors && !tiktak->no_colors)
370 				free_colors(
371 #ifdef STANDALONE
372 					screen,
373 #else
374 					display,
375 #endif
376 					tiktak->cmap, tiktak->colors, tiktak->ncolors);
377 			free(tiktak->colors);
378 			tiktak->colors = (XColor *) NULL;
379 		}
380 		tiktak->ncolors = MI_NCOLORS(mi);
381 		if (tiktak->ncolors < 2)
382 			tiktak->ncolors = 2;
383 		if (tiktak->ncolors <= 2)
384 			tiktak->mono_p = True;
385 		else
386 			tiktak->mono_p = False;
387 
388 		if (tiktak->mono_p)
389 			tiktak->colors = (XColor *) NULL;
390 		else
391 			if ((tiktak->colors = (XColor *) malloc(sizeof (*tiktak->colors) *
392 					(tiktak->ncolors + 1))) == NULL) {
393 				free_tik_tak_screen(mi, tiktak);
394 				return;
395 			}
396 		tiktak->cycle_p = has_writable_cells(
397 #ifdef STANDALONE
398 			screen, MI_VISUAL(mi)
399 #else
400 			mi
401 #endif
402 			);
403 
404 		if (tiktak->cycle_p) {
405 			if (MI_IS_FULLRANDOM(mi)) {
406 				if (!NRAND(8))
407 					tiktak->cycle_p = False;
408 				else
409 					tiktak->cycle_p = True;
410 			} else {
411 				tiktak->cycle_p = cycle_p;
412 			}
413 		}
414 		if (!tiktak->mono_p) {
415 			if (!(LRAND() % 10))
416 				make_random_colormap(
417 #ifdef STANDALONE
418 					screen, MI_VISUAL(mi),
419 					tiktak->cmap, tiktak->colors, &tiktak->ncolors,
420 					True, True, &tiktak->cycle_p, True
421 #else
422                                         mi,
423 					tiktak->cmap, tiktak->colors, &tiktak->ncolors,
424 					True, True, &tiktak->cycle_p
425 #endif
426                                         );
427 			else if (!(LRAND() % 2))
428 				make_uniform_colormap(
429 #ifdef STANDALONE
430 					screen, MI_VISUAL(mi),
431 					tiktak->cmap, tiktak->colors, &tiktak->ncolors,
432 					True, &tiktak->cycle_p, True
433 #else
434                                         mi,
435 					tiktak->cmap, tiktak->colors, &tiktak->ncolors,
436 					True, &tiktak->cycle_p
437 #endif
438                                         );
439 			else
440 				make_smooth_colormap(
441 #ifdef STANDALONE
442 					screen, MI_VISUAL(mi),
443 					tiktak->cmap, tiktak->colors, &tiktak->ncolors,
444 					True, &tiktak->cycle_p, True
445 #else
446                                         mi,
447 					tiktak->cmap, tiktak->colors, &tiktak->ncolors,
448 					True, &tiktak->cycle_p
449 #endif
450                                         );
451 		}
452 		XInstallColormap(display, tiktak->cmap);
453 		if (tiktak->ncolors < 2) {
454 			tiktak->ncolors = 2;
455 			tiktak->no_colors = True;
456 		} else
457 			tiktak->no_colors = False;
458 		if (tiktak->ncolors <= 2)
459 			tiktak->mono_p = True;
460 
461 		if (tiktak->mono_p)
462 			tiktak->cycle_p = False;
463 
464 	}
465 	for (i = 0; i < tiktak->num_object; i++) {
466 		tik_takobject *object0;
467 
468 		object0 = &tiktak->object[i];
469 		if (MI_IS_INSTALL(mi) && MI_NPIXELS(mi) > 2) {
470 			if (tiktak->ncolors > 2)
471 				object0->colour = NRAND(tiktak->ncolors - 2) + 2;
472 			else
473 				object0->colour = 1;	/* Just in case */
474 			XSetForeground(display, tiktak->gc, tiktak->colors[object0->colour].pixel);
475 		} else {
476 			if (MI_NPIXELS(mi) > 2)
477 				object0->colour = MI_PIXEL(mi, NRAND(MI_NPIXELS(mi)));
478 			else
479 				object0->colour = 1;	/*Xor'red so WHITE may not be appropriate */
480 			XSetForeground(display, tiktak->gc, object0->colour);
481 		}
482 		object0->angle = NRAND(90) * PI_RAD;
483 		object0->angle1 = NRAND(90) * PI_RAD;
484 		object0->velocity_a = (NRAND(7) - 3) * PI_RAD;
485 		object0->velocity_a1 = (NRAND(7) - 3) * PI_RAD;
486 		if (size_object == 0)
487 			object0->size_ob = 9;
488 		else if (size_object > 0)
489 			object0->size_ob = size_object;
490 		else
491 			object0->size_ob = NRAND(-size_object) + 1;
492 		object0->size_ob++;
493 		object0->num_point = NRAND(6)+3;
494 	   if (LRAND() & 1)
495 	     object0->size_mult = 1.0;
496 	   else
497 	     {
498 		object0->num_point *= 2;
499 		object0->size_mult = 1.0 - ( 1.0 / (float) ((LRAND() & 1) +
500 							    2 ) );
501 	     }
502 	   if (object0->xy != NULL)
503 			free(object0->xy);
504 	   if ((object0->xy = (XPoint *) malloc(sizeof( XPoint ) *
505 				(2 * object0->num_point + 2))) == NULL) {
506 			free_tik_tak_screen(mi, tiktak);
507 			return;
508 		}
509 	   if ((LRAND() & 1) || object0->size_ob < 10 )
510 	     {
511 		object0->inner = False;
512 		if ( object0->xy1 != NULL ) free( object0->xy1 );
513 		object0->xy1 = (XPoint *) NULL;
514 	     }
515 	   else
516 	     {
517 		object0->inner = True;
518 	        object0->size_ob1 = object0->size_ob -
519 		  NRAND( object0->size_ob / 5 ) - 1;
520 		object0->num_point1 = NRAND(6)+3;
521 		if (LRAND() & 1)
522 		  object0->size_mult1 = 1.0;
523 		else
524 		  {
525 		     object0->num_point1 *= 2;
526 		     object0->size_mult1 = 1.0 -
527 		        ( 1.0 / (float) ((LRAND() & 1) + 2 ) );
528 		  }
529 		if (object0->xy1 != NULL)
530 			free(object0->xy1);
531 		if ((object0->xy1 = (XPoint *) malloc(sizeof( XPoint ) *
532 				(2 * object0->num_point1 + 2))) == NULL) {
533 			free_tik_tak_screen(mi, tiktak);
534 			return;
535 		}
536 		object0->size_mult1 = 1.0;
537 	     }
538 		tik_tak_setupobject( mi , object0);
539 		tik_tak_reset_object( object0);
540 		tik_tak_drawobject(mi, object0 );
541 	}
542 	XFlush(display);
543 	XSetFunction(display, tiktak->gc, GXcopy);
544 }
545 
546 ENTRYPOINT void
draw_tik_tak(ModeInfo * mi)547 draw_tik_tak(ModeInfo * mi)
548 {
549 	Display    *display = MI_DISPLAY(mi);
550 	int         i;
551 	tik_takstruct *tiktak;
552 
553 	if (tik_taks == NULL)
554 		return;
555 	tiktak = &tik_taks[MI_SCREEN(mi)];
556 	if (tiktak->object == NULL)
557 		return;
558 
559 	if (tiktak->no_colors) {
560 		free_tik_tak_screen(mi, tiktak);
561 		init_tik_tak(mi);
562 		return;
563 	}
564 	tiktak->painted = True;
565 	MI_IS_DRAWN(mi) = True;
566 	XSetFunction(display, tiktak->gc, GXxor);
567 
568 /* Rotate colours */
569 	if (tiktak->cycle_p) {
570 		rotate_colors(
571 #ifdef STANDALONE
572 			MI_SCREENPTR(mi),
573 #else
574 			display,
575 #endif
576 			tiktak->cmap, tiktak->colors, tiktak->ncolors, tiktak->direction);
577 		if (!(LRAND() % 1000))
578 			tiktak->direction = -tiktak->direction;
579 	}
580 	for (i = 0; i < tiktak->num_object; i++) {
581 		tik_takobject *object0;
582 
583 		object0 = &tiktak->object[i];
584 		if (MI_IS_INSTALL(mi) && MI_NPIXELS(mi) > 2) {
585 			XSetForeground(display, tiktak->gc, tiktak->colors[object0->colour].pixel);
586 		} else {
587 			XSetForeground(display, tiktak->gc, object0->colour);
588 		}
589 		object0->velocity_a += ((float) NRAND(1001) - 500.0) / 200000.0;
590 		object0->angle += object0->velocity_a;
591 		object0->velocity_a1 += ((float) NRAND(1001) - 500.0) / 200000.0;
592 		object0->angle1 += object0->velocity_a1;
593 		tik_tak_setupobject( mi , object0);
594 		tik_tak_drawobject(mi, object0 );
595 	}
596 	XSetFunction(display, tiktak->gc, GXcopy);
597 }
598 
599 ENTRYPOINT void
release_tik_tak(ModeInfo * mi)600 release_tik_tak(ModeInfo * mi)
601 {
602 	if (tik_taks != NULL) {
603 		int         screen;
604 
605 		for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
606 			free_tik_tak_screen(mi, &tik_taks[screen]);
607 		free(tik_taks);
608 		tik_taks = (tik_takstruct *) NULL;
609 	}
610 }
611 
612 #ifndef STANDALONE
613 ENTRYPOINT void
refresh_tik_tak(ModeInfo * mi)614 refresh_tik_tak(ModeInfo * mi)
615 {
616 	Display    *display = MI_DISPLAY(mi);
617 	int         i;
618 	tik_takstruct *tiktak;
619 
620 	if (tik_taks == NULL)
621 		return;
622 	tiktak = &tik_taks[MI_SCREEN(mi)];
623 	if (tiktak->object == NULL)
624 		return;
625 
626 	if (!tiktak->painted)
627 		return;
628 	MI_CLEARWINDOW(mi);
629 	XSetFunction(display, tiktak->gc, GXxor);
630 
631 	for (i = 0; i < tiktak->num_object; i++) {
632 		tik_takobject *object0;
633 
634 		object0 = &tiktak->object[i];
635 		if (MI_IS_INSTALL(mi) && MI_NPIXELS(mi) > 2) {
636 			XSetForeground(display, tiktak->gc, tiktak->colors[object0->colour].pixel);
637 		} else {
638 			XSetForeground(display, tiktak->gc, object0->colour);
639 		}
640 		tik_tak_setupobject( mi , object0);
641 		tik_tak_reset_object( object0);
642 		tik_tak_drawobject(mi, object0 );
643 	}
644 	XSetFunction(display, tiktak->gc, GXcopy);
645 }
646 #endif
647 
648 XSCREENSAVER_MODULE ("Tik_tak", tik_tak)
649 
650 #endif /* MODE_tik_tak */
651