1 /* -*- Mode: C; tab-width: 4 -*- */
2 /* random --- run random modes for a certain duration */
3 
4 #if 0
5 static const char sccsid[] = "@(#)random.c	5.00 2000/11/01 xlockmore";
6 
7 #endif
8 
9 /*-
10  * Permission to use, copy, modify, and distribute this software and its
11  * documentation for any purpose and without fee is hereby granted,
12  * provided that the above copyright notice appear in all copies and that
13  * both that copyright notice and this permission notice appear in
14  * supporting documentation.
15  *
16  * This file is provided AS IS with no warranties of any kind.  The author
17  * shall have no liability with respect to the infringement of copyrights,
18  * trade secrets or any patents by this file or any part thereof.  In no
19  * event will the author be liable for any lost revenue or profits or
20  * other special, indirect and consequential damages.
21  *
22  * Revision History:
23  * 01-Nov-2000: Allocation checks
24  * 10-May-1997: Made more compatible with xscreensaver :)
25  * 18-Mar-1996: Ron Hitchens <ron AT idiom.com>
26  *              Re-coded for the ModeInfo calling scheme.  Added the
27  *              change hook.  Get ready for 3.8 release.
28  * 23-Dec-1995: Ron Hitchens <ron AT idiom.com>
29  *              Re-coded pickMode() to keep track of the modes, so
30  *              that all modes are tried before there are any repeats.
31  *              Also prevent a mode from being picked twice in a row
32  *              (could happen as first pick after refreshing the list).
33  * 04-Sep-1995: Written by Heath A. Kehoe <hakehoe AT icaen.uiowa.edu>.
34  *
35  */
36 
37 #ifdef STANDALONE
38 #define MODE_random
39 #define DEFAULTS "*verbose: False \n" \
40 
41 # define free_random 0
42 # define reshape_random 0
43 # define random_handle_event 0
44 #include "xlockmore.h"		/* in xscreensaver distribution */
45 #else /* STANDALONE */
46 #include "xlock.h"		/* in xlockmore distribution */
47 #include "color.h"
48 #include "util.h"
49 #endif /* STANDALONE */
50 
51 #define DEF_DURATION	"60"	/* 0 == infinite duration */
52 #define DEF_MODELIST	""
53 #define DEF_SEQUENTIAL "False"
54 #define DEF_FULLRANDOM "True"
55 
56 static int  duration;
57 static char *modelist;
58 static Bool sequential;
59 extern Bool fullrandom;
60 
61 static XrmOptionDescRec opts[] =
62 {
63 	{(char *) "-duration", (char *) ".random.duration", XrmoptionSepArg, (caddr_t) NULL},
64 	{(char *) "-modelist", (char *) ".random.modelist", XrmoptionSepArg, (caddr_t) NULL},
65 	{(char *) "-sequential", (char *) ".random.sequential", XrmoptionNoArg, (caddr_t) "on"},
66 	{(char *) "+sequential", (char *) ".random.sequential", XrmoptionNoArg, (caddr_t) "off"},
67 	{(char *) "-fullrandom", (char *) ".random.fullrandom", XrmoptionNoArg, (caddr_t) "on"},
68 	{(char *) "+fullrandom", (char *) ".random.fullrandom", XrmoptionNoArg, (caddr_t) "off"}
69 };
70 
71 static argtype vars[] =
72 {
73 	{(void *) & duration, (char *) "duration", (char *) "Duration", (char *) DEF_DURATION, t_Int},
74 	{(void *) & modelist, (char *) "modelist", (char *) "Modelist", (char *) DEF_MODELIST, t_String},
75 	{(void *) & sequential, (char *) "sequential", (char *) "Sequential", (char *) DEF_SEQUENTIAL, t_Bool},
76 	{(void *) & fullrandom, (char *) "fullrandom", (char *) "FullRandom", (char *) DEF_FULLRANDOM, t_Bool}
77 };
78 
79 static OptionStruct desc[] =
80 {
81 	{(char *) "-duration num", (char *) "how long a mode runs before changing to another"},
82 	{(char *) "-modelist string", (char *) "list of modes to randomly choose from"},
83 	{(char *) "-/+sequential", (char *) "turn on/off picking of modes sequentially"},
84 	{(char *) "-/+fullrandom", (char *) "turn on/off full random choice of mode-options"}
85 };
86 
87 ENTRYPOINT ModeSpecOpt random_opts =
88 {sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc};
89 
90 #ifdef USE_MODULES
91 ModStruct   random_description =
92 {"random", "init_random", "draw_random", "release_random",
93  "refresh_random", "change_random", (char *) NULL, &random_opts,
94  1, 1, 1, 1, 64, 1.0, "",
95 #ifdef MODE_run
96 #ifdef MODE_bomb
97  "Shows a random mode from above except blank, run, and bomb", 0, NULL};
98 #else
99  "Shows a random mode from above except blank and run", 0, NULL};
100 #endif
101 #else
102 #ifdef MODE_bomb
103  "Shows a random mode from above except blank and bomb", 0, NULL};
104 #else
105  "Shows a random mode from above except blank", 0, NULL};
106 #endif
107 #endif
108 
109 #endif
110 
111 #define GC_SAVE_VALUES (GCFunction|GCLineWidth|GCLineStyle|GCCapStyle|GCJoinStyle|GCGraphicsExposures|GCFont|GCSubwindowMode)
112 
113 extern int  startscreen;
114 extern int  delay;
115 extern int  count;
116 extern int  cycles;
117 extern int  size;
118 extern int  ncolors;
119 extern float saturation;
120 extern char *bitmap;
121 
122 #define MAXMODECHARS 14
123 
124 static char special_modes[][MAXMODECHARS] =
125 {
126 #ifdef MODE_bomb
127 	"bomb",
128 #endif
129 #ifdef MODE_run
130 	"run",
131 #endif
132 	"blank", "random"
133 };
134 
135 #define NUMSPECIAL (int) (sizeof (special_modes) / sizeof (special_modes[0]))
136 
137 #ifdef USE_GL
138 static char gl_modes[][MAXMODECHARS] =
139 {
140 #ifdef MODE_atlantis
141 	"atlantis",
142 #endif
143 #ifdef MODE_atunnels
144 	"atunnels",
145 #endif
146 #ifdef MODE_boxed
147 	"boxed",
148 #endif
149 #ifdef MODE_bubble3d
150 	"bubble3d",
151 #endif
152 #ifdef MODE_cage
153 	"cage",
154 #endif
155 #ifdef MODE_fire
156 	"fire",
157 #endif
158 #ifdef MODE_gears
159 	"gears",
160 #endif
161 #ifdef MODE_glplanet
162 	"glplanet",
163 #endif
164 #ifdef MODE_invert
165 	"invert",
166 #endif
167 #ifdef MODE_juggler3d
168 	"juggler3d",
169 #endif
170 #ifdef MODE_lament
171 	"lament",
172 #endif
173 #ifdef MODE_maze3d
174 	"maze3d",
175 #endif
176 #ifdef MODE_moebius
177 	"moebius",
178 #endif
179 #ifdef MODE_molecule
180 	"molecule",
181 #endif
182 #ifdef MODE_morph3d
183 	"morph3d",
184 #endif
185 #ifdef MODE_noof
186 	"noof",
187 #endif
188 #ifdef MODE_pipes
189 	"pipes",
190 #endif
191 #ifdef MODE_rubik
192 	"rubik",
193 #endif
194 #ifdef MODE_sballs
195 	"sballs",
196 #endif
197 #ifdef MODE_sierpinski3d
198 	"sierpinski3d",
199 #endif
200 #ifdef MODE_skewb
201 	"skewb",
202 #endif
203 #ifdef MODE_sproingies
204 	"sproingies",
205 #endif
206 #ifdef MODE_stairs
207 	"stairs",
208 #endif
209 #ifdef MODE_superquadrics
210 	"superquadrics",
211 #endif
212 #ifdef MODE_text3d
213 	"text3d",
214 #endif
215 #ifdef MODE_text3d2
216 	"text3d2",
217 #endif
218 };
219 
220 #define NUMGL (int) (sizeof (gl_modes) / sizeof (gl_modes[0]))
221 #else
222 static char gl_modes[][MAXMODECHARS] =
223 {""};
224 
225 #define NUMGL 0
226 #endif
227 
228 static char xpm_modes[][MAXMODECHARS] =
229 {
230 #ifdef MODE_bat
231 	"bat",
232 #endif
233 #ifdef MODE_image
234 	"image",
235 #endif
236 #ifdef MODE_flag
237 	"flag",
238 #endif
239 #ifdef MODE_life
240 	"life",
241 #endif
242 #ifdef MODE_life1d
243 	"life1d",
244 #endif
245 #ifdef MODE_maze
246 	"maze",
247 #endif
248 #ifdef MODE_puzzle
249 	"puzzle"
250 #endif
251 };
252 
253 #define NUMXPM (int) (sizeof (xpm_modes) / sizeof (xpm_modes[0]))
254 
255 static char write_modes[][MAXMODECHARS] =
256 {
257 #ifdef MODE_crystal
258 	"crystal",
259 #endif
260 #ifdef MODE_lyapunov
261 	"lyapunov",
262 #endif
263 #ifdef MODE_mandelbrot
264 	"mandelbrot",
265 #endif
266 #ifdef MODE_starfish
267 	"starfish",
268 #endif
269 #ifdef MODE_swirl
270 	"swirl",
271 #endif
272 #ifdef MODE_tetris
273 	"tetris",
274 #endif
275 #ifdef MODE_tik_tak
276 	"tik_tak",
277 #endif
278 #ifdef MODE_toneclock
279 	"toneclock",
280 #endif
281 #ifdef MODE_tube
282 	"tube"
283 #endif
284 	/* XPM modes are usually writable too ... */
285 };
286 
287 #define NUMWRITE (int) (sizeof (write_modes) / sizeof (write_modes[0]))
288 
289 static char nice_modes[][MAXMODECHARS] =
290 {
291 #ifdef MODE_apollonian
292 	"apollonian",
293 #endif
294 #ifdef MODE_blot
295 	"blot",
296 #endif
297 #ifdef MODE_bouboule
298 	"bouboule",
299 #endif
300 #ifdef MODE_bug
301 	"bug",
302 #endif
303 #ifdef MODE_clock
304 	"clock",
305 #endif
306 #ifdef MODE_daisy
307 	"daisy",
308 #endif
309 #ifdef MODE_dclock
310 	"dclock",
311 #endif
312 #ifdef MODE_decay
313 	"decay",
314 #endif
315 #ifdef MODE_deco
316 	"deco",
317 #endif
318 #ifdef MODE_demon
319 	"demon",
320 #endif
321 #ifdef MODE_dilemma
322 	"dilemma",
323 #endif
324 #ifdef MODE_dragon
325 	"dragon",
326 #endif
327 #ifdef MODE_eyes
328 	"eyes",
329 #endif
330 #ifdef MODE_fadeplot
331 	"fadeplot",
332 #endif
333 #ifdef MODE_flame
334 	"flame",
335 #endif
336 #ifdef MODE_forest
337 	"forest",
338 #endif
339 #ifdef MODE_grav
340 	"grav",
341 #endif
342 #ifdef MODE_hop
343 	"hop",
344 #endif
345 #ifdef MODE_hyper
346 	"hyper",
347 #endif
348 #ifdef MODE_ico
349 	"ico",
350 #endif
351 #ifdef MODE_image
352 	"image",
353 #endif
354 #ifdef MODE_kaleid
355 	"kaleid",
356 #endif
357 #ifdef MODE_life
358 	"life",
359 #endif
360 #ifdef MODE_life1d
361 	"life1d",
362 #endif
363 #ifdef MODE_life3d
364 	"life3d",
365 #endif
366 #ifdef MODE_lightning
367 	"lightning",
368 #endif
369 #ifdef MODE_lisa
370 	"lisa",
371 #endif
372 #ifdef MODE_lissie
373 	"lissie",
374 #endif
375 #ifdef MODE_loop
376 	"loop",
377 #endif
378 #ifdef MODE_marquee
379 	"marquee",
380 #endif
381 #ifdef MODE_munch
382 	"munch",
383 #endif
384 #ifdef MODE_nose
385 	"nose",
386 #endif
387 #ifdef MODE_pacman
388 	"pacman",
389 #endif
390 #ifdef MODE_penrose
391 	"penrose",
392 #endif
393 #ifdef MODE_petal
394 	"petal",
395 #endif
396 #ifdef MODE_puzzle
397 	"puzzle",
398 #endif
399 #ifdef MODE_pyro
400 	"pyro",
401 #endif
402 #ifdef MODE_qix
403 	"qix",
404 #endif
405 #ifdef MODE_roll
406 	"roll",
407 #endif
408 #ifdef MODE_solitaire
409 	"solitaire",
410 #endif
411 #ifdef MODE_space
412 	"space",
413 #endif
414 #ifdef MODE_sphere
415 	"sphere",
416 #endif
417 #ifdef MODE_spiral
418 	"spiral",
419 #endif
420 #ifdef MODE_spline
421 	"spline",
422 #endif
423 #ifdef MODE_star
424 	"star",
425 #endif
426 #ifdef MODE_swarm
427 	"swarm",
428 #endif
429 #ifdef MODE_tetris
430 	"tetris",
431 #endif
432 #ifdef MODE_triangle
433 	"triangle",
434 #endif
435 #ifdef MODE_tube
436 	"tube",
437 #endif
438 #ifdef MODE_turtle
439 	"turtle",
440 #endif
441 #ifdef MODE_vines
442 	"vines",
443 #endif
444 #ifdef MODE_wator
445 	"wator",
446 #endif
447 #ifdef MODE_wire
448 	"wire",
449 #endif
450 #ifdef MODE_world
451 	"world",
452 #endif
453 #ifdef MODE_worm
454 	"worm",
455 #endif
456 #ifdef MODE_xcl
457 	"xcl",
458 #endif
459 #ifdef MODE_xjack
460 	"xjack"
461 #endif
462 };
463 
464 #define NUMNICE (int) (sizeof (nice_modes) / sizeof (nice_modes[0]))
465 
466 static char use3d_modes[][MAXMODECHARS] =
467 {
468 #ifdef MODE_bouboule
469 	"bouboule",
470 #endif
471 #ifdef MODE_hyper
472 	"hyper",
473 #endif
474 #ifdef MODE_pyro
475 	"pyro",
476 #endif
477 #ifdef MODE_star
478 	"star",
479 #endif
480 #ifdef MODE_worm
481 	"worm"
482 #endif
483 };
484 
485 #define NUMUSE3D (int) (sizeof (use3d_modes) / sizeof (use3d_modes[0]))
486 
487 static char mouse_modes[][MAXMODECHARS] =
488 {
489 #ifndef DISABLE_INTERACTIVE
490 #ifdef MODE_maze
491 	"maze",
492 #endif
493 #ifdef MODE_pacman
494 	"pacman",
495 #endif
496 #ifdef MODE_solitaire
497 	"solitaire",
498 #endif
499 #ifdef MODE_tetris
500 	"tetris",
501 #endif
502 #endif
503 /* Mostly harmless interaction */
504 #ifdef MODE_eyes
505 	"eyes",
506 #endif
507 #ifdef MODE_fire
508 	"fire",
509 #endif
510 #ifdef MODE_julia
511 	"julia",
512 #endif
513 #ifdef MODE_swarm
514 	"swarm",
515 #endif
516 #ifdef MODE_t3d
517 	"t3d"
518 #endif
519 };
520 
521 #define NUMMOUSE (int) (sizeof (mouse_modes) / sizeof (mouse_modes[0]))
522 
523 static char automata_modes[][MAXMODECHARS] =
524 {
525 #ifdef MODE_ant
526 	"ant",
527 #endif
528 #ifdef MODE_ant3d
529 	"ant3d",
530 #endif
531 #ifdef MODE_bug
532 	"bug",
533 #endif
534 #ifdef MODE_demon
535 	"demon",
536 #endif
537 #ifdef MODE_dilemma
538 	"dilemma",
539 #endif
540 #ifdef MODE_life
541 	"life",
542 #endif
543 #ifdef MODE_life1d
544 	"life1d",
545 #endif
546 #ifdef MODE_life3d
547 	"life3d",
548 #endif
549 #ifdef MODE_loop
550 	"loop",
551 #endif
552 #ifdef MODE_petri
553 	"petri",
554 #endif
555 #ifdef MODE_voters
556 	"voters",
557 #endif
558 #ifdef MODE_wator
559 	"wator",
560 #endif
561 #ifdef MODE_wire
562 	"wire"
563 #endif
564 };
565 
566 #define NUMAUTOMATA (int) (sizeof (automata_modes) / sizeof (automata_modes[0]))
567 
568 static char fractal_modes[][MAXMODECHARS] =
569 {
570 #ifdef MODE_coral
571 	"coral",
572 #endif
573 #ifdef MODE_discrete
574 	"discrete",
575 #endif
576 #ifdef MODE_dragon
577 	"dragon",
578 #endif
579 #ifdef MODE_drift
580 	"drift",
581 #endif
582 #ifdef MODE_euler2d
583 	"euler2d",
584 #endif
585 #ifdef MODE_flame
586 	"flame",
587 #endif
588 #ifdef MODE_flow
589 	"flow",
590 #endif
591 #ifdef MODE_forest
592 	"forest",
593 #endif
594 #ifdef MODE_julia
595 	"julia",
596 #endif
597 #ifdef MODE_hop
598 	"hop",
599 #endif
600 #ifdef MODE_ifs
601 	"ifs",
602 #endif
603 #ifdef MODE_lightning
604 	"lightning",
605 #endif
606 #ifdef MODE_mandelbrot
607 	"mandelbrot",
608 #endif
609 #ifdef MODE_mountain
610 	"mountain",
611 #endif
612 #ifdef MODE_sierpinski
613 	"sierpinski",
614 #endif
615 #ifdef MODE_strange
616 	"strange",
617 #endif
618 #ifdef MODE_thornbird
619 	"thornbird",
620 #endif
621 #ifdef MODE_triangle
622 	"triangle",
623 #endif
624 #ifdef MODE_turtle
625 	"turtle",
626 #endif
627 #ifdef MODE_vines
628 	"vines"
629 #endif
630 };
631 
632 #define NUMFRACTAL (int) (sizeof (fractal_modes) / sizeof (fractal_modes[0]))
633 
634 
635 static char geometry_modes[][MAXMODECHARS] =
636 {
637 #ifdef MODE_apollonian
638 	"apollonian",
639 #endif
640 #ifdef MODE_braid
641 	"braid",
642 #endif
643 #ifdef MODE_fadeplot
644 	"fadeplot",
645 #endif
646 #ifdef MODE_helix
647 	"helix",
648 #endif
649 #ifdef MODE_hyper
650 	"hyper",
651 #endif
652 #ifdef MODE_ico
653 	"ico",
654 #endif
655 #ifdef MODE_kaleid
656 	"kaleid",
657 #endif
658 #ifdef MODE_laser
659 	"laser",
660 #endif
661 #ifdef MODE_lisa
662 	"lisa",
663 #endif
664 #ifdef MODE_lissie
665 	"lissie",
666 #endif
667 #ifdef MODE_penrose
668 	"penrose",
669 #endif
670 #ifdef MODE_petal
671 	"petal",
672 #endif
673 #ifdef MODE_polyominoes
674 	"polyominoes",
675 #endif
676 #ifdef MODE_qix
677 	"qix",
678 #endif
679 #ifdef MODE_shape
680 	"shape",
681 #endif
682 #ifdef MODE_sphere
683 	"sphere",
684 #endif
685 #ifdef MODE_spiral
686 	"spiral",
687 #endif
688 #ifdef MODE_spline
689 	"spline",
690 #endif
691 #ifdef MODE_tik_tak
692 	"tik_tak",
693 #endif
694 #ifdef MODE_toneclock
695 	"toneclock"
696 #endif
697 };
698 
699 #define NUMGEOMETRY (int) (sizeof (geometry_modes) / sizeof (geometry_modes[0]))
700 
701 static char space_modes[][MAXMODECHARS] =
702 {
703 #ifdef MODE_bouboule
704 	"bouboule",
705 #endif
706 #ifdef MODE_galaxy
707 	"galaxy",
708 #endif
709 #ifdef MODE_grav
710 	"grav",
711 #endif
712 #ifdef MODE_star
713 	"star",
714 #endif
715 #ifdef MODE_world
716 	"world"
717 #endif
718 };
719 
720 #define NUMSPACE (int) (sizeof (space_modes) / sizeof (space_modes[0]))
721 
722 typedef struct {
723 	XGCValues   gcvs;
724 	int         fix;
725 } randomstruct;
726 
727 static int  currentmode = -1;
728 static int  previousmode = -1;
729 static unsigned long starttime;
730 static int *modes;
731 static int  nmodes;
732 static Bool change_now = False;
733 
734 static randomstruct *randoms;
735 
736 static int
pickMode(void)737 pickMode(void)
738 {
739 	static int *mode_indexes = (int *) NULL;
740 	static int  mode_count = 0;
741 	static int  last_mode = -1, last_index = -1;
742 	int         mode, i;
743 
744 	if (mode_indexes == NULL) {
745 		if (!nmodes)
746 			return 0;
747 		if ((mode_indexes = (int *) calloc(nmodes,
748 				sizeof (int))) == NULL) {
749 			if (sequential)
750 				return modes[0];
751 			else
752 				return modes[NRAND(nmodes)];
753 		}
754 	}
755 	if (mode_count == 0) {
756 		for (i = 0; i < nmodes; i++) {
757 			mode_indexes[i] = modes[i];
758 		}
759 		mode_count = nmodes;
760 	}
761 	if (mode_count == 1) {
762 		/* only one left, let's use that one */
763 		last_index = -1;
764 		return (last_mode = mode_indexes[--mode_count]);
765 	} else {
766 		/* pick a random slot in the list, check for last */
767 		if (sequential) {
768 			last_index = i = (last_index + 1) % nmodes;
769 		} else
770 			while (mode_indexes[i = NRAND(mode_count)] == last_mode);
771 	}
772 
773 	mode = mode_indexes[i];	/* copy out chosen mode */
774 	/* move mode at end of list to slot vacated by chosen mode, dec count */
775 	mode_indexes[i] = mode_indexes[--mode_count];
776 	return (last_mode = mode);	/* remember last mode picked */
777 }
778 
779 static char *
strpmtok(int * sign,char * str)780 strpmtok(int *sign, char *str)
781 {
782 	static int  nextsign = 0;
783 	static char *loc;
784 	char       *p, *r;
785 
786 	if (str)
787 		loc = str;
788 	if (nextsign) {
789 		*sign = nextsign;
790 		nextsign = 0;
791 	}
792 	p = loc - 1;
793 	for (;;) {
794 		switch (*++p) {
795 			case '+':
796 				*sign = 1;
797 				continue;
798 			case '-':
799 				*sign = -1;
800 				continue;
801 			case ' ':
802 			case ',':
803 			case '\t':
804 			case '\n':
805 				continue;
806 			case 0:
807 				loc = p;
808 				return (char *) NULL;
809 		}
810 		break;
811 	}
812 	r = p;
813 
814 	for (;;) {
815 		switch (*++p) {
816 			case '+':
817 				nextsign = 1;
818 				break;
819 			case '-':
820 				nextsign = -1;
821 				break;
822 			case ' ':
823 			case ',':
824 			case '\t':
825 			case '\n':
826 			case 0:
827 				break;
828 			default:
829 				continue;
830 		}
831 		break;
832 	}
833 	if (*p) {
834 		*p = 0;
835 		loc = p + 1;
836 	} else
837 		loc = p;
838 
839 	return r;
840 }
841 
842 static Bool
parsemodelist(ModeInfo * mi)843 parsemodelist(ModeInfo * mi)
844 {
845 	int         i, sign = 1, j, found;
846 	char       *p;
847 
848 	if ((modes = (int *) calloc(numprocs - 1, sizeof (int))) == NULL) {
849 			return False;
850 	}
851 	p = strpmtok(&sign, (modelist) ? modelist : (char *) "");
852 
853 	while (p) {
854 		if (!strcmp(p, "all")) {
855 			for (i = 0; i < numprocs; i++) {
856 				found = 0;
857 				for (j = 0; j < NUMSPECIAL; j++)
858 					if (!strcmp(special_modes[j], LockProcs[i].cmdline_arg)) {
859 						found = 1; /* if found do not want on list nomatter sign */
860 			      break;
861 					}
862 				if (!found)
863 					modes[i] = (sign > 0);
864 			}
865 		} else if (!strcmp(p, "allgl")) {
866 			for (i = 0; i < numprocs; i++)
867 				for (j = 0; j < NUMGL; j++)
868 					if (!strcmp(gl_modes[j], LockProcs[i].cmdline_arg))
869 						modes[i] = (sign > 0);
870 		} else if (!strcmp(p, "allxpm")) {
871 			for (i = 0; i < numprocs; i++)
872 				for (j = 0; j < NUMXPM; j++)
873 					if (!strcmp(xpm_modes[j], LockProcs[i].cmdline_arg))
874 						modes[i] = (sign > 0);
875 		} else if (!strcmp(p, "allwrite")) {
876 			for (i = 0; i < numprocs; i++)
877 				for (j = 0; j < NUMWRITE; j++)
878 					if (!strcmp(write_modes[j], LockProcs[i].cmdline_arg))
879 						modes[i] = (sign > 0);
880 		} else if (!strcmp(p, "allnice")) {
881 			for (i = 0; i < numprocs; i++)
882 				for (j = 0; j < NUMNICE; j++)
883 					if (!strcmp(nice_modes[j], LockProcs[i].cmdline_arg))
884 						modes[i] = (sign > 0);
885 		} else if (!strcmp(p, "all3d")) {
886 			for (i = 0; i < numprocs; i++)
887 				for (j = 0; j < NUMUSE3D; j++)
888 					if (!strcmp(use3d_modes[j], LockProcs[i].cmdline_arg))
889 						modes[i] = (sign > 0);
890 		} else if (!strcmp(p, "allmouse")) {
891 			for (i = 0; i < numprocs; i++)
892 				for (j = 0; j < NUMMOUSE; j++)
893 					if (!strcmp(mouse_modes[j], LockProcs[i].cmdline_arg))
894 						modes[i] = (sign > 0);
895 		} else if (!strcmp(p, "allautomata")) {
896 			for (i = 0; i < numprocs; i++)
897 				for (j = 0; j < NUMAUTOMATA; j++)
898 					if (!strcmp(automata_modes[j], LockProcs[i].cmdline_arg))
899 						modes[i] = (sign > 0);
900 		} else if (!strcmp(p, "allfractal")) {
901 			for (i = 0; i < numprocs; i++)
902 				for (j = 0; j < NUMFRACTAL; j++)
903 					if (!strcmp(fractal_modes[j], LockProcs[i].cmdline_arg))
904 						modes[i] = (sign > 0);
905 		} else if (!strcmp(p, "allgeometry")) {
906 			for (i = 0; i < numprocs; i++)
907 				for (j = 0; j < NUMGEOMETRY; j++)
908 					if (!strcmp(geometry_modes[j], LockProcs[i].cmdline_arg))
909 						modes[i] = (sign > 0);
910 		} else if (!strcmp(p, "allspace")) {
911 			for (i = 0; i < numprocs; i++)
912 				for (j = 0; j < NUMSPACE; j++)
913 					if (!strcmp(space_modes[j], LockProcs[i].cmdline_arg))
914 						modes[i] = (sign > 0);
915 		} else {
916 			for (i = 0; i < numprocs - 1; i++)
917 				if (!strcmp(p, LockProcs[i].cmdline_arg))
918 					break;
919 			if (i < numprocs - 1)
920 				modes[i] = (sign > 0);
921 			else
922 				(void) fprintf(stderr, "unrecognized mode \"%s\"\n", p);
923 		}
924 		p = strpmtok(&sign, (char *) NULL);
925 	}
926 
927 	nmodes = 0;
928 	for (i = 0; i < numprocs - 1; i++)
929 		if (modes[i])
930 			modes[nmodes++] = i;
931 	if (!nmodes) {		/* empty list */
932 		for (i = 0; i < numprocs; i++) {
933 			found = 0;
934 			for (j = 0; j < NUMSPECIAL; j++)
935 				if (!strcmp(special_modes[j], LockProcs[i].cmdline_arg)) {
936 					found = 1;
937 		      break;
938 				}
939 			if (!found)
940 				modes[i] = i;
941 		}
942 		nmodes = numprocs - NUMSPECIAL;
943 	}
944 	if (MI_IS_DEBUG(mi)) {
945 		(void) fprintf(stderr, "%d mode%s: ", nmodes, ((nmodes == 1) ? "" : "s"));
946 		for (i = 0; i < nmodes; i++)
947 			(void) fprintf(stderr, "%d ", modes[i]);
948 		(void) fprintf(stderr, "\n");
949 	}
950 	return True;
951 }
952 #ifdef WIN32
953 extern int showtext;/* from xlock.c */
954 extern char* xlock95_get_modelist(void);/* from xlock95.c */
955 extern GC GCCreate();
956 extern void xlockmore_set_mode_options(ModeSpecOpt *ms);
957 extern void XGetGCValues(Display *display, GC gc, unsigned long valuemask,
958     XGCValues* values_return);
959 #endif
960 
961 static void
setMode(ModeInfo * mi,int newmode)962 setMode(ModeInfo * mi, int newmode)
963 {
964 #ifndef WIN32
965 	randomstruct *rp = &randoms[MI_SCREEN(mi)];
966 	int         i;
967 #endif
968 
969 	previousmode = currentmode;
970 	currentmode = newmode;
971 
972 /* FIX THIS GLOBAL ACCESS */
973 	delay = MI_DELAY(mi) = LockProcs[currentmode].def_delay;
974 	count = MI_COUNT(mi) = LockProcs[currentmode].def_count;
975 	cycles = MI_CYCLES(mi) = LockProcs[currentmode].def_cycles;
976 	size = MI_SIZE(mi) = LockProcs[currentmode].def_size;
977 	ncolors = MI_NCOLORS(mi) = LockProcs[currentmode].def_ncolors;
978 	saturation = MI_SATURATION(mi) = LockProcs[currentmode].def_saturation;
979 	bitmap = MI_BITMAP(mi) = LockProcs[currentmode].def_bitmap;
980 
981 #ifndef WIN32
982 	for (i = startscreen; i < MI_NUM_SCREENS(mi); i++) {
983 
984 		XChangeGC(MI_DISPLAY(mi), MI_GC(mi), GC_SAVE_VALUES,
985 			  &(rp->gcvs));		/* Not sure if this is right for multiscreens */
986 		randoms[i].fix = True;
987 	}
988 #endif
989 	if (MI_IS_VERBOSE(mi))
990 		(void) fprintf(stderr, "mode %d: %s\n", currentmode, LockProcs[currentmode].cmdline_arg);
991 #ifdef WIN32
992 	{
993 	  ModeSpecOpt *ms = LockProcs[currentmode].msopt;
994 	  /*MI_COLORMAP_SIZE(mi) = ncolors = mi->screeninfo->npixels = colorcount;*/
995 	  XFreeGC(MI_DISPLAY(mi), MI_GC(mi));
996 	  MI_GC(mi) = GCCreate();
997 	  xlockmore_set_mode_options(ms);
998 
999 	  /* Needed because WIN32 sections of xlock.c use these as
1000 		 globals */
1001 	  /*randommode = currentmode;
1002 	  showtext=0;*/
1003 	}
1004 #endif
1005 }
1006 
1007 ENTRYPOINT void
init_random(ModeInfo * mi)1008 init_random(ModeInfo * mi)
1009 {
1010 	randomstruct *rp;
1011 	int         i;
1012 
1013 	/* NO MI_INIT here*/
1014 	if (randoms == NULL) {
1015 		if ((randoms = (randomstruct *) calloc(MI_NUM_SCREENS(mi),
1016 					     sizeof (randomstruct))) == NULL)
1017 			return;
1018 	}
1019 	rp = &randoms[MI_SCREEN(mi)];
1020 #ifdef WIN32
1021 	/* Fetch current modelist from registry */
1022 	modelist = xlock95_get_modelist();
1023 #endif
1024 	MI_SET_FLAG_STATE(mi, WI_FLAG_FULLRANDOM, fullrandom);
1025 	if (currentmode < 0) {
1026 		if (!parsemodelist(mi))
1027 			return;
1028 		for (i = startscreen; i < MI_NUM_SCREENS(mi); i++) {
1029 			(void) XGetGCValues(MI_DISPLAY(mi), MI_GC(mi),
1030 					    GC_SAVE_VALUES, &(rp->gcvs));
1031 		}
1032 		setMode(mi, pickMode());
1033 		starttime = seconds();
1034 		if (duration < 0)
1035 			duration = 0;
1036 	}
1037 	if (rp->fix) {
1038 		fixColormap(mi, MI_NCOLORS(mi),
1039 			MI_SATURATION(mi), MI_IS_MONO(mi), MI_IS_INSTALL(mi),
1040 		    MI_IS_INROOT(mi), MI_IS_INWINDOW(mi), MI_IS_VERBOSE(mi));
1041 		rp->fix = False;
1042 	}
1043 	call_init_hook(&LockProcs[currentmode], mi);
1044 }
1045 
1046 ENTRYPOINT void
draw_random(ModeInfo * mi)1047 draw_random(ModeInfo * mi)
1048 {
1049 	int         scrn = MI_SCREEN(mi);
1050 	int         newmode;
1051 	unsigned long now = seconds();
1052 	int         has_run = (duration == 0) ? 0 : (int) (now - starttime);
1053 	static int  do_init = 0;
1054 	randomstruct *rp;
1055 
1056 	if (randoms == NULL)
1057 		return;
1058 	rp = &randoms[scrn];
1059 	if (currentmode < 0)
1060 		return;
1061 
1062 	if ((scrn == startscreen) && do_init) {
1063 		do_init = 0;
1064 	}
1065 	if ((scrn == startscreen) && (change_now || (has_run > duration))) {
1066 		newmode = pickMode();
1067 
1068 		MI_CLEARWINDOW(mi);
1069 
1070 		setMode(mi, newmode);
1071 		starttime = now;
1072 		do_init = 1;
1073 		change_now = False;
1074 	}
1075 	if (rp->fix) {
1076 		fixColormap(mi, MI_NCOLORS(mi),
1077 			MI_SATURATION(mi), MI_IS_MONO(mi), MI_IS_INSTALL(mi),
1078 		    MI_IS_INROOT(mi), MI_IS_INWINDOW(mi), MI_IS_VERBOSE(mi));
1079 		rp->fix = False;
1080 	}
1081 	if (do_init) {
1082 		call_init_hook(&LockProcs[currentmode], mi);
1083 	}
1084 	call_callback_hook(&LockProcs[currentmode], mi);
1085 }
1086 
1087 ENTRYPOINT void
release_random(ModeInfo * mi)1088 release_random(ModeInfo * mi)
1089 {
1090 	if (previousmode >= 0 && previousmode != currentmode)
1091 		call_release_hook(&LockProcs[previousmode], mi);
1092 	previousmode = currentmode;
1093 }
1094 
1095 #ifndef STANDALONE
1096 ENTRYPOINT void
refresh_random(ModeInfo * mi)1097 refresh_random(ModeInfo * mi)
1098 {
1099 	if (currentmode < 0)
1100 		return;
1101 	call_refresh_hook(&LockProcs[currentmode], mi);
1102 }
1103 
1104 ENTRYPOINT void
change_random(ModeInfo * mi)1105 change_random(ModeInfo * mi)
1106 {
1107 	if (currentmode < 0)
1108 		return;
1109 	if (MI_SCREEN(mi) == startscreen)
1110 		change_now = True;	/* force a change on next draw callback */
1111 	draw_random(mi);
1112 }
1113 #endif
1114 
1115 XSCREENSAVER_MODULE ("Random", random)
1116