ftp://ftp.demon.nl/disk1/redhat-contrib/libc5/SRPMS/xscreensaver-2.14-1.src.rpm
[xscreensaver] / hacks / decayscreen.c
1 /* xscreensaver, Copyright (c) 1992, 1993, 1994, 1996, 1997 
2  * Jamie Zawinski <jwz@netscape.com>
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and its
5  * documentation for any purpose is hereby granted without fee, provided that
6  * the above copyright notice appear in all copies and that both that
7  * copyright notice and this permission notice appear in supporting
8  * documentation.  No representations are made about the suitability of this
9  * software for any purpose.  It is provided "as is" without express or 
10  * implied warranty.
11  */
12
13 /* decayscreen
14  *
15  * Based on slidescreen program from the xscreensaver application and the
16  * decay program for Sun framebuffers.  This is the comment from the decay.c
17  * file:
18
19  * decay.c
20  *   find the screen bitmap for the console and make it "decay" by
21  *   randomly shifting random rectangles by one pixelwidth at a time.
22  *
23  *   by David Wald, 1988
24  *        rewritten by Natuerlich!
25  *   based on a similar "utility" on the Apollo ring at Yale.
26
27  * X version by
28  *
29  *  Vivek Khera <khera@cs.duke.edu>
30  *  5-AUG-1993
31  *
32  *  Hacked by jwz, 28-Nov-97 (sped up and added new motion directions)
33  */
34
35 #include "screenhack.h"
36
37 static int sizex, sizey;
38 static int delay;
39 static GC gc;
40 static int mode;
41
42 #define SHUFFLE 0
43 #define UP 1
44 #define LEFT 2
45 #define RIGHT 3
46 #define DOWN 4
47 #define UPLEFT 5
48 #define DOWNLEFT 6
49 #define UPRIGHT 7
50 #define DOWNRIGHT 8
51 #define IN 9
52 #define OUT 10
53
54
55 static void
56 init_decay (Display *dpy, Window window)
57 {
58   XGCValues gcv;
59   XWindowAttributes xgwa;
60   long gcflags;
61
62   char *s = get_string_resource("mode", "Mode");
63   if      (s && !strcmp(s, "shuffle")) mode = SHUFFLE;
64   else if (s && !strcmp(s, "up")) mode = UP;
65   else if (s && !strcmp(s, "left")) mode = LEFT;
66   else if (s && !strcmp(s, "right")) mode = RIGHT;
67   else if (s && !strcmp(s, "down")) mode = DOWN;
68   else if (s && !strcmp(s, "upleft")) mode = UPLEFT;
69   else if (s && !strcmp(s, "downleft")) mode = DOWNLEFT;
70   else if (s && !strcmp(s, "upright")) mode = UPRIGHT;
71   else if (s && !strcmp(s, "downright")) mode = DOWNRIGHT;
72   else if (s && !strcmp(s, "in")) mode = IN;
73   else if (s && !strcmp(s, "out")) mode = OUT;
74   else {
75     if (s && *s && !!strcmp(s, "random"))
76       fprintf(stderr, "%s: unknown mode %s\n", progname, s);
77     mode = random() % (OUT+1);
78   }
79
80   delay = get_integer_resource ("delay", "Integer");
81
82   if (delay < 0) delay = 0;
83
84   gcv.function = GXcopy;
85   gcv.subwindow_mode = IncludeInferiors;
86   gcflags = GCForeground |GCFunction;
87   if (use_subwindow_mode_p(xgwa.screen, window)) /* see grabscreen.c */
88     gcflags |= GCSubwindowMode;
89   gc = XCreateGC (dpy, window, gcflags, &gcv);
90
91   XGetWindowAttributes (dpy, window, &xgwa);
92   sizex = xgwa.width;
93   sizey = xgwa.height;
94
95   grab_screen_image (xgwa.screen, window);
96 }
97
98
99 /*
100  * perform one iteration of decay
101  */
102 static void
103 decay1 (Display *dpy, Window window)
104 {
105     int left, top, width, height, toleft, totop;
106
107 #define L 101
108 #define R 102
109 #define U 103
110 #define D 104
111     static int no_bias[]        = { L,L,L,L, R,R,R,R, U,U,U,U, D,D,D,D };
112     static int up_bias[]        = { L,L,L,L, R,R,R,R, U,U,U,U, U,U,D,D };
113     static int down_bias[]      = { L,L,L,L, R,R,R,R, U,U,D,D, D,D,D,D };
114     static int left_bias[]      = { L,L,L,L, L,L,R,R, U,U,U,U, D,D,D,D };
115     static int right_bias[]     = { L,L,R,R, R,R,R,R, U,U,U,U, D,D,D,D };
116
117     static int upleft_bias[]    = { L,L,L,L, L,R,R,R, U,U,U,U, U,D,D,D };
118     static int downleft_bias[]  = { L,L,L,L, L,R,R,R, U,U,U,D, D,D,D,D };
119     static int upright_bias[]   = { L,L,L,R, R,R,R,R, U,U,U,U, U,D,D,D };
120     static int downright_bias[] = { L,L,L,R, R,R,R,R, U,U,U,D, D,D,D,D };
121     static int *bias;
122
123     switch (mode) {
124       case SHUFFLE:     bias = no_bias; break;
125       case UP:          bias = up_bias; break;
126       case LEFT:        bias = left_bias; break;
127       case RIGHT:       bias = right_bias; break;
128       case DOWN:        bias = down_bias; break;
129       case UPLEFT:      bias = upleft_bias; break;
130       case DOWNLEFT:    bias = downleft_bias; break;
131       case UPRIGHT:     bias = upright_bias; break;
132       case DOWNRIGHT:   bias = downright_bias; break;
133       case IN:          bias = no_bias; break;
134       case OUT:         bias = no_bias; break;
135       default: abort();
136     }
137
138 #define nrnd(x) (random() % (x))
139
140     left = nrnd(sizex - 1);
141     top = nrnd(sizey);
142     width = nrnd(sizex - left);
143     height = nrnd(sizey - top);
144
145     toleft = left;
146     totop = top;
147
148     if (mode == IN || mode == OUT) {
149       int x = left+(width/2);
150       int y = top+(height/2);
151       int cx = sizex/2;
152       int cy = sizey/2;
153       if (mode == IN) {
154         if      (x > cx && y > cy)   bias = upleft_bias;
155         else if (x < cx && y > cy)   bias = upright_bias;
156         else if (x < cx && y < cy)   bias = downright_bias;
157         else /* (x > cx && y < cy)*/ bias = downleft_bias;
158       } else {
159         if      (x > cx && y > cy)   bias = downright_bias;
160         else if (x < cx && y > cy)   bias = downleft_bias;
161         else if (x < cx && y < cy)   bias = upleft_bias;
162         else /* (x > cx && y < cy)*/ bias = upright_bias;
163       }
164     }
165
166     switch (bias[random() % (sizeof(no_bias)/sizeof(*no_bias))]) {
167       case L: toleft = left-1; break;
168       case R: toleft = left+1; break;
169       case U: totop = top-1; break;
170       case D: totop = top+1; break;
171       default: abort(); break;
172     }
173
174     XCopyArea (dpy, window, window, gc, left, top, width, height,
175                toleft, totop);
176 #undef nrnd
177 }
178
179 \f
180 char *progclass = "DecayScreen";
181
182 char *defaults [] = {
183   "*dontClearRoot:              True",
184
185 #ifdef __sgi    /* really, HAVE_READ_DISPLAY_EXTENSION */
186   "*visualID:                   Best",
187 #endif
188
189   "*delay:                      10000",
190   "*mode:                       random",
191   0
192 };
193
194 XrmOptionDescRec options [] = {
195   { "-delay",           ".delay",               XrmoptionSepArg, 0 },
196   { "-mode",            ".mode",                XrmoptionSepArg, 0 },
197   { 0, 0, 0, 0 }
198 };
199
200 void
201 screenhack (Display *dpy, Window window)
202 {
203     init_decay (dpy, window);
204     while (1) {
205       int i;
206       for (i = 0; i < 100; i++)
207         decay1 (dpy, window);
208       XSync(dpy, False);
209       if (delay) usleep (delay);
210     }
211 }