1 /* -*- Mode: C; tab-width: 4 -*- */
2 /* blot --- Rorschach's ink blot test */
3
4 #if 0
5 static const char sccsid[] = "@(#)blot.c 5.00 2000/11/01 xlockmore";
6
7 #endif
8
9 /*-
10 * Copyright (c) 1992 by Jamie Zawinski
11 *
12 * Permission to use, copy, modify, and distribute this software and its
13 * documentation for any purpose and without fee is hereby granted,
14 * provided that the above copyright notice appear in all copies and that
15 * both that copyright notice and this permission notice appear in
16 * supporting documentation.
17 *
18 * This file is provided AS IS with no warranties of any kind. The author
19 * shall have no liability with respect to the infringement of copyrights,
20 * trade secrets or any patents by this file or any part thereof. In no
21 * event will the author be liable for any lost revenue or profits or
22 * other special, indirect and consequential damages.
23 *
24 * 01-Nov-2000: Allocation checks
25 * 10-May-1997: Compatible with xscreensaver
26 * 05-Jan-1995: patch for Dual-Headed machines from Greg Onufer
27 * <Greg.Onufer@Eng.Sun.COM>
28 * 07-Dec-1994: now randomly has xsym, ysym, or both.
29 * 02-Sep-1993: xlock version David Bagley <bagleyd AT verizon.net>
30 * 1992: xscreensaver version Jamie Zawinski <jwz AT jwz.org>
31 */
32
33 /*-
34 * original copyright
35 * Copyright (c) 1992 by Jamie Zawinski
36 * Permission to use, copy, modify, distribute, and sell this software and
37 * its documentation for any purpose is hereby granted without fee, provided
38 * that the above copyright notice appear in all copies and that both that
39 * copyright notice and this permission notice appear in supporting
40 * documentation. No representations are made about the suitability of this
41 * software for any purpose. It is provided "as is" without express or
42 * implied warranty.
43 */
44
45 #ifdef STANDALONE
46 # define MODE_blot
47 # define DEFAULTS "*delay: 2000000 \n" \
48 "*count: 6 \n" \
49 "*cycles: 30 \n" \
50 "*ncolors: 200 \n" \
51
52 # define reshape_blot 0
53 # define blot_handle_event 0
54 # include "xlockmore.h" /* in xscreensaver distribution */
55 #else /* STANDALONE */
56 # include "xlock.h" /* in xlockmore distribution */
57 #endif /* STANDALONE */
58
59 #ifdef MODE_blot
60
61 ENTRYPOINT ModeSpecOpt blot_opts =
62 {0, (XrmOptionDescRec *) NULL, 0, (argtype *) NULL, (OptionStruct *) NULL};
63
64 #ifdef USE_MODULES
65 const ModStruct blot_description =
66 {"blot", "init_blot", "draw_blot", "release_blot",
67 "refresh_blot", "init_blot", "free_blot", &blot_opts,
68 200000, 6, 30, 1, 64, 0.3, "",
69 "Shows Rorschach's ink blot test", 0, NULL};
70
71 #endif
72
73 typedef struct {
74 int width;
75 int height;
76 int xmid, ymid;
77 int offset;
78 int xsym, ysym;
79 int size;
80 int pix;
81 int count;
82 XPoint *pointBuffer;
83 unsigned int pointBufferSize;
84 } blotstruct;
85
86 static blotstruct *blots = (blotstruct *) NULL;
87
88 ENTRYPOINT void
init_blot(ModeInfo * mi)89 init_blot(ModeInfo * mi)
90 {
91 Display *display = MI_DISPLAY(mi);
92 blotstruct *bp;
93
94 MI_INIT(mi, blots);
95 bp = &blots[MI_SCREEN(mi)];
96
97 bp->width = MI_WIDTH(mi);
98 bp->height = MI_HEIGHT(mi);
99 bp->xmid = bp->width / 2;
100 bp->ymid = bp->height / 2;
101
102 bp->offset = 4;
103 bp->ysym = (int) LRAND() & 1;
104 bp->xsym = (bp->ysym) ? (int) LRAND() & 1 : 1;
105 if (MI_NPIXELS(mi) > 2)
106 bp->pix = NRAND(MI_NPIXELS(mi));
107 if (bp->offset <= 0)
108 bp->offset = 3;
109 if (MI_COUNT(mi) < 0)
110 bp->size = NRAND(-MI_COUNT(mi) + 1);
111 else
112 bp->size = MI_COUNT(mi);
113
114 /* Fudge the size so it takes up the whole screen */
115 bp->size *= (bp->width / 32 + 1) * (bp->height / 32 + 1);
116 if (!bp->pointBuffer || bp->pointBufferSize < bp->size * sizeof (XPoint)) {
117 if (bp->pointBuffer != NULL)
118 free(bp->pointBuffer);
119 bp->pointBufferSize = bp->size * sizeof (XPoint);
120 if ((bp->pointBuffer = (XPoint *) malloc(bp->pointBufferSize)) ==
121 NULL) {
122 return;
123 }
124 }
125 MI_CLEARWINDOW(mi);
126 XSetForeground(display, MI_GC(mi), MI_WHITE_PIXEL(mi));
127 bp->count = 0;
128 }
129
130 ENTRYPOINT void
draw_blot(ModeInfo * mi)131 draw_blot(ModeInfo * mi)
132 {
133 blotstruct *bp;
134 XPoint *xp;
135 int x, y, k;
136
137 if (blots == NULL)
138 return;
139 bp = &blots[MI_SCREEN(mi)];
140 xp = bp->pointBuffer;
141 if (xp == NULL)
142 init_blot(mi);
143
144 MI_IS_DRAWN(mi) = True;
145 if (MI_NPIXELS(mi) > 2) {
146 XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_PIXEL(mi, bp->pix));
147 if (++bp->pix >= MI_NPIXELS(mi))
148 bp->pix = 0;
149 }
150 x = bp->xmid;
151 y = bp->ymid;
152 k = bp->size;
153 while (k >= 4) {
154 x += (NRAND(1 + (bp->offset << 1)) - bp->offset);
155 y += (NRAND(1 + (bp->offset << 1)) - bp->offset);
156 k--;
157 xp->x = x;
158 xp->y = y;
159 xp++;
160 if (bp->xsym) {
161 k--;
162 xp->x = bp->width - x;
163 xp->y = y;
164 xp++;
165 }
166 if (bp->ysym) {
167 k--;
168 xp->x = x;
169 xp->y = bp->height - y;
170 xp++;
171 }
172 if (bp->xsym && bp->ysym) {
173 k--;
174 xp->x = bp->width - x;
175 xp->y = bp->height - y;
176 xp++;
177 }
178 }
179 XDrawPoints(MI_DISPLAY(mi), MI_WINDOW(mi), MI_GC(mi),
180 bp->pointBuffer, (bp->size - k), CoordModeOrigin);
181 if (++bp->count > MI_CYCLES(mi))
182 init_blot(mi);
183 }
184
185 static void
free_blot_screen(blotstruct * bp)186 free_blot_screen(blotstruct *bp)
187 {
188 if (bp == NULL) {
189 return;
190 }
191 if (bp->pointBuffer != NULL) {
192 free(bp->pointBuffer);
193 bp->pointBuffer = NULL;
194 }
195 bp = NULL;
196 }
197
198
199 ENTRYPOINT void
free_blot(ModeInfo * mi)200 free_blot(ModeInfo * mi)
201 {
202 blotstruct *bp = &blots[MI_SCREEN(mi)];
203 free_blot_screen(bp);
204 }
205
206 ENTRYPOINT void
release_blot(ModeInfo * mi)207 release_blot(ModeInfo * mi)
208 {
209 if (blots != NULL) {
210 int screen;
211
212 for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) {
213 free_blot_screen(&blots[screen]);
214 }
215 free(blots);
216 blots = (blotstruct *) NULL;
217 }
218 }
219
220 #ifndef STANDALONE
221 ENTRYPOINT void
refresh_blot(ModeInfo * mi)222 refresh_blot(ModeInfo * mi)
223 {
224 MI_CLEARWINDOW(mi);
225 }
226 #endif
227
228 XSCREENSAVER_MODULE ("Blot", blot)
229
230 #endif /* MODE_blot */
231