~ubuntu-branches/ubuntu/lucid/xscreensaver/lucid

« back to all changes in this revision

Viewing changes to hacks/petri.c

  • Committer: Bazaar Package Importer
  • Author(s): Oliver Grawert
  • Date: 2007-12-06 09:53:12 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20071206095312-fkzcwe4vqm50z208
Tags: 5.04-1ubuntu1
* Merge from debian unstable, remaining changes:
  - split xscreensaver into xscreensaver, xscreensaver-data (hacks we ship),
    xscreensaver-data-extra (hacks in universe). split out gl hacks for
    universe to xscreensaver-gl-extra
  - use fridge for rss screensavers
  - create and install .desktop files for gnome-screensaver

Show diffs side-by-side

added added

removed removed

Lines of Context:
81
81
                                    /* 24 36 - */
82
82
} cell;
83
83
 
84
 
static int arr_width;
85
 
static int arr_height;
86
 
static int count;
87
 
 
88
 
static cell *arr;
89
 
static cell *head;
90
 
static cell *tail;
91
 
static int blastcount;
92
 
 
93
 
static Display *display;
94
 
static Window window;
95
 
static GC *coloredGCs;
96
 
 
97
 
static int windowWidth;
98
 
static int windowHeight;
99
 
static int xOffset;
100
 
static int yOffset;
101
 
static int xSize;
102
 
static int ySize;
103
 
 
104
 
static FLOAT orthlim = 1.0;
105
 
static FLOAT diaglim;
106
 
static FLOAT anychan;
107
 
static FLOAT minorchan;
108
 
static FLOAT instantdeathchan;
109
 
static int minlifespan;
110
 
static int maxlifespan;
111
 
static FLOAT minlifespeed;
112
 
static FLOAT maxlifespeed;
113
 
static FLOAT mindeathspeed;
114
 
static FLOAT maxdeathspeed;
115
 
static Bool originalcolors;
116
 
 
117
 
#define cell_x(c) (((c) - arr) % arr_width)
118
 
#define cell_y(c) (((c) - arr) / arr_width)
119
 
 
120
 
 
121
 
static int random_life_value (void)
 
84
struct state {
 
85
  Display *dpy;
 
86
  Window window;
 
87
 
 
88
  int arr_width;
 
89
  int arr_height;
 
90
  int count;
 
91
 
 
92
  cell *arr;
 
93
  cell *head;
 
94
  cell *tail;
 
95
  int blastcount;
 
96
 
 
97
  GC *coloredGCs;
 
98
 
 
99
  int windowWidth;
 
100
  int windowHeight;
 
101
  int xOffset;
 
102
  int yOffset;
 
103
  int xSize;
 
104
  int ySize;
 
105
 
 
106
  FLOAT orthlim;
 
107
  FLOAT diaglim;
 
108
  FLOAT anychan;
 
109
  FLOAT minorchan;
 
110
  FLOAT instantdeathchan;
 
111
  int minlifespan;
 
112
  int maxlifespan;
 
113
  FLOAT minlifespeed;
 
114
  FLOAT maxlifespeed;
 
115
  FLOAT mindeathspeed;
 
116
  FLOAT maxdeathspeed;
 
117
  Bool originalcolors;
 
118
 
 
119
  int warned;
 
120
  int delay;
 
121
};
 
122
 
 
123
 
 
124
#define cell_x(c) (st->arr_width ? ((c) - st->arr) % st->arr_width : 0)
 
125
#define cell_y(c) (st->arr_width ? ((c) - st->arr) / st->arr_width : 0)
 
126
 
 
127
 
 
128
static int random_life_value (struct state *st)
122
129
{
123
 
    return (int) ((RAND_FLOAT * (maxlifespan - minlifespan)) + minlifespan);
 
130
    return (int) ((RAND_FLOAT * (st->maxlifespan - st->minlifespan)) + st->minlifespan);
124
131
}
125
132
 
126
 
static void setup_random_colormap (XWindowAttributes *xgwa)
 
133
static void setup_random_colormap (struct state *st, XWindowAttributes *xgwa)
127
134
{
128
135
    XGCValues gcv;
129
136
    int lose = 0;
130
 
    int ncolors = count - 1;
 
137
    int ncolors = st->count - 1;
131
138
    int n;
132
 
    XColor *colors = (XColor *) calloc (sizeof(*colors), count*2);
133
 
    
134
 
    colors[0].pixel = get_pixel_resource ("background", "Background",
135
 
                                          display, xgwa->colormap);
136
 
    
137
 
    make_random_colormap (display, xgwa->visual, xgwa->colormap,
 
139
    XColor *colors = (XColor *) calloc (sizeof(*colors), st->count*2);
 
140
    
 
141
    colors[0].pixel = get_pixel_resource (st->dpy, xgwa->colormap,
 
142
                                          "background", "Background");
 
143
    
 
144
    make_random_colormap (st->dpy, xgwa->visual, xgwa->colormap,
138
145
                          colors+1, &ncolors, True, True, 0, True);
139
146
    if (ncolors < 1)
140
147
      {
143
150
      }
144
151
    
145
152
    ncolors++;
146
 
    count = ncolors;
147
 
    
148
 
    memcpy (colors + count, colors, count * sizeof(*colors));
149
 
    colors[count].pixel = get_pixel_resource ("foreground", "Foreground",
150
 
                                              display, xgwa->colormap);
151
 
    
152
 
    for (n = 1; n < count; n++)
 
153
    st->count = ncolors;
 
154
    
 
155
    memcpy (colors + st->count, colors, st->count * sizeof(*colors));
 
156
    colors[st->count].pixel = get_pixel_resource (st->dpy, xgwa->colormap,
 
157
                                              "foreground", "Foreground");
 
158
    
 
159
    for (n = 1; n < st->count; n++)
153
160
    {
154
 
        int m = n + count;
 
161
        int m = n + st->count;
155
162
        colors[n].red = colors[m].red / 2;
156
163
        colors[n].green = colors[m].green / 2;
157
164
        colors[n].blue = colors[m].blue / 2;
158
165
        
159
 
        if (!XAllocColor (display, xgwa->colormap, &colors[n]))
 
166
        if (!XAllocColor (st->dpy, xgwa->colormap, &colors[n]))
160
167
        {
161
168
            lose++;
162
169
            colors[n] = colors[m];
170
177
                 progname, lose);
171
178
    }
172
179
    
173
 
    for (n = 0; n < count*2; n++) 
 
180
    for (n = 0; n < st->count*2; n++) 
174
181
    {
175
182
        gcv.foreground = colors[n].pixel;
176
 
        coloredGCs[n] = XCreateGC (display, window, GCForeground, &gcv);
 
183
        st->coloredGCs[n] = XCreateGC (st->dpy, st->window, GCForeground, &gcv);
177
184
    }
178
185
 
179
186
    free (colors);
180
187
}
181
188
 
182
 
static void setup_original_colormap (XWindowAttributes *xgwa)
 
189
static void setup_original_colormap (struct state *st, XWindowAttributes *xgwa)
183
190
{
184
191
    XGCValues gcv;
185
192
    int lose = 0;
186
193
    int n;
187
 
    XColor *colors = (XColor *) calloc (sizeof(*colors), count*2);
 
194
    XColor *colors = (XColor *) calloc (sizeof(*colors), st->count*2);
188
195
    
189
 
    colors[0].pixel = get_pixel_resource ("background", "Background",
190
 
                                          display, xgwa->colormap);
191
 
 
192
 
    colors[count].pixel = get_pixel_resource ("foreground", "Foreground",
193
 
                                              display, xgwa->colormap);
194
 
 
195
 
    for (n = 1; n < count; n++)
 
196
    colors[0].pixel = get_pixel_resource (st->dpy, xgwa->colormap,
 
197
                                          "background", "Background");
 
198
 
 
199
    colors[st->count].pixel = get_pixel_resource (st->dpy, xgwa->colormap,
 
200
                                              "foreground", "Foreground");
 
201
 
 
202
    for (n = 1; n < st->count; n++)
196
203
    {
197
 
        int m = n + count;
 
204
        int m = n + st->count;
198
205
        colors[n].red =   ((n & 0x01) != 0) * 0x8000;
199
206
        colors[n].green = ((n & 0x02) != 0) * 0x8000;
200
207
        colors[n].blue =  ((n & 0x04) != 0) * 0x8000;
201
208
 
202
 
        if (!XAllocColor (display, xgwa->colormap, &colors[n]))
 
209
        if (!XAllocColor (st->dpy, xgwa->colormap, &colors[n]))
203
210
        {
204
211
            lose++;
205
212
            colors[n] = colors[0];
209
216
        colors[m].green = colors[n].green + 0x4000;
210
217
        colors[m].blue  = colors[n].blue + 0x4000;
211
218
 
212
 
        if (!XAllocColor (display, xgwa->colormap, &colors[m]))
 
219
        if (!XAllocColor (st->dpy, xgwa->colormap, &colors[m]))
213
220
        {
214
221
            lose++;
215
 
            colors[m] = colors[count];
 
222
            colors[m] = colors[st->count];
216
223
        }
217
224
    }
218
225
 
223
230
                 progname, lose);
224
231
    }
225
232
    
226
 
    for (n = 0; n < count*2; n++) 
 
233
    for (n = 0; n < st->count*2; n++) 
227
234
    {
228
235
        gcv.foreground = colors[n].pixel;
229
 
        coloredGCs[n] = XCreateGC (display, window, GCForeground, &gcv);
 
236
        st->coloredGCs[n] = XCreateGC (st->dpy, st->window, GCForeground, &gcv);
230
237
    }
231
238
 
232
239
    free (colors);
233
240
}
234
241
 
235
 
static void setup_display (void)
 
242
static void
 
243
setup_display (struct state *st)
236
244
{
237
245
    XWindowAttributes xgwa;
238
246
    Colormap cmap;
239
247
 
240
 
    int cell_size = get_integer_resource ("size", "Integer");
 
248
    int cell_size = get_integer_resource (st->dpy, "size", "Integer");
241
249
    int osize, alloc_size, oalloc;
242
250
    int mem_throttle = 0;
243
251
    char *s;
246
254
 
247
255
    osize = cell_size;
248
256
 
249
 
    s = get_string_resource ("memThrottle", "MemThrottle");
 
257
    s = get_string_resource (st->dpy, "memThrottle", "MemThrottle");
250
258
    if (s)
251
259
      {
252
260
        int n;
269
277
        free (s);
270
278
      }
271
279
 
272
 
    XGetWindowAttributes (display, window, &xgwa);
273
 
 
274
 
    originalcolors = get_boolean_resource ("originalcolors", "Boolean");
275
 
 
276
 
    count = get_integer_resource ("count", "Integer");
277
 
    if (count < 2) count = 2;
 
280
    XGetWindowAttributes (st->dpy, st->window, &xgwa);
 
281
 
 
282
    st->originalcolors = get_boolean_resource (st->dpy, "originalcolors", "Boolean");
 
283
 
 
284
    st->count = get_integer_resource (st->dpy, "count", "Integer");
 
285
    if (st->count < 2) st->count = 2;
278
286
 
279
287
    /* number of colors can't be greater than the half depth of the screen. */
280
 
    if (count > (1L << (xgwa.depth-1)))
281
 
      count = (1L << (xgwa.depth-1));
 
288
    if (st->count > (unsigned int) (1L << (xgwa.depth-1)))
 
289
      st->count = (unsigned int) (1L << (xgwa.depth-1));
282
290
 
283
291
    /* Actually, since cell->col is of type char, this has to be small. */
284
 
    if (count >= (1L << ((sizeof(arr[0].col) * 8) - 1)))
285
 
      count = (1L << ((sizeof(arr[0].col) * 8) - 1));
286
 
 
287
 
 
288
 
    if (originalcolors && (count > 8))
289
 
    {
290
 
        count = 8;
291
 
    }
292
 
 
293
 
    coloredGCs = (GC *) calloc (sizeof(GC), count * 2);
294
 
 
295
 
    diaglim  = get_float_resource ("diaglim", "Float");
296
 
    if (diaglim < 1.0)
297
 
    {
298
 
        diaglim = 1.0;
299
 
    }
300
 
    else if (diaglim > 2.0)
301
 
    {
302
 
        diaglim = 2.0;
303
 
    }
304
 
    diaglim *= orthlim;
305
 
 
306
 
    anychan  = get_float_resource ("anychan", "Float");
307
 
    if (anychan < 0.0)
308
 
    {
309
 
        anychan = 0.0;
310
 
    }
311
 
    else if (anychan > 1.0)
312
 
    {
313
 
        anychan = 1.0;
314
 
    }
315
 
    
316
 
    minorchan = get_float_resource ("minorchan","Float");
317
 
    if (minorchan < 0.0)
318
 
    {
319
 
        minorchan = 0.0;
320
 
    }
321
 
    else if (minorchan > 1.0)
322
 
    {
323
 
        minorchan = 1.0;
324
 
    }
325
 
    
326
 
    instantdeathchan = get_float_resource ("instantdeathchan","Float");
327
 
    if (instantdeathchan < 0.0)
328
 
    {
329
 
        instantdeathchan = 0.0;
330
 
    }
331
 
    else if (instantdeathchan > 1.0)
332
 
    {
333
 
        instantdeathchan = 1.0;
334
 
    }
335
 
 
336
 
    minlifespan = get_integer_resource ("minlifespan", "Integer");
337
 
    if (minlifespan < 1)
338
 
    {
339
 
        minlifespan = 1;
340
 
    }
341
 
 
342
 
    maxlifespan = get_integer_resource ("maxlifespan", "Integer");
343
 
    if (maxlifespan < minlifespan)
344
 
    {
345
 
        maxlifespan = minlifespan;
346
 
    }
347
 
 
348
 
    minlifespeed = get_float_resource ("minlifespeed", "Float");
349
 
    if (minlifespeed < 0.0)
350
 
    {
351
 
        minlifespeed = 0.0;
352
 
    }
353
 
    else if (minlifespeed > 1.0)
354
 
    {
355
 
        minlifespeed = 1.0;
356
 
    }
357
 
 
358
 
    maxlifespeed = get_float_resource ("maxlifespeed", "Float");
359
 
    if (maxlifespeed < minlifespeed)
360
 
    {
361
 
        maxlifespeed = minlifespeed;
362
 
    }
363
 
    else if (maxlifespeed > 1.0)
364
 
    {
365
 
        maxlifespeed = 1.0;
366
 
    }
367
 
 
368
 
    mindeathspeed = get_float_resource ("mindeathspeed", "Float");
369
 
    if (mindeathspeed < 0.0)
370
 
    {
371
 
        mindeathspeed = 0.0;
372
 
    }
373
 
    else if (mindeathspeed > 1.0)
374
 
    {
375
 
        mindeathspeed = 1.0;
376
 
    }
377
 
 
378
 
    maxdeathspeed = get_float_resource ("maxdeathspeed", "Float");
379
 
    if (maxdeathspeed < mindeathspeed)
380
 
    {
381
 
        maxdeathspeed = mindeathspeed;
382
 
    }
383
 
    else if (maxdeathspeed > 1.0)
384
 
    {
385
 
        maxdeathspeed = 1.0;
386
 
    }
387
 
 
388
 
    minlifespeed *= diaglim;
389
 
    maxlifespeed *= diaglim;
390
 
    mindeathspeed *= diaglim;
391
 
    maxdeathspeed *= diaglim;
 
292
    if (st->count >= (unsigned int) (1L << ((sizeof(st->arr[0].col) * 8) - 1)))
 
293
      st->count = (unsigned int) (1L << ((sizeof(st->arr[0].col) * 8) - 1));
 
294
 
 
295
 
 
296
    if (st->originalcolors && (st->count > 8))
 
297
    {
 
298
        st->count = 8;
 
299
    }
 
300
 
 
301
    st->coloredGCs = (GC *) calloc (sizeof(GC), st->count * 2);
 
302
 
 
303
    st->diaglim  = get_float_resource (st->dpy, "diaglim", "Float");
 
304
    if (st->diaglim < 1.0)
 
305
    {
 
306
        st->diaglim = 1.0;
 
307
    }
 
308
    else if (st->diaglim > 2.0)
 
309
    {
 
310
        st->diaglim = 2.0;
 
311
    }
 
312
    st->diaglim *= st->orthlim;
 
313
 
 
314
    st->anychan  = get_float_resource (st->dpy, "anychan", "Float");
 
315
    if (st->anychan < 0.0)
 
316
    {
 
317
        st->anychan = 0.0;
 
318
    }
 
319
    else if (st->anychan > 1.0)
 
320
    {
 
321
        st->anychan = 1.0;
 
322
    }
 
323
    
 
324
    st->minorchan = get_float_resource (st->dpy, "minorchan","Float");
 
325
    if (st->minorchan < 0.0)
 
326
    {
 
327
        st->minorchan = 0.0;
 
328
    }
 
329
    else if (st->minorchan > 1.0)
 
330
    {
 
331
        st->minorchan = 1.0;
 
332
    }
 
333
    
 
334
    st->instantdeathchan = get_float_resource (st->dpy, "instantdeathchan","Float");
 
335
    if (st->instantdeathchan < 0.0)
 
336
    {
 
337
        st->instantdeathchan = 0.0;
 
338
    }
 
339
    else if (st->instantdeathchan > 1.0)
 
340
    {
 
341
        st->instantdeathchan = 1.0;
 
342
    }
 
343
 
 
344
    st->minlifespan = get_integer_resource (st->dpy, "minlifespan", "Integer");
 
345
    if (st->minlifespan < 1)
 
346
    {
 
347
        st->minlifespan = 1;
 
348
    }
 
349
 
 
350
    st->maxlifespan = get_integer_resource (st->dpy, "maxlifespan", "Integer");
 
351
    if (st->maxlifespan < st->minlifespan)
 
352
    {
 
353
        st->maxlifespan = st->minlifespan;
 
354
    }
 
355
 
 
356
    st->minlifespeed = get_float_resource (st->dpy, "minlifespeed", "Float");
 
357
    if (st->minlifespeed < 0.0)
 
358
    {
 
359
        st->minlifespeed = 0.0;
 
360
    }
 
361
    else if (st->minlifespeed > 1.0)
 
362
    {
 
363
        st->minlifespeed = 1.0;
 
364
    }
 
365
 
 
366
    st->maxlifespeed = get_float_resource (st->dpy, "maxlifespeed", "Float");
 
367
    if (st->maxlifespeed < st->minlifespeed)
 
368
    {
 
369
        st->maxlifespeed = st->minlifespeed;
 
370
    }
 
371
    else if (st->maxlifespeed > 1.0)
 
372
    {
 
373
        st->maxlifespeed = 1.0;
 
374
    }
 
375
 
 
376
    st->mindeathspeed = get_float_resource (st->dpy, "mindeathspeed", "Float");
 
377
    if (st->mindeathspeed < 0.0)
 
378
    {
 
379
        st->mindeathspeed = 0.0;
 
380
    }
 
381
    else if (st->mindeathspeed > 1.0)
 
382
    {
 
383
        st->mindeathspeed = 1.0;
 
384
    }
 
385
 
 
386
    st->maxdeathspeed = get_float_resource (st->dpy, "maxdeathspeed", "Float");
 
387
    if (st->maxdeathspeed < st->mindeathspeed)
 
388
    {
 
389
        st->maxdeathspeed = st->mindeathspeed;
 
390
    }
 
391
    else if (st->maxdeathspeed > 1.0)
 
392
    {
 
393
        st->maxdeathspeed = 1.0;
 
394
    }
 
395
 
 
396
    st->minlifespeed *= st->diaglim;
 
397
    st->maxlifespeed *= st->diaglim;
 
398
    st->mindeathspeed *= st->diaglim;
 
399
    st->maxdeathspeed *= st->diaglim;
392
400
 
393
401
    cmap = xgwa.colormap;
394
402
    
395
 
    windowWidth = xgwa.width;
396
 
    windowHeight = xgwa.height;
 
403
    st->windowWidth = xgwa.width;
 
404
    st->windowHeight = xgwa.height;
397
405
    
398
 
    arr_width = windowWidth / cell_size;
399
 
    arr_height = windowHeight / cell_size;
 
406
    st->arr_width = st->windowWidth / cell_size;
 
407
    st->arr_height = st->windowHeight / cell_size;
400
408
 
401
 
    alloc_size = sizeof(cell) * arr_width * arr_height;
 
409
    alloc_size = sizeof(cell) * st->arr_width * st->arr_height;
402
410
    oalloc = alloc_size;
403
411
 
404
412
    if (mem_throttle > 0)
405
 
      while (cell_size < windowWidth/10 &&
406
 
             cell_size < windowHeight/10 &&
 
413
      while (cell_size < st->windowWidth/10 &&
 
414
             cell_size < st->windowHeight/10 &&
407
415
             alloc_size > mem_throttle)
408
416
        {
409
417
          cell_size++;
410
 
          arr_width = windowWidth / cell_size;
411
 
          arr_height = windowHeight / cell_size;
412
 
          alloc_size = sizeof(cell) * arr_width * arr_height;
 
418
          st->arr_width = st->windowWidth / cell_size;
 
419
          st->arr_height = st->windowHeight / cell_size;
 
420
          alloc_size = sizeof(cell) * st->arr_width * st->arr_height;
413
421
        }
414
422
 
415
423
    if (osize != cell_size)
416
424
      {
417
 
        static int warned = 0;
418
 
        if (!warned)
 
425
        if (!st->warned)
419
426
          {
420
427
            fprintf (stderr,
421
428
             "%s: throttling cell size from %d to %d because of %dM limit.\n",
422
429
                     progname, osize, cell_size, mem_throttle / (1 << 20));
423
430
            fprintf (stderr, "%s: %dx%dx%d = %.1fM, %dx%dx%d = %.1fM.\n",
424
431
                     progname,
425
 
                     windowWidth, windowHeight, osize,
 
432
                     st->windowWidth, st->windowHeight, osize,
426
433
                     ((float) oalloc) / (1 << 20),
427
 
                     windowWidth, windowHeight, cell_size,
 
434
                     st->windowWidth, st->windowHeight, cell_size,
428
435
                     ((float) alloc_size) / (1 << 20));
429
 
            warned = 1;
 
436
            st->warned = 1;
430
437
          }
431
438
      }
432
439
 
433
 
    xSize = windowWidth / arr_width;
434
 
    ySize = windowHeight / arr_height;
435
 
    if (xSize > ySize)
 
440
    st->xSize = st->arr_width ? st->windowWidth / st->arr_width : 0;
 
441
    st->ySize = st->arr_height ? st->windowHeight / st->arr_height : 0;
 
442
    if (st->xSize > st->ySize)
436
443
    {
437
 
        xSize = ySize;
 
444
        st->xSize = st->ySize;
438
445
    }
439
446
    else
440
447
    {
441
 
        ySize = xSize;
 
448
        st->ySize = st->xSize;
442
449
    }
443
450
    
444
 
    xOffset = (windowWidth - (arr_width * xSize)) / 2;
445
 
    yOffset = (windowHeight - (arr_height * ySize)) / 2;
 
451
    st->xOffset = (st->windowWidth - (st->arr_width * st->xSize)) / 2;
 
452
    st->yOffset = (st->windowHeight - (st->arr_height * st->ySize)) / 2;
446
453
 
447
 
    if (originalcolors)
 
454
    if (st->originalcolors)
448
455
    {
449
 
        setup_original_colormap (&xgwa);
 
456
        setup_original_colormap (st, &xgwa);
450
457
    }
451
458
    else
452
459
    {
453
 
        setup_random_colormap (&xgwa);
 
460
        setup_random_colormap (st, &xgwa);
454
461
    }
455
462
}
456
463
 
457
 
static void drawblock (int x, int y, unsigned char c)
 
464
static void drawblock (struct state *st, int x, int y, unsigned char c)
458
465
{
459
 
  if (xSize == 1 && ySize == 1)
460
 
    XDrawPoint (display, window, coloredGCs[c], x + xOffset, y + yOffset);
 
466
  if (st->xSize == 1 && st->ySize == 1)
 
467
    XDrawPoint (st->dpy, st->window, st->coloredGCs[c], x + st->xOffset, y + st->yOffset);
461
468
  else
462
 
    XFillRectangle (display, window, coloredGCs[c],
463
 
                    x * xSize + xOffset, y * ySize + yOffset,
464
 
                    xSize, ySize);
 
469
    XFillRectangle (st->dpy, st->window, st->coloredGCs[c],
 
470
                    x * st->xSize + st->xOffset, y * st->ySize + st->yOffset,
 
471
                    st->xSize, st->ySize);
465
472
}
466
473
 
467
 
static void setup_arr (void)
 
474
static void setup_arr (struct state *st)
468
475
{
469
476
    int x, y;
470
477
 
471
 
    if (arr != NULL)
 
478
    if (st->arr != NULL)
472
479
    {
473
 
        free (arr);
 
480
        free (st->arr);
474
481
    }
475
482
 
476
 
    XFillRectangle (display, window, coloredGCs[0], 0, 0, 
477
 
                    windowWidth, windowHeight);
 
483
    XFillRectangle (st->dpy, st->window, st->coloredGCs[0], 0, 0, 
 
484
                    st->windowWidth, st->windowHeight);
 
485
    
 
486
    if (!st->arr_width) st->arr_width = 1;
 
487
    if (!st->arr_height) st->arr_height = 1;
478
488
 
479
 
    arr = (cell *) calloc (sizeof(cell), arr_width * arr_height);  
480
 
    if (!arr)
 
489
    st->arr = (cell *) calloc (sizeof(cell), st->arr_width * st->arr_height);  
 
490
    if (!st->arr)
481
491
      {
482
492
        fprintf (stderr, "%s: out of memory allocating %dx%d grid\n",
483
 
                 progname, arr_width, arr_height);
 
493
                 progname, st->arr_width, st->arr_height);
484
494
        exit (1);
485
495
      }
486
496
 
487
 
    for (y = 0; y < arr_height; y++)
 
497
    for (y = 0; y < st->arr_height; y++)
488
498
    {
489
 
      int row = y * arr_width;
490
 
        for (x = 0; x < arr_width; x++) 
 
499
      int row = y * st->arr_width;
 
500
       for (x = 0; x < st->arr_width; x++) 
491
501
        {
492
 
            arr[row+x].speed = 0.0;
493
 
            arr[row+x].growth = 0.0;
494
 
            arr[row+x].col = 0;
495
 
            arr[row+x].isnext = 0;
496
 
            arr[row+x].next = 0;
497
 
            arr[row+x].prev = 0;
 
502
            st->arr[row+x].speed = 0.0;
 
503
            st->arr[row+x].growth = 0.0;
 
504
            st->arr[row+x].col = 0;
 
505
            st->arr[row+x].isnext = 0;
 
506
            st->arr[row+x].next = 0;
 
507
            st->arr[row+x].prev = 0;
498
508
        }
499
509
    }
500
510
 
501
 
    if (head == NULL)
 
511
    if (st->head == NULL)
502
512
    {
503
 
        head = (cell *) malloc (sizeof (cell));
 
513
        st->head = (cell *) malloc (sizeof (cell));
504
514
    }
505
515
    
506
 
    if (tail == NULL)
 
516
    if (st->tail == NULL)
507
517
    {
508
 
        tail = (cell *) malloc (sizeof (cell));
 
518
        st->tail = (cell *) malloc (sizeof (cell));
509
519
    }
510
520
 
511
 
    head->next = tail;
512
 
    head->prev = head;
513
 
    tail->next = tail;
514
 
    tail->prev = head;
 
521
    st->head->next = st->tail;
 
522
    st->head->prev = st->head;
 
523
    st->tail->next = st->tail;
 
524
    st->tail->prev = st->head;
515
525
 
516
 
    blastcount = random_life_value ();
 
526
    st->blastcount = random_life_value (st);
517
527
}
518
528
 
519
 
static void newcell (cell *c, unsigned char col, FLOAT sp)
 
529
static void newcell (struct state *st, cell *c, unsigned char col, FLOAT sp)
520
530
{
521
531
    if (! c) return;
522
532
    
527
537
    c->isnext = 1;
528
538
    
529
539
    if (c->prev == 0) {
530
 
        c->next = head->next;
531
 
        c->prev = head;
532
 
        head->next = c;
 
540
        c->next = st->head->next;
 
541
        c->prev = st->head;
 
542
        st->head->next = c;
533
543
        c->next->prev = c;
534
544
    }
535
545
}
536
546
 
537
 
static void killcell (cell *c)
 
547
static void killcell (struct state *st, cell *c)
538
548
{
539
549
    c->prev->next = c->next;
540
550
    c->next->prev = c->prev;
541
551
    c->prev = 0;
542
552
    c->speed = 0.0;
543
 
    drawblock (cell_x(c), cell_y(c), c->col);
 
553
    drawblock (st, cell_x(c), cell_y(c), c->col);
544
554
}
545
555
 
546
556
 
547
 
static void randblip (int doit)
 
557
static void randblip (struct state *st, int doit)
548
558
{
549
559
    int n;
550
560
    int b = 0;
551
561
    if (!doit 
552
 
        && (blastcount-- >= 0) 
553
 
        && (RAND_FLOAT > anychan))
 
562
        && (st->blastcount-- >= 0) 
 
563
        && (RAND_FLOAT > st->anychan))
554
564
    {
555
565
        return;
556
566
    }
557
567
    
558
 
    if (blastcount < 0) 
 
568
    if (st->blastcount < 0) 
559
569
    {
560
570
        b = 1;
561
571
        n = 2;
562
 
        blastcount = random_life_value ();
563
 
        if (RAND_FLOAT < instantdeathchan)
 
572
        st->blastcount = random_life_value (st);
 
573
        if (RAND_FLOAT < st->instantdeathchan)
564
574
        {
565
575
            /* clear everything every so often to keep from getting into a
566
576
             * rut */
567
 
            setup_arr ();
 
577
            setup_arr (st);
568
578
            b = 0;
569
579
        }
570
580
    }
571
 
    else if (RAND_FLOAT <= minorchan) 
 
581
    else if (RAND_FLOAT <= st->minorchan) 
572
582
    {
573
583
        n = 2;
574
584
    }
579
589
    
580
590
    while (n--) 
581
591
    {
582
 
        int x = random () % arr_width;
583
 
        int y = random () % arr_height;
 
592
      int x = st->arr_width ? random () % st->arr_width : 0;
 
593
      int y = st->arr_height ? random () % st->arr_height : 0;
584
594
        int c;
585
595
        FLOAT s;
586
596
        if (b)
587
597
        {
588
598
            c = 0;
589
 
            s = RAND_FLOAT * (maxdeathspeed - mindeathspeed) + mindeathspeed;
 
599
            s = RAND_FLOAT * (st->maxdeathspeed - st->mindeathspeed) + st->mindeathspeed;
590
600
        }
591
601
        else
592
602
        {
593
 
            c = (random () % (count-1)) + 1;
594
 
            s = RAND_FLOAT * (maxlifespeed - minlifespeed) + minlifespeed;
 
603
            c = ((st->count - 1) ? random () % (st->count-1) : 0) + 1;
 
604
            s = RAND_FLOAT * (st->maxlifespeed - st->minlifespeed) + st->minlifespeed;
595
605
        }
596
 
        newcell (&arr[y * arr_width + x], c, s);
 
606
        newcell (st, &st->arr[y * st->arr_width + x], c, s);
597
607
    }
598
608
}
599
609
 
600
 
static void update (void)
 
610
static void update (struct state *st)
601
611
{
602
612
    cell *a;
603
613
    
604
 
    for (a = head->next; a != tail; a = a->next) 
 
614
    for (a = st->head->next; a != st->tail; a = a->next) 
605
615
    {
606
 
        static XPoint all_coords[] = {{-1, -1}, {-1, 1}, {1, -1}, {1, 1},
607
 
                                      {-1,  0}, { 1, 0}, {0, -1}, {0, 1},
608
 
                                      {99, 99}};
 
616
        static const XPoint all_coords[] = {{-1, -1}, {-1, 1}, {1, -1}, {1, 1},
 
617
                                            {-1,  0}, { 1, 0}, {0, -1}, {0, 1},
 
618
                                            {99, 99}};
609
619
 
610
 
        XPoint *coords = 0;
 
620
        const XPoint *coords = 0;
611
621
 
612
622
        if (a->speed == 0) continue;
613
623
        a->growth += a->speed;
614
624
 
615
 
        if (a->growth >= diaglim) 
 
625
        if (a->growth >= st->diaglim) 
616
626
        {
617
627
            coords = all_coords;
618
628
        }
619
 
        else if (a->growth >= orthlim)
 
629
        else if (a->growth >= st->orthlim)
620
630
        {
621
631
            coords = &all_coords[4];
622
632
        }
630
640
            int x = cell_x(a) + coords->x;
631
641
            int y = cell_y(a) + coords->y;
632
642
            coords++;
633
 
            
634
 
            if (x < 0) x = arr_width - 1;
635
 
            else if (x >= arr_width) x = 0;
636
 
            
637
 
            if (y < 0) y = arr_height - 1;
638
 
            else if (y >= arr_height) y = 0;
639
 
            
640
 
            newcell (&arr[y * arr_width + x], a->col, a->speed);
 
643
 
 
644
            if (x < 0) x = st->arr_width - 1;
 
645
            else if (x >= st->arr_width) x = 0;
 
646
            
 
647
            if (y < 0) y = st->arr_height - 1;
 
648
            else if (y >= st->arr_height) y = 0;
 
649
            
 
650
            newcell (st, &st->arr[y * st->arr_width + x], a->col, a->speed);
641
651
        }
642
652
 
643
 
        if (a->growth >= diaglim) 
644
 
            killcell (a);
 
653
        if (a->growth >= st->diaglim) 
 
654
            killcell (st, a);
645
655
    }
646
 
    
647
 
    randblip ((head->next) == tail);
648
 
    
649
 
    for (a = head->next; a != tail; a = a->next)
 
656
 
 
657
    randblip (st, (st->head->next) == st->tail);
 
658
 
 
659
    for (a = st->head->next; a != st->tail; a = a->next)
650
660
    {
651
661
        if (a->isnext) 
652
662
        {
654
664
            a->speed = a->nextspeed;
655
665
            a->growth = 0.0;
656
666
            a->col = a->nextcol;
657
 
            drawblock (cell_x(a), cell_y(a), a->col + count);
 
667
            drawblock (st, cell_x(a), cell_y(a), a->col + st->count);
658
668
        }
659
669
    }
660
670
}
661
671
 
662
 
 
663
 
char *progclass = "Petri";
664
 
 
665
 
char *defaults [] = {
 
672
static void *
 
673
petri_init (Display *dpy, Window win)
 
674
{
 
675
    struct state *st = (struct state *) calloc (1, sizeof(*st));
 
676
    st->dpy = dpy;
 
677
    st->window = win;
 
678
 
 
679
    st->delay = get_integer_resource (st->dpy, "delay", "Delay");
 
680
    st->orthlim = 1;
 
681
 
 
682
    setup_display (st);
 
683
    setup_arr (st);
 
684
    randblip (st, 1);
 
685
    
 
686
    return st;
 
687
}
 
688
 
 
689
static unsigned long
 
690
petri_draw (Display *dpy, Window window, void *closure)
 
691
{
 
692
  struct state *st = (struct state *) closure;
 
693
  update (st);
 
694
  return st->delay;
 
695
}
 
696
 
 
697
static void
 
698
petri_reshape (Display *dpy, Window window, void *closure, 
 
699
                 unsigned int w, unsigned int h)
 
700
{
 
701
}
 
702
 
 
703
static Bool
 
704
petri_event (Display *dpy, Window window, void *closure, XEvent *event)
 
705
{
 
706
  return False;
 
707
}
 
708
 
 
709
static void
 
710
petri_free (Display *dpy, Window window, void *closure)
 
711
{
 
712
  struct state *st = (struct state *) closure;
 
713
  free (st);
 
714
}
 
715
 
 
716
 
 
717
 
 
718
static const char *petri_defaults [] = {
666
719
  ".background:         black",
667
720
  ".foreground:         white",
668
721
  "*delay:              10000",
669
 
  "*count:              8",
670
 
  "*size:               4",
 
722
  "*count:              20",
 
723
  "*size:               2",
671
724
  "*diaglim:            1.414",
672
725
  "*anychan:            0.0015",
673
726
  "*minorchan:          0.5",
684
737
    0
685
738
};
686
739
 
687
 
XrmOptionDescRec options [] = {
 
740
static XrmOptionDescRec petri_options [] = {
688
741
  { "-delay",            ".delay",              XrmoptionSepArg, 0 },
689
742
  { "-size",             ".size",               XrmoptionSepArg, 0 },
690
743
  { "-count",            ".count",              XrmoptionSepArg, 0 },
703
756
  { 0, 0, 0, 0 }
704
757
};
705
758
 
706
 
void screenhack (Display *dpy, Window win)
707
 
{
708
 
    int delay = get_integer_resource ("delay", "Delay");
709
 
    display = dpy;
710
 
    window = win;
711
 
    setup_display ();
712
 
    
713
 
    setup_arr ();
714
 
    
715
 
    randblip (1);
716
 
    
717
 
    for (;;) 
718
 
    {
719
 
        update ();
720
 
        XSync (dpy, False);
721
 
        screenhack_handle_events (dpy);
722
 
        usleep (delay);
723
 
    }
724
 
}
 
759
 
 
760
XSCREENSAVER_MODULE ("Petri", petri)