ftp://ftp.smr.ru/pub/0/FreeBSD/releases/distfiles/xscreensaver-3.16.tar.gz
[xscreensaver] / hacks / mountain.c
diff --git a/hacks/mountain.c b/hacks/mountain.c
new file mode 100644 (file)
index 0000000..1853b93
--- /dev/null
@@ -0,0 +1,235 @@
+/* -*- Mode: C; tab-width: 4 -*- */
+/* mountain -- square grid mountains */
+
+#if !defined( lint ) && !defined( SABER )
+static const char sccsid[] = "@(#)mountain.c   4.04 97/07/28 xlockmore";
+
+#endif
+
+/*-
+ * Copyright (c) 1995 Pascal Pensa <pensa@aurora.unice.fr>
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appear in all copies and that
+ * both that copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * This file is provided AS IS with no warranties of any kind.  The author
+ * shall have no liability with respect to the infringement of copyrights,
+ * trade secrets or any patents by this file or any part thereof.  In no
+ * event will the author be liable for any lost revenue or profits or
+ * other special, indirect and consequential damages.
+ *
+ * Revision History:
+ * 10-May-97: Compatible with xscreensaver
+ */
+
+#ifdef STANDALONE
+# define PROGCLASS "Mountain"
+# define HACK_INIT init_mountain
+# define HACK_DRAW draw_mountain
+# define mountain_opts xlockmore_opts
+# define DEFAULTS      "*delay: 0 \n"          \
+                                       "*count: 30 \n"         \
+                                       "*cycles: 100 \n"       \
+                                       "*ncolors: 64 \n"
+# define SMOOTH_COLORS
+#include "xlockmore.h"         /* in xscreensaver distribution */
+#else /* STANDALONE */
+#include "xlock.h"             /* in xlockmore distribution */
+#endif /* STANDALONE */
+
+ModeSpecOpt mountain_opts =
+{0, NULL, 0, NULL, NULL};
+
+/* ~ 5000 Max mountain height (1000 - 10000) */
+#define MAXHEIGHT  (3 * (mp->width + mp->height))
+
+#define WORLDWIDTH 50          /* World size x * y */
+
+#define RANGE_RAND(min,max) ((min) + NRAND((max) - (min)))
+
+typedef struct {
+       int         pixelmode;
+       int         width;
+       int         height;
+       int         x, y;
+       int         offset;
+       int         stage;
+       int         h[WORLDWIDTH][WORLDWIDTH];
+       int         time;       /* up time */
+       int         first;
+       GC          stippled_GC;
+} mountainstruct;
+
+static mountainstruct *mountains = NULL;
+
+static void
+spread(int  (*m)[50], int x, int y)
+{
+       int         x2, y2;
+       int         h = m[x][y];
+
+       for (y2 = y - 1; y2 <= y + 1; y2++)
+               for (x2 = x - 1; x2 <= x + 1; x2++)
+                       if (x2 >= 0 && y2 >= 0 && x2 < WORLDWIDTH && y2 < WORLDWIDTH)
+                               m[x2][y2] = (m[x2][y2] + h) / 2;
+}
+
+static void
+drawamountain(ModeInfo * mi)
+{
+       Display    *display = MI_DISPLAY(mi);
+       Window      window = MI_WINDOW(mi);
+       GC          gc = MI_GC(mi);
+       mountainstruct *mp = &mountains[MI_SCREEN(mi)];
+       int         x2, y2, x3, y3, y4, y5, c = 0;
+       XPoint      p[5];
+
+       if (MI_NPIXELS(mi) > 2) {
+               c = (mp->h[mp->x][mp->y] + mp->h[mp->x + 1][mp->y] +
+                 mp->h[mp->x][mp->y + 1] + mp->h[mp->x + 1][mp->y + 1]) / 4;
+               c = (c / 10 + mp->offset) % MI_NPIXELS(mi);
+       }
+       x2 = mp->x * (2 * mp->width) / (3 * WORLDWIDTH);
+       y2 = mp->y * (2 * mp->height) / (3 * WORLDWIDTH);
+       p[0].x = (x2 - y2 / 2) + (mp->width / 4);
+       p[0].y = (y2 - mp->h[mp->x][mp->y]) + mp->height / 4;
+
+       x3 = (mp->x + 1) * (2 * mp->width) / (3 * WORLDWIDTH);
+       y3 = mp->y * (2 * mp->height) / (3 * WORLDWIDTH);
+       p[1].x = (x3 - y3 / 2) + (mp->width / 4);
+       p[1].y = (y3 - mp->h[mp->x + 1][mp->y]) + mp->height / 4;
+
+       y4 = (mp->y + 1) * (2 * mp->height) / (3 * WORLDWIDTH);
+       p[2].x = (x3 - y4 / 2) + (mp->width / 4);
+       p[2].y = (y4 - mp->h[mp->x + 1][mp->y + 1]) + mp->height / 4;
+
+       y5 = (mp->y + 1) * (2 * mp->height) / (3 * WORLDWIDTH);
+       p[3].x = (x2 - y5 / 2) + (mp->width / 4);
+       p[3].y = (y5 - mp->h[mp->x][mp->y + 1]) + mp->height / 4;
+
+       p[4].x = p[0].x;
+       p[4].y = p[0].y;
+
+       if (MI_NPIXELS(mi) > 2)
+               XSetForeground(display, gc, MI_PIXEL(mi, c));
+       else
+               XSetForeground(display, gc, MI_WIN_WHITE_PIXEL(mi));
+       XFillPolygon(display, window, gc, p, 4, Complex, CoordModeOrigin);
+
+       if (!mp->pixelmode) {
+               XSetForeground(display, gc, MI_WIN_BLACK_PIXEL(mi));
+               XDrawLines(display, window, gc, p, 5, CoordModeOrigin);
+       }
+       mp->x++;
+       if (mp->x == WORLDWIDTH - 1) {
+               mp->y++;
+               mp->x = 0;
+       }
+       if (mp->y == WORLDWIDTH - 1)
+               mp->stage++;
+}
+
+void
+init_mountain(ModeInfo * mi)
+{
+       mountainstruct *mp;
+       int         i, j, x, y;
+       XGCValues   gcv;
+
+       if (mountains == NULL) {
+               if ((mountains = (mountainstruct *) calloc(MI_NUM_SCREENS(mi),
+                                          sizeof (mountainstruct))) == NULL)
+                       return;
+       }
+       mp = &mountains[MI_SCREEN(mi)];
+       mp->width = MI_WIN_WIDTH(mi);
+       mp->height = MI_WIN_HEIGHT(mi);
+       mp->pixelmode = (mp->width + mp->height < 200);
+       mp->stage = 0;
+       mp->time = 0;
+       mp->x = mp->y = 0;
+       if (!mp->first) {
+               mp->first = 1;
+               gcv.foreground = MI_WIN_WHITE_PIXEL(mi);
+               gcv.background = MI_WIN_BLACK_PIXEL(mi);
+
+               mp->stippled_GC = XCreateGC(MI_DISPLAY(mi), MI_WINDOW(mi),
+                                         GCForeground | GCBackground, &gcv);
+       }
+       XClearWindow(MI_DISPLAY(mi), MI_WINDOW(mi));
+
+       for (y = 0; y < WORLDWIDTH; y++)
+               for (x = 0; x < WORLDWIDTH; x++)
+                       mp->h[x][y] = 0;
+
+       j = MI_BATCHCOUNT(mi);
+       if (j < 0)
+               j = NRAND(-j) + 1;
+       for (i = 0; i < j; i++)
+               mp->h[RANGE_RAND(1, WORLDWIDTH - 1)][RANGE_RAND(1, WORLDWIDTH - 1)] =
+                       NRAND(MAXHEIGHT);
+
+       for (y = 0; y < WORLDWIDTH; y++)
+               for (x = 0; x < WORLDWIDTH; x++)
+                       spread(mp->h, x, y);
+
+       for (y = 0; y < WORLDWIDTH; y++)
+               for (x = 0; x < WORLDWIDTH; x++) {
+                       mp->h[x][y] = mp->h[x][y] + NRAND(10) - 5;
+                       if (mp->h[x][y] < 10)
+                               mp->h[x][y] = 0;
+               }
+
+       if (MI_NPIXELS(mi) > 2)
+               mp->offset = NRAND(MI_NPIXELS(mi));
+       else
+               mp->offset = 0;
+}
+
+void
+draw_mountain(ModeInfo * mi)
+{
+       mountainstruct *mp = &mountains[MI_SCREEN(mi)];
+
+       switch (mp->stage) {
+               case 0:
+                       drawamountain(mi);
+                       break;
+               case 1:
+                       MI_PAUSE(mi) = 2000000;
+                       /*if (++mp->time > MI_CYCLES(mi)); */
+                       mp->stage++;
+                       break;
+               case 2:
+                       init_mountain(mi);
+                       break;
+       }
+}
+
+void
+release_mountain(ModeInfo * mi)
+{
+       if (mountains != NULL) {
+               int         screen;
+
+               for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) {
+                       mountainstruct *mp = &mountains[screen];
+
+                       XFreeGC(MI_DISPLAY(mi), mp->stippled_GC);
+               }
+               (void) free((void *) mountains);
+               mountains = NULL;
+       }
+}
+
+void
+refresh_mountain(ModeInfo * mi)
+{
+       mountainstruct *mp = &mountains[MI_SCREEN(mi)];
+
+       mp->x = 0;
+       mp->y = 0;
+}