~ubuntu-branches/ubuntu/breezy/xscreensaver/breezy

« back to all changes in this revision

Viewing changes to hacks/twang.c

  • Committer: Bazaar Package Importer
  • Author(s): Oliver Grawert
  • Date: 2005-10-11 21:00:42 UTC
  • mfrom: (2.1.1 sarge)
  • Revision ID: james.westby@ubuntu.com-20051011210042-u7q6zslgevdxspr3
Tags: 4.21-4ubuntu17
updated pt_BR again, fixed to UTF-8 

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* twang, twist around screen bits, v1.3
 
2
 * by Dan Bornstein, danfuzz@milk.com
 
3
 * Copyright (c) 2003 Dan Bornstein. All rights reserved.
 
4
 *
 
5
 * Permission to use, copy, modify, distribute, and sell this software and its
 
6
 * documentation for any purpose is hereby granted without fee, provided that
 
7
 * the above copyright notice appear in all copies and that both that
 
8
 * copyright notice and this permission notice appear in supporting
 
9
 * documentation.  No representations are made about the suitability of this
 
10
 * software for any purpose.  It is provided "as is" without express or 
 
11
 * implied warranty.
 
12
 *
 
13
 * See the included man page for more details.
 
14
 */
 
15
 
 
16
#include <math.h>
 
17
#include "screenhack.h"
 
18
#include <X11/Xutil.h>
 
19
 
 
20
#ifdef HAVE_XSHM_EXTENSION
 
21
#include "xshm.h"
 
22
#endif
 
23
 
 
24
#define FLOAT double
 
25
 
 
26
/* random float in the range (-1..1) */
 
27
#define RAND_FLOAT_PM1 \
 
28
        (((FLOAT) ((random() >> 8) & 0xffff)) / ((FLOAT) 0x10000) * 2 - 1)
 
29
 
 
30
/* random float in the range (0..1) */
 
31
#define RAND_FLOAT_01 \
 
32
        (((FLOAT) ((random() >> 8) & 0xffff)) / ((FLOAT) 0x10000))
 
33
 
 
34
 
 
35
 
 
36
/* parameters that are user configurable */
 
37
 
 
38
/* whether or not to use xshm */
 
39
#ifdef HAVE_XSHM_EXTENSION
 
40
static Bool useShm;
 
41
#endif
 
42
 
 
43
/* delay (usec) between iterations */
 
44
static int delay;
 
45
 
 
46
/* the maximum number of columns of tiles */
 
47
static int maxColumns;
 
48
 
 
49
/* the maximum number of rows of tiles */
 
50
static int maxRows;
 
51
 
 
52
/* the size (width and height) of a tile */
 
53
static int tileSize;
 
54
 
 
55
/* the width of the border around each tile */
 
56
static int borderWidth;
 
57
 
 
58
/* the chance, per iteration, of an interesting event happening */
 
59
static FLOAT eventChance;
 
60
 
 
61
/* friction: the fraction (0..1) by which velocity decreased per iteration */
 
62
static FLOAT friction;
 
63
 
 
64
/* springiness: the fraction (0..1) of the orientation that turns into 
 
65
 * velocity towards the center */
 
66
static FLOAT springiness;
 
67
 
 
68
/* transference: the fraction (0..1) of the orientations of orthogonal
 
69
 * neighbors that turns into velocity (in the same direction as the
 
70
 * orientation) */
 
71
static FLOAT transference;
 
72
 
 
73
 
 
74
 
 
75
/* non-user-modifiable immutable definitions */
 
76
 
 
77
/* width and height of the window */
 
78
static int windowWidth;
 
79
static int windowHeight;
 
80
 
 
81
static Display *display;        /* the display to draw on */
 
82
static Window window;           /* the window to draw on */
 
83
static Screen *screen;          /* the screen to draw on */
 
84
 
 
85
static XImage *sourceImage;     /* image source of stuff to draw */
 
86
static XImage *workImage;       /* work area image, used when rendering */
 
87
static XImage *backgroundImage; /* image filled with background pixels */
 
88
 
 
89
static GC backgroundGC;         /* GC for the background color */
 
90
static GC foregroundGC;         /* GC for the foreground color */
 
91
static GC borderGC;             /* GC for the border color */
 
92
unsigned long backgroundPixel;  /* background color as a pixel value */
 
93
unsigned long borderPixel;      /* border color as a pixel value */
 
94
 
 
95
#ifdef HAVE_XSHM_EXTENSION
 
96
XShmSegmentInfo shmInfo;
 
97
#endif
 
98
 
 
99
 
 
100
 
 
101
/* the model */
 
102
 
 
103
typedef struct
 
104
{
 
105
    int x;        /* x coordinate of the center of the tile */
 
106
    int y;        /* y coordinate of the center of the tile */
 
107
    FLOAT angle;  /* angle of the tile (-pi..pi) */
 
108
    FLOAT zoom;   /* log of the zoom of the tile (-1..1) */
 
109
    FLOAT vAngle; /* angular velocity (-pi/4..pi/4) */
 
110
    FLOAT vZoom;  /* zoomular velocity (-0.25..0.25) */
 
111
}
 
112
Tile;
 
113
 
 
114
static Tile *tiles;  /* array of tiles (left->right, top->bottom, row major) */
 
115
static int rows;     /* number of rows of tiles */
 
116
static int columns;  /* number of columns of tiles */
 
117
 
 
118
static Tile **sortedTiles; /* array of tile pointers, sorted by zoom */
 
119
static int tileCount;     /* total number of tiles */
 
120
 
 
121
#define TILE_AT(col,row) (&tiles[(row) * columns + (col)])
 
122
 
 
123
#define MAX_VANGLE (M_PI / 4.0)
 
124
#define MAX_VZOOM 0.25
 
125
 
 
126
#define RAND_ANGLE (RAND_FLOAT_PM1 * M_PI)
 
127
#define RAND_ZOOM (RAND_FLOAT_PM1)
 
128
#define RAND_VANGLE (RAND_FLOAT_PM1 * MAX_VANGLE)
 
129
#define RAND_VZOOM (RAND_FLOAT_PM1 * MAX_VZOOM)
 
130
 
 
131
 
 
132
 
 
133
/*
 
134
 * overall setup stuff
 
135
 */
 
136
 
 
137
/* grab the source image */
 
138
static void grabImage (XWindowAttributes *xwa)
 
139
{
 
140
    XFillRectangle (display, window, backgroundGC, 0, 0, 
 
141
                    windowWidth, windowHeight);
 
142
    backgroundImage = 
 
143
        XGetImage (display, window, 0, 0, windowWidth, windowHeight,
 
144
                   ~0L, ZPixmap);
 
145
 
 
146
    load_random_image (screen, window, window, NULL, NULL);
 
147
    sourceImage = XGetImage (display, window, 0, 0, windowWidth, windowHeight,
 
148
                             ~0L, ZPixmap);
 
149
 
 
150
#ifdef HAVE_XSHM_EXTENSION
 
151
    workImage = NULL;
 
152
    if (useShm) 
 
153
    {
 
154
        workImage = create_xshm_image (display, xwa->visual, xwa->depth,
 
155
                                       ZPixmap, 0, &shmInfo, 
 
156
                                       windowWidth, windowHeight);
 
157
        if (!workImage) 
 
158
        {
 
159
            useShm = False;
 
160
            fprintf (stderr, "create_xshm_image failed\n");
 
161
        }
 
162
    }
 
163
 
 
164
    if (workImage == NULL)
 
165
#endif /* HAVE_XSHM_EXTENSION */
 
166
 
 
167
        /* just use XSubImage to acquire the right visual, depth, etc;
 
168
         * easier than the other alternatives */
 
169
        workImage = XSubImage (sourceImage, 0, 0, windowWidth, windowHeight);
 
170
}
 
171
 
 
172
/* set up the system */
 
173
static void setup (void)
 
174
{
 
175
    XWindowAttributes xgwa;
 
176
    XGCValues gcv;
 
177
 
 
178
    XGetWindowAttributes (display, window, &xgwa);
 
179
 
 
180
    screen = xgwa.screen;
 
181
    windowWidth = xgwa.width;
 
182
    windowHeight = xgwa.height;
 
183
 
 
184
    gcv.line_width = borderWidth;
 
185
    gcv.foreground = get_pixel_resource ("borderColor", "BorderColor",
 
186
                                         display, xgwa.colormap);
 
187
    borderPixel = gcv.foreground;
 
188
    borderGC = XCreateGC (display, window, GCForeground | GCLineWidth, 
 
189
                          &gcv);
 
190
 
 
191
    gcv.foreground = get_pixel_resource ("background", "Background",
 
192
                                         display, xgwa.colormap);
 
193
    backgroundPixel = gcv.foreground;
 
194
    backgroundGC = XCreateGC (display, window, GCForeground, &gcv);
 
195
 
 
196
    gcv.foreground = get_pixel_resource ("foreground", "Foreground",
 
197
                                         display, xgwa.colormap);
 
198
    foregroundGC = XCreateGC (display, window, GCForeground, &gcv);
 
199
 
 
200
    grabImage (&xgwa);
 
201
}
 
202
 
 
203
 
 
204
 
 
205
/*
 
206
 * the simulation
 
207
 */
 
208
 
 
209
/* event: randomize all the angular velocities */
 
210
static void randomizeAllAngularVelocities (void)
 
211
{
 
212
    int c;
 
213
    int r;
 
214
 
 
215
    for (r = 0; r < rows; r++)
 
216
    {
 
217
        for (c = 0; c < columns; c++)
 
218
        {
 
219
            TILE_AT (c, r)->vAngle = RAND_VANGLE;
 
220
        }
 
221
    }
 
222
}
 
223
 
 
224
/* event: randomize all the zoomular velocities */
 
225
static void randomizeAllZoomularVelocities (void)
 
226
{
 
227
    int c;
 
228
    int r;
 
229
 
 
230
    for (r = 0; r < rows; r++)
 
231
    {
 
232
        for (c = 0; c < columns; c++)
 
233
        {
 
234
            TILE_AT (c, r)->vZoom = RAND_VZOOM;
 
235
        }
 
236
    }
 
237
}
 
238
 
 
239
/* event: randomize all the velocities */
 
240
static void randomizeAllVelocities (void)
 
241
{
 
242
    randomizeAllAngularVelocities ();
 
243
    randomizeAllZoomularVelocities ();
 
244
}
 
245
 
 
246
/* event: randomize all the angular orientations */
 
247
static void randomizeAllAngularOrientations (void)
 
248
{
 
249
    int c;
 
250
    int r;
 
251
 
 
252
    for (r = 0; r < rows; r++)
 
253
    {
 
254
        for (c = 0; c < columns; c++)
 
255
        {
 
256
            TILE_AT (c, r)->angle = RAND_ANGLE;
 
257
        }
 
258
    }
 
259
}
 
260
 
 
261
/* event: randomize all the zoomular orientations */
 
262
static void randomizeAllZoomularOrientations (void)
 
263
{
 
264
    int c;
 
265
    int r;
 
266
 
 
267
    for (r = 0; r < rows; r++)
 
268
    {
 
269
        for (c = 0; c < columns; c++)
 
270
        {
 
271
            TILE_AT (c, r)->zoom = RAND_ZOOM;
 
272
        }
 
273
    }
 
274
}
 
275
 
 
276
/* event: randomize all the orientations */
 
277
static void randomizeAllOrientations (void)
 
278
{
 
279
    randomizeAllAngularOrientations ();
 
280
    randomizeAllZoomularOrientations ();
 
281
}
 
282
 
 
283
/* event: randomize everything */
 
284
static void randomizeEverything (void)
 
285
{
 
286
    randomizeAllVelocities ();
 
287
    randomizeAllOrientations ();
 
288
}
 
289
 
 
290
/* event: pick one tile and randomize all its stats */
 
291
static void randomizeOneTile (void)
 
292
{
 
293
    int c = RAND_FLOAT_01 * columns;
 
294
    int r = RAND_FLOAT_01 * rows;
 
295
 
 
296
    Tile *t = TILE_AT (c, r);
 
297
    t->angle = RAND_ANGLE;
 
298
    t->zoom = RAND_ZOOM;
 
299
    t->vAngle = RAND_VANGLE;
 
300
    t->vZoom = RAND_VZOOM;
 
301
}
 
302
 
 
303
/* event: pick one row and randomize everything about each of its tiles */
 
304
static void randomizeOneRow (void)
 
305
{
 
306
    int c;
 
307
    int r = RAND_FLOAT_01 * rows;
 
308
 
 
309
    for (c = 0; c < columns; c++)
 
310
    {
 
311
        Tile *t = TILE_AT (c, r);
 
312
        t->angle = RAND_ANGLE;
 
313
        t->zoom = RAND_ZOOM;
 
314
        t->vAngle = RAND_VANGLE;
 
315
        t->vZoom = RAND_VZOOM;
 
316
    }
 
317
}
 
318
 
 
319
/* event: pick one column and randomize everything about each of its tiles */
 
320
static void randomizeOneColumn (void)
 
321
{
 
322
    int c = RAND_FLOAT_01 * columns;
 
323
    int r;
 
324
 
 
325
    for (r = 0; r < rows; r++)
 
326
    {
 
327
        Tile *t = TILE_AT (c, r);
 
328
        t->angle = RAND_ANGLE;
 
329
        t->zoom = RAND_ZOOM;
 
330
        t->vAngle = RAND_VANGLE;
 
331
        t->vZoom = RAND_VZOOM;
 
332
    }
 
333
}
 
334
 
 
335
/* do model event processing */
 
336
static void modelEvents (void)
 
337
{
 
338
    int which;
 
339
 
 
340
    if (RAND_FLOAT_01 > eventChance)
 
341
    {
 
342
        return;
 
343
    }
 
344
 
 
345
    which = RAND_FLOAT_01 * 10;
 
346
 
 
347
    switch (which)
 
348
    {
 
349
        case 0: randomizeAllAngularVelocities ();    break;
 
350
        case 1: randomizeAllZoomularVelocities ();   break;
 
351
        case 2: randomizeAllVelocities ();           break;
 
352
        case 3: randomizeAllAngularOrientations ();  break;
 
353
        case 4: randomizeAllZoomularOrientations (); break;
 
354
        case 5: randomizeAllOrientations ();         break;
 
355
        case 6: randomizeEverything ();              break;
 
356
        case 7: randomizeOneTile ();                 break;
 
357
        case 8: randomizeOneColumn ();               break;
 
358
        case 9: randomizeOneRow ();                  break;
 
359
    }
 
360
}
 
361
 
 
362
/* update the model for one iteration */
 
363
static void updateModel (void)
 
364
{
 
365
    int r;
 
366
    int c;
 
367
 
 
368
    /* for each tile, decrease its velocities according to the friction,
 
369
     * and increase them based on its current orientation and the orientations
 
370
     * of its orthogonal neighbors */
 
371
    for (r = 0; r < rows; r++)
 
372
    {
 
373
        for (c = 0; c < columns; c++)
 
374
        {
 
375
            Tile *t = TILE_AT (c, r);
 
376
            FLOAT a = t->angle;
 
377
            FLOAT z = t->zoom;
 
378
            FLOAT va = t->vAngle;
 
379
            FLOAT vz = t->vZoom;
 
380
 
 
381
            va -= t->angle * springiness;
 
382
            vz -= t->zoom * springiness;
 
383
 
 
384
            if (c > 0)
 
385
            {
 
386
                Tile *t2 = TILE_AT (c - 1, r);
 
387
                va += (t2->angle - a) * transference;
 
388
                vz += (t2->zoom - z) * transference;
 
389
            }
 
390
 
 
391
            if (c < (columns - 1))
 
392
            {
 
393
                Tile *t2 = TILE_AT (c + 1, r);
 
394
                va += (t2->angle - a) * transference;
 
395
                vz += (t2->zoom - z) * transference;
 
396
            }
 
397
 
 
398
            if (r > 0)
 
399
            {
 
400
                Tile *t2 = TILE_AT (c, r - 1);
 
401
                va += (t2->angle - a) * transference;
 
402
                vz += (t2->zoom - z) * transference;
 
403
            }
 
404
 
 
405
            if (r < (rows - 1))
 
406
            {
 
407
                Tile *t2 = TILE_AT (c, r + 1);
 
408
                va += (t2->angle - a) * transference;
 
409
                vz += (t2->zoom - z) * transference;
 
410
            }
 
411
 
 
412
            va *= (1.0 - friction);
 
413
            vz *= (1.0 - friction);
 
414
 
 
415
            if (va > MAX_VANGLE) va = MAX_VANGLE;
 
416
            else if (va < -MAX_VANGLE) va = -MAX_VANGLE;
 
417
            t->vAngle = va;
 
418
 
 
419
            if (vz > MAX_VZOOM) vz = MAX_VZOOM;
 
420
            else if (vz < -MAX_VZOOM) vz = -MAX_VZOOM;
 
421
            t->vZoom = vz;
 
422
        }
 
423
    }
 
424
 
 
425
    /* for each tile, update its orientation based on its velocities */
 
426
    for (r = 0; r < rows; r++)
 
427
    {
 
428
        for (c = 0; c < columns; c++)
 
429
        {
 
430
            Tile *t = TILE_AT (c, r);
 
431
            FLOAT a = t->angle + t->vAngle;
 
432
            FLOAT z = t->zoom + t->vZoom;
 
433
 
 
434
            if (a > M_PI) a = M_PI;
 
435
            else if (a < -M_PI) a = -M_PI;
 
436
            t->angle = a;
 
437
 
 
438
            if (z > 1.0) z = 1.0;
 
439
            else if (z < -1.0) z = -1.0;
 
440
            t->zoom = z;
 
441
        }
 
442
    }
 
443
}
 
444
 
 
445
/* the comparator to us to sort the tiles (used immediately below); it'd
 
446
 * sure be nice if C allowed inner functions (or jeebus-forbid *real
 
447
 * closures*!) */
 
448
static int sortTilesComparator (const void *v1, const void *v2)
 
449
{
 
450
    Tile *t1 = *(Tile **) v1;
 
451
    Tile *t2 = *(Tile **) v2;
 
452
    
 
453
    if (t1->zoom < t2->zoom)
 
454
    {
 
455
        return -1;
 
456
    }
 
457
 
 
458
    if (t1->zoom > t2->zoom)
 
459
    {
 
460
        return 1;
 
461
    }
 
462
 
 
463
    return 0;
 
464
}
 
465
 
 
466
/* sort the tiles in sortedTiles by zoom */
 
467
static void sortTiles (void)
 
468
{
 
469
    qsort (sortedTiles, tileCount, sizeof (Tile *), sortTilesComparator);
 
470
}
 
471
 
 
472
/* render the given tile */
 
473
static void renderTile (Tile *t)
 
474
{
 
475
    /* note: the zoom as stored per tile is log-based (centered on 0, with
 
476
     * 0 being no zoom, but the range for zoom-as-drawn is 0.4..2.5,
 
477
     * hence the alteration of t->zoom, below */
 
478
 
 
479
    int x, y;
 
480
 
 
481
    int tx = t->x;
 
482
    int ty = t->y;
 
483
 
 
484
    FLOAT zoom = pow (2.5, t->zoom);
 
485
    FLOAT ang = -t->angle;
 
486
    FLOAT sinAng = sin (ang);
 
487
    FLOAT cosAng = cos (ang);
 
488
 
 
489
    FLOAT innerBorder = (tileSize - borderWidth) / 2.0;
 
490
    FLOAT outerBorder = innerBorder + borderWidth;
 
491
 
 
492
    int maxCoord = outerBorder * zoom * (fabs (sinAng) + fabs (cosAng));
 
493
    int minX = tx - maxCoord;
 
494
    int maxX = tx + maxCoord;
 
495
    int minY = ty - maxCoord;
 
496
    int maxY = ty + maxCoord;
 
497
 
 
498
    FLOAT prey;
 
499
 
 
500
    if (minX < 0) minX = 0;
 
501
    if (maxX > windowWidth) maxX = windowWidth;
 
502
    if (minY < 0) minY = 0;
 
503
    if (maxY > windowHeight) maxY = windowHeight;
 
504
 
 
505
    sinAng /= zoom;
 
506
    cosAng /= zoom;
 
507
 
 
508
    for (y = minY, prey = y - ty; y < maxY; y++, prey++)
 
509
    {
 
510
        FLOAT prex = minX - tx;
 
511
        FLOAT srcx = prex * cosAng - prey * sinAng;
 
512
        FLOAT srcy = prex * sinAng + prey * cosAng;
 
513
 
 
514
        for (x = minX; 
 
515
             x < maxX; 
 
516
             x++, srcx += cosAng, srcy += sinAng)
 
517
        {
 
518
            if ((srcx < -innerBorder) || (srcx >= innerBorder) ||
 
519
                (srcy < -innerBorder) || (srcy >= innerBorder))
 
520
            {
 
521
                if ((srcx < -outerBorder) || (srcx >= outerBorder) ||
 
522
                    (srcy < -outerBorder) || (srcy >= outerBorder))
 
523
                {
 
524
                    continue;
 
525
                }
 
526
                XPutPixel (workImage, x, y, borderPixel);
 
527
            }
 
528
            else
 
529
            {
 
530
                unsigned long p = 
 
531
                    XGetPixel (sourceImage, srcx + tx, srcy + ty);
 
532
                XPutPixel (workImage, x, y, p);
 
533
            }
 
534
        }
 
535
    }
 
536
}
 
537
 
 
538
/* render and display the current model */
 
539
static void renderFrame (void)
 
540
{
 
541
    int n;
 
542
 
 
543
    memcpy (workImage->data, backgroundImage->data, 
 
544
            workImage->bytes_per_line * workImage->height);
 
545
 
 
546
    sortTiles ();
 
547
 
 
548
    for (n = 0; n < tileCount; n++)
 
549
    {
 
550
        renderTile (sortedTiles[n]);
 
551
    }
 
552
 
 
553
#ifdef HAVE_XSHM_EXTENSION
 
554
    if (useShm)
 
555
        XShmPutImage (display, window, backgroundGC, workImage, 0, 0, 0, 0,
 
556
                      windowWidth, windowHeight, False);
 
557
    else
 
558
#endif /* HAVE_XSHM_EXTENSION */
 
559
        XPutImage (display, window, backgroundGC, workImage, 
 
560
                   0, 0, 0, 0, windowWidth, windowHeight);
 
561
}
 
562
 
 
563
/* set up the model */
 
564
static void setupModel (void)
 
565
{
 
566
    int c;
 
567
    int r;
 
568
 
 
569
    int leftX; /* x of the center of the top-left tile */
 
570
    int topY;  /* y of the center of the top-left tile */
 
571
 
 
572
    if (tileSize > (windowWidth / 2))
 
573
    {
 
574
        tileSize = windowWidth / 2;
 
575
    }
 
576
 
 
577
    if (tileSize > (windowHeight / 2))
 
578
    {
 
579
        tileSize = windowHeight / 2;
 
580
    }
 
581
 
 
582
    columns = windowWidth / tileSize;
 
583
    rows = windowHeight / tileSize;
 
584
 
 
585
    if ((maxColumns != 0) && (columns > maxColumns))
 
586
    {
 
587
        columns = maxColumns;
 
588
    }
 
589
 
 
590
    if ((maxRows != 0) && (rows > maxRows))
 
591
    {
 
592
        rows = maxRows;
 
593
    }
 
594
 
 
595
    tileCount = rows * columns;
 
596
 
 
597
    leftX = (windowWidth - (columns * tileSize) + tileSize) / 2;
 
598
    topY = (windowHeight - (rows * tileSize) + tileSize) / 2;
 
599
 
 
600
    tiles = calloc (tileCount, sizeof (Tile));
 
601
    sortedTiles = calloc (tileCount, sizeof (Tile *));
 
602
 
 
603
    for (r = 0; r < rows; r++)
 
604
    {
 
605
        for (c = 0; c < columns; c++)
 
606
        {
 
607
            Tile *t = TILE_AT (c, r);
 
608
            t->x = leftX + c * tileSize;
 
609
            t->y = topY + r * tileSize;
 
610
            sortedTiles[c + r * columns] = t;
 
611
        }
 
612
    }
 
613
 
 
614
    randomizeEverything ();
 
615
}
 
616
 
 
617
/* do one iteration */
 
618
static void oneIteration (void)
 
619
{
 
620
    modelEvents ();
 
621
    updateModel ();
 
622
    renderFrame ();
 
623
}
 
624
 
 
625
 
 
626
 
 
627
/* main and options and stuff */
 
628
 
 
629
char *progclass = "Twang";
 
630
 
 
631
char *defaults [] = {
 
632
    ".background:       black",
 
633
    ".foreground:       white",
 
634
    "*borderColor:      blue",
 
635
    "*borderWidth:      3",
 
636
    "*delay:            10000",
 
637
    "*eventChance:      0.01",
 
638
    "*friction:         0.05",
 
639
    "*maxColumns:       0",
 
640
    "*maxRows:          0",
 
641
    "*springiness:      0.1",
 
642
    "*tileSize:         120",
 
643
    "*transference:     0.025",
 
644
#ifdef HAVE_XSHM_EXTENSION
 
645
    "*useSHM: True",
 
646
#endif
 
647
    0
 
648
};
 
649
 
 
650
XrmOptionDescRec options [] = {
 
651
  { "-border-color",     ".borderColor",    XrmoptionSepArg, 0 },
 
652
  { "-border-width",     ".borderWidth",    XrmoptionSepArg, 0 },
 
653
  { "-delay",            ".delay",          XrmoptionSepArg, 0 },
 
654
  { "-event-chance",     ".eventChance",    XrmoptionSepArg, 0 },
 
655
  { "-friction",         ".friction",       XrmoptionSepArg, 0 },
 
656
  { "-max-columns",      ".maxColumns",     XrmoptionSepArg, 0 },
 
657
  { "-max-rows",         ".maxRows",        XrmoptionSepArg, 0 },
 
658
  { "-springiness",      ".springiness",    XrmoptionSepArg, 0 },
 
659
  { "-tile-size",        ".tileSize",       XrmoptionSepArg, 0 },
 
660
  { "-transference",     ".transference",   XrmoptionSepArg, 0 },
 
661
#ifdef HAVE_XSHM_EXTENSION
 
662
  { "-shm",              ".useSHM",         XrmoptionNoArg, "True" },
 
663
  { "-no-shm",           ".useSHM",         XrmoptionNoArg, "False" },
 
664
#endif
 
665
  { 0, 0, 0, 0 }
 
666
};
 
667
 
 
668
/* initialize the user-specifiable params */
 
669
static void initParams (void)
 
670
{
 
671
    int problems = 0;
 
672
 
 
673
    borderWidth = get_integer_resource ("borderWidth", "Integer");
 
674
    if (borderWidth < 0)
 
675
    {
 
676
        fprintf (stderr, "error: border width must be at least 0\n");
 
677
        problems = 1;
 
678
    }
 
679
 
 
680
    delay = get_integer_resource ("delay", "Delay");
 
681
    if (delay < 0)
 
682
    {
 
683
        fprintf (stderr, "error: delay must be at least 0\n");
 
684
        problems = 1;
 
685
    }
 
686
 
 
687
    eventChance = get_float_resource ("eventChance", "Double");
 
688
    if ((eventChance < 0.0) || (eventChance > 1.0))
 
689
    {
 
690
        fprintf (stderr, "error: eventChance must be in the range 0..1\n");
 
691
        problems = 1;
 
692
    }
 
693
 
 
694
    friction = get_float_resource ("friction", "Double");
 
695
    if ((friction < 0.0) || (friction > 1.0))
 
696
    {
 
697
        fprintf (stderr, "error: friction must be in the range 0..1\n");
 
698
        problems = 1;
 
699
    }
 
700
 
 
701
    maxColumns = get_integer_resource ("maxColumns", "Integer");
 
702
    if (maxColumns < 0)
 
703
    {
 
704
        fprintf (stderr, "error: max columns must be at least 0\n");
 
705
        problems = 1;
 
706
    }
 
707
 
 
708
    maxRows = get_integer_resource ("maxRows", "Integer");
 
709
    if (maxRows < 0)
 
710
    {
 
711
        fprintf (stderr, "error: max rows must be at least 0\n");
 
712
        problems = 1;
 
713
    }
 
714
 
 
715
    springiness = get_float_resource ("springiness", "Double");
 
716
    if ((springiness < 0.0) || (springiness > 1.0))
 
717
    {
 
718
        fprintf (stderr, "error: springiness must be in the range 0..1\n");
 
719
        problems = 1;
 
720
    }
 
721
 
 
722
    tileSize = get_integer_resource ("tileSize", "Integer");
 
723
    if (tileSize < 1)
 
724
    {
 
725
        fprintf (stderr, "error: tile size must be at least 1\n");
 
726
        problems = 1;
 
727
    }
 
728
    
 
729
    transference = get_float_resource ("transference", "Double");
 
730
    if ((transference < 0.0) || (transference > 1.0))
 
731
    {
 
732
        fprintf (stderr, "error: transference must be in the range 0..1\n");
 
733
        problems = 1;
 
734
    }
 
735
 
 
736
#ifdef HAVE_XSHM_EXTENSION
 
737
    useShm = get_boolean_resource ("useSHM", "Boolean");
 
738
#endif
 
739
 
 
740
    if (problems)
 
741
    {
 
742
        exit (1);
 
743
    }
 
744
}
 
745
 
 
746
/* main function */
 
747
void screenhack (Display *dpy, Window win)
 
748
{
 
749
    display = dpy;
 
750
    window = win;
 
751
 
 
752
    initParams ();
 
753
    setup ();
 
754
    setupModel ();
 
755
 
 
756
    for (;;) 
 
757
    {
 
758
        oneIteration ();
 
759
        XSync (dpy, False);
 
760
        screenhack_handle_events (dpy);
 
761
        usleep (delay);
 
762
    }
 
763
}