http://ftp.x.org/contrib/applications/xscreensaver-3.09.tar.gz
[xscreensaver] / hacks / deco.c
1 /* xscreensaver, Copyright (c) 1997, 1998 Jamie Zawinski <jwz@jwz.org>
2  *
3  * Permission to use, copy, modify, distribute, and sell this software and its
4  * documentation for any purpose is hereby granted without fee, provided that
5  * the above copyright notice appear in all copies and that both that
6  * copyright notice and this permission notice appear in supporting
7  * documentation.  No representations are made about the suitability of this
8  * software for any purpose.  It is provided "as is" without express or 
9  * implied warranty.
10  *
11  * Concept snarfed from Michael D. Bayne in
12  * http://www.go2net.com/internet/deep/1997/04/16/body.html
13  */
14
15 #include "screenhack.h"
16 #include <stdio.h>
17
18 static XColor colors[255];
19 static int ncolors = 0;
20 static int max_depth = 0;
21 static int min_height = 0;
22 static int min_width = 0;
23
24 static void
25 deco (Display *dpy,
26       Window window,
27       Colormap cmap,
28       GC fgc, GC bgc,
29       int x, int y, int w, int h, int depth)
30 {
31   if (((random() % max_depth) < depth) || (w < min_width) || (h < min_height))
32     {
33       if (!mono_p)
34         {
35           static int current_color = 0;
36           if (++current_color >= ncolors)
37             current_color = 0;
38           XSetForeground(dpy, bgc, colors[current_color].pixel);
39         }
40       XFillRectangle (dpy, window, bgc, x, y, w, h);
41       XDrawRectangle (dpy, window, fgc, x, y, w, h);
42     }
43   else
44     {
45       if (random() & 1)
46         {
47           deco (dpy, window, cmap, fgc, bgc, x, y, w/2, h, depth+1);
48           deco (dpy, window, cmap, fgc, bgc, x+w/2, y, w/2, h, depth+1);
49         }
50       else
51         {
52           deco (dpy, window, cmap, fgc, bgc, x, y, w, h/2, depth+1);
53           deco (dpy, window, cmap, fgc, bgc, x, y+h/2, w, h/2, depth+1);
54         }
55     }
56 }
57
58 \f
59 char *progclass = "Deco";
60
61 char *defaults [] = {
62   ".background:         black",
63   ".foreground:         white",
64   "*maxDepth:           12",
65   "*minWidth:           20",
66   "*minHeight:          20",
67   "*cycle:              False",
68   "*delay:              5",
69   "*cycleDelay:         1000000",
70   "*ncolors:            64",
71   0
72 };
73
74 XrmOptionDescRec options [] = {
75   { "-max-depth",       ".maxDepth",    XrmoptionSepArg, 0 },
76   { "-min-width",       ".minWidth",    XrmoptionSepArg, 0 },
77   { "-min-height",      ".minHeight",   XrmoptionSepArg, 0 },
78   { "-delay",           ".delay",       XrmoptionSepArg, 0 },
79   { "-ncolors",         ".ncolors",     XrmoptionSepArg, 0 },
80   { "-cycle",           ".cycle",       XrmoptionNoArg, "True" },
81   { "-no-cycle",        ".cycle",       XrmoptionNoArg, "False" },
82   { "-cycle-delay",     ".cycleDelay",  XrmoptionSepArg, 0 },
83   { 0, 0, 0, 0 }
84 };
85
86 void
87 screenhack (Display *dpy, Window window)
88 {
89   GC fgc, bgc;
90   XGCValues gcv;
91   XWindowAttributes xgwa;
92   int delay = get_integer_resource ("delay", "Integer");
93   int cycle_delay = get_integer_resource ("cycleDelay", "Integer");
94   Bool writable = get_boolean_resource ("cycle", "Boolean");
95
96   max_depth = get_integer_resource ("maxDepth", "Integer");
97   if (max_depth < 1) max_depth = 1;
98   else if (max_depth > 1000) max_depth = 1000;
99
100   min_width = get_integer_resource ("minWidth", "Integer");
101   if (min_width < 2) min_width = 2;
102   min_height = get_integer_resource ("minHeight", "Integer");
103   if (min_height < 2) min_height = 2;
104
105   XGetWindowAttributes (dpy, window, &xgwa);
106
107   gcv.foreground = get_pixel_resource("foreground", "Foreground",
108                                       dpy, xgwa.colormap);
109   fgc = XCreateGC (dpy, window, GCForeground, &gcv);
110
111   gcv.foreground = get_pixel_resource("background", "Background",
112                                       dpy, xgwa.colormap);
113   bgc = XCreateGC (dpy, window, GCForeground, &gcv);
114
115   ncolors = get_integer_resource ("ncolors", "Integer");
116
117   make_random_colormap (dpy, xgwa.visual, xgwa.colormap, colors, &ncolors,
118                         False, True, &writable, True);
119
120   if (ncolors <= 2)
121     mono_p = True;
122
123   if (!mono_p)
124     {
125       GC tmp = fgc;
126       fgc = bgc;
127       bgc = tmp;
128     }
129
130   while (1)
131     {
132       XGetWindowAttributes (dpy, window, &xgwa);
133       XFillRectangle(dpy, window, bgc, 0, 0, xgwa.width, xgwa.height);
134       deco (dpy, window, xgwa.colormap, fgc, bgc,
135             0, 0, xgwa.width, xgwa.height, 0);
136       XSync (dpy, False);
137       screenhack_handle_events (dpy);
138
139       if (!delay) continue;
140       if (!writable)
141         sleep (delay);
142       else
143         {
144           time_t start = time((time_t) 0);
145           while (start - delay < time((time_t) 0))
146             {
147               rotate_colors (dpy, xgwa.colormap, colors, ncolors, 1);
148               XSync (dpy, False);
149               screenhack_handle_events (dpy);
150               if (cycle_delay)
151                 usleep (cycle_delay);
152             }
153         }
154     }
155 }