From http://www.jwz.org/xscreensaver/xscreensaver-5.37.tar.gz
[xscreensaver] / hacks / crystal.c
index 15c01ba3ffb718c2fee0622dc668f405d0d6ab4f..2a12a7e2cd84421d0f8f1e7669bf9620464004f1 100644 (file)
@@ -69,17 +69,15 @@ static const char sccsid[] = "@(#)crystal.c 4.12 98/09/10 xlockmore";
  */
 
 #ifdef STANDALONE
-# define PROGCLASS             "Crystal"
-# define HACK_INIT             init_crystal
-# define HACK_DRAW             draw_crystal
-# define crystal_opts  xlockmore_opts
 # define DEFAULTS              "*delay:                60000   \n" \
                                                 "*count:                -500   \n" \
                                                 "*cycles:                200   \n" \
                                                 "*size:                  -15   \n" \
                                                 "*ncolors:               100   \n" \
-                                                "*fullrandom:   True   \n" \
-                                                "*verbose:             False   \n"
+                                                "*fpsSolid:       True \n" \
+                                                "*ignoreRotation: True \n" \
+
+# define release_crystal 0
 # include "xlockmore.h"                /* in xscreensaver distribution */
 #else /* STANDALONE */
 # include "xlock.h"                    /* in xlockmore distribution */
@@ -96,11 +94,10 @@ static const char sccsid[] = "@(#)crystal.c 4.12 98/09/10 xlockmore";
 #define DEF_MAXSIZE "False"
 #define DEF_CYCLE "True"
 
-#define min(a,b) ((a) <= (b) ? (a) : (b))
+#undef NRAND
+#define NRAND(n)           ( (n) ? (int) (LRAND() % (n)) : 0)
 
-#ifdef STANDALONE
-void release_crystal(ModeInfo * mi);
-#endif
+#define min(a,b) ((a) <= (b) ? (a) : (b))
 
 static int  nx, ny;
 
@@ -143,12 +140,12 @@ static OptionStruct desc[] =
        {"-/+shift", "turn on/off colour cycling"}
 };
 
-ModeSpecOpt crystal_opts =
+ENTRYPOINT ModeSpecOpt crystal_opts =
 {sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc};
 
 #ifdef USE_MODULES
 ModStruct   crystal_description =
-{"crystal", "init_crystal", "draw_crystal", "release_crystal",
+{"crystal", "init_crystal", "draw_crystal", NULL,
  "refresh_crystal", "init_crystal", NULL, &crystal_opts,
  60000, -40, 200, -15, 64, 1.0, "",
  "Shows polygons in 2D plane groups", 0, NULL};
@@ -560,15 +557,21 @@ crystal_drawatom(ModeInfo * mi, crystalatom * atom0)
        }
 }
 
-void
+ENTRYPOINT void init_crystal(ModeInfo * mi);
+
+
+ENTRYPOINT void
 draw_crystal(ModeInfo * mi)
 {
        Display    *display = MI_DISPLAY(mi);
        crystalstruct *cryst = &crystals[MI_SCREEN(mi)];
        int         i;
 
+#ifdef HAVE_JWXYZ      /* Don't second-guess Quartz's double-buffering */
+    XClearWindow(MI_DISPLAY(mi), MI_WINDOW(mi));
+#endif
+
        if (cryst->no_colors) {
-               release_crystal(mi);
                init_crystal(mi);
                return;
        }
@@ -578,7 +581,8 @@ draw_crystal(ModeInfo * mi)
 
 /* Rotate colours */
        if (cryst->cycle_p) {
-               rotate_colors(display, cryst->cmap, cryst->colors, cryst->ncolors,
+               rotate_colors(mi->xgwa.screen, cryst->cmap,
+                      cryst->colors, cryst->ncolors,
                              cryst->direction);
                if (!(LRAND() % 1000))
                        cryst->direction = -cryst->direction;
@@ -618,7 +622,7 @@ draw_crystal(ModeInfo * mi)
        XSetFunction(display, cryst->gc, GXcopy);
 }
 
-void
+ENTRYPOINT void
 refresh_crystal(ModeInfo * mi)
 {
        Display    *display = MI_DISPLAY(mi);
@@ -785,43 +789,35 @@ refresh_crystal(ModeInfo * mi)
        XSetFunction(display, cryst->gc, GXcopy);
 }
 
-void
-release_crystal(ModeInfo * mi)
+static void
+free_crystal(ModeInfo * mi)
 {
        Display    *display = MI_DISPLAY(mi);
+       crystalstruct *cryst = &crystals[MI_SCREEN(mi)];
 
-       if (crystals != NULL) {
-               int         screen;
-
-               for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) {
-                       crystalstruct *cryst = &crystals[screen];
-
-                       if (MI_IS_INSTALL(mi) && MI_NPIXELS(mi) > 2) {
-                               MI_WHITE_PIXEL(mi) = cryst->whitepixel;
-                               MI_BLACK_PIXEL(mi) = cryst->blackpixel;
+       if (MI_IS_INSTALL(mi) && MI_NPIXELS(mi) > 2) {
+               MI_WHITE_PIXEL(mi) = cryst->whitepixel;
+               MI_BLACK_PIXEL(mi) = cryst->blackpixel;
 #ifndef STANDALONE
-                               MI_FG_PIXEL(mi) = cryst->fg;
-                               MI_BG_PIXEL(mi) = cryst->bg;
+               MI_FG_PIXEL(mi) = cryst->fg;
+               MI_BG_PIXEL(mi) = cryst->bg;
 #endif
-                               if (cryst->colors && cryst->ncolors && !cryst->no_colors)
-                                       free_colors(display, cryst->cmap, cryst->colors, cryst->ncolors);
-                               if (cryst->colors)
-                                       (void) free((void *) cryst->colors);
+               if (cryst->colors && cryst->ncolors && !cryst->no_colors)
+                       free_colors(mi->xgwa.screen, cryst->cmap, cryst->colors,
+                        cryst->ncolors);
+               if (cryst->colors)
+                       (void) free((void *) cryst->colors);
 #if 0 /* #### wrong! -jwz */
-                               XFreeColormap(display, cryst->cmap);
+               XFreeColormap(display, cryst->cmap);
 #endif
-                       }
-                       if (cryst->gc != NULL)
-                               XFreeGC(display, cryst->gc);
-                       if (cryst->atom != NULL)
-                               (void) free((void *) cryst->atom);
-               }
-               (void) free((void *) crystals);
-               crystals = NULL;
        }
+       if (cryst->gc != NULL)
+               XFreeGC(display, cryst->gc);
+       if (cryst->atom != NULL)
+               (void) free((void *) cryst->atom);
 }
 
-void
+ENTRYPOINT void
 init_crystal(ModeInfo * mi)
 {
        Display    *display = MI_DISPLAY(mi);
@@ -833,11 +829,7 @@ init_crystal(ModeInfo * mi)
 #define MIN_CELL 200
 
 /* initialize */
-       if (crystals == NULL) {
-               if ((crystals = (crystalstruct *) calloc(MI_NUM_SCREENS(mi),
-                                           sizeof (crystalstruct))) == NULL)
-                       return;
-       }
+       MI_INIT (mi, crystals, free_crystal);
        cryst = &crystals[MI_SCREEN(mi)];
 
        if (!cryst->gc) {
@@ -980,9 +972,12 @@ init_crystal(ModeInfo * mi)
                        cryst->offset_w = (int) (cryst->b * 0.5);
                }
        } else {
+               int max_repeat = 10;
                cryst->offset_w = -1;
-               while (cryst->offset_w < 4 || (int) (cryst->offset_w - cryst->b *
-                                   sin((cryst->gamma - 90) * PI_RAD)) < 4) {
+               while (max_repeat-- && 
+                 (cryst->offset_w < 4 || (int) (cryst->offset_w - cryst->b *
+                                   sin((cryst->gamma - 90) * PI_RAD)) < 4)
+                          ) {
                        cryst->b = NRAND((int) (cryst->win_height / (cos((cryst->gamma - 90) *
                                            PI_RAD))) - cell_min) + cell_min;
                        if (cryst->planegroup > 8)
@@ -1168,7 +1163,8 @@ init_crystal(ModeInfo * mi)
        if (MI_IS_INSTALL(mi) && MI_NPIXELS(mi) > 2) {
 /* Set up colour map */
                if (cryst->colors && cryst->ncolors && !cryst->no_colors)
-                       free_colors(display, cryst->cmap, cryst->colors, cryst->ncolors);
+                       free_colors(mi->xgwa.screen, cryst->cmap,
+                        cryst->colors, cryst->ncolors);
                if (cryst->colors)
                        (void) free((void *) cryst->colors);
                cryst->colors = 0;
@@ -1197,14 +1193,20 @@ init_crystal(ModeInfo * mi)
                }
                if (!cryst->mono_p) {
                        if (!(LRAND() % 10))
-                               make_random_colormap(MI_DISPLAY(mi), MI_VISUAL(mi), cryst->cmap, cryst->colors, &cryst->ncolors,
-                                               True, True, &cryst->cycle_p, True);
+                               make_random_colormap(mi->xgwa.screen, MI_VISUAL(mi),
+                                     cryst->cmap, cryst->colors,
+                                     &cryst->ncolors,
+                                     True, True, &cryst->cycle_p, True);
                        else if (!(LRAND() % 2))
-                               make_uniform_colormap(MI_DISPLAY(mi), MI_VISUAL(mi), cryst->cmap, cryst->colors, &cryst->ncolors,
-                                                     True, &cryst->cycle_p, True);
+                               make_uniform_colormap(mi->xgwa.screen, MI_VISUAL(mi),
+                                      cryst->cmap, cryst->colors,
+                                      &cryst->ncolors, True,
+                                      &cryst->cycle_p, True);
                        else
-                               make_smooth_colormap(MI_DISPLAY(mi), MI_VISUAL(mi), cryst->cmap, cryst->colors, &cryst->ncolors,
-                                                    True, &cryst->cycle_p, True);
+                               make_smooth_colormap(mi->xgwa.screen, MI_VISUAL(mi),
+                                     cryst->cmap, cryst->colors,
+                                     &cryst->ncolors,
+                                     True, &cryst->cycle_p, True);
                }
 #if 0 /* #### wrong! -jwz */
                XInstallColormap(display, cryst->cmap);
@@ -1259,6 +1261,24 @@ init_crystal(ModeInfo * mi)
                crystal_setupatom(atom0, cryst->gamma);
                crystal_drawatom(mi, atom0);
        }
-       XSync(display, False);
        XSetFunction(display, cryst->gc, GXcopy);
 }
+
+ENTRYPOINT void
+reshape_crystal(ModeInfo * mi, int width, int height)
+{
+  init_crystal(mi);
+}
+
+ENTRYPOINT Bool
+crystal_handle_event (ModeInfo *mi, XEvent *event)
+{
+  if (screenhack_event_helper (MI_DISPLAY(mi), MI_WINDOW(mi), event))
+    {
+      reshape_crystal (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
+      return True;
+    }
+  return False;
+}
+
+XSCREENSAVER_MODULE ("Crystal", crystal)