http://www.jwz.org/xscreensaver/xscreensaver-5.09.tar.gz
authorZygo Blaxell <zblaxell@faye.furryterror.org>
Fri, 11 Sep 2009 03:31:03 +0000 (23:31 -0400)
committerZygo Blaxell <zblaxell@faye.furryterror.org>
Fri, 8 Feb 2013 17:54:56 +0000 (12:54 -0500)
-rw-r--r-- 1 zblaxell zblaxell 5549665 Sep  3 05:08 xscreensaver-5.09.tar.gz
24cb3d04244ee6f89c16866f0eed93a8d16d0de2  xscreensaver-5.09.tar.gz

97 files changed:
OSX/._InvertedSlider.m [new file with mode: 0644]
OSX/._PrefsReader.m [deleted file]
OSX/._SaverTester.m [new file with mode: 0644]
OSX/._XScreenSaver.icns
OSX/._XScreenSaverView.m [new file with mode: 0644]
OSX/._osxgrabscreen.m [new file with mode: 0644]
OSX/InvertedSlider.m
OSX/Makefile
OSX/PrefsReader.m
OSX/SaverTester.m
OSX/SaverTester.plist
OSX/XScreenSaver.plist
OSX/XScreenSaverConfigSheet.m
OSX/XScreenSaverGLView.h
OSX/XScreenSaverGLView.m
OSX/XScreenSaverView.m
OSX/bindist.rtf
OSX/jwxyz.h
OSX/jwxyz.m
OSX/osxgrabscreen.m
OSX/update-info-plist.pl
README
aclocal.m4
configure
configure.in
driver/Makefile.in
driver/XScreenSaver.ad.in
driver/XScreenSaver_ad.h
driver/dpms.c
driver/mlstring.c
driver/remote.c
driver/screens.c
driver/timers.c
driver/xscreensaver-getimage-file
driver/xscreensaver-text
hacks/._fps.c [new file with mode: 0644]
hacks/Makefile.in
hacks/config/._klein.xml [new file with mode: 0644]
hacks/config/README
hacks/config/cube21.xml
hacks/config/juggler3d.xml
hacks/config/klein.xml
hacks/config/ripples.xml
hacks/config/rubikblocks.xml [new file with mode: 0644]
hacks/config/surfaces.xml [new file with mode: 0644]
hacks/eruption.man
hacks/fps.c
hacks/glx/._grab-ximage.c [new file with mode: 0644]
hacks/glx/._rubikblocks.man [new file with mode: 0644]
hacks/glx/Makefile.in
hacks/glx/blinkbox.c
hacks/glx/blinkbox.man
hacks/glx/cube21.c
hacks/glx/flurry.h
hacks/glx/fps-gl.c
hacks/glx/glhanoi.c
hacks/glx/glxfonts.c
hacks/glx/glxfonts.h
hacks/glx/grab-ximage.c
hacks/glx/juggler3d.c
hacks/glx/juggler3d.man
hacks/glx/klein.c
hacks/glx/klein.man
hacks/glx/mirrorblob.c
hacks/glx/molecule.c
hacks/glx/photopile.c
hacks/glx/rubikblocks.c [new file with mode: 0644]
hacks/glx/rubikblocks.man [new file with mode: 0644]
hacks/glx/sonar-icmp.c
hacks/glx/sonar.c
hacks/glx/surfaces.c [new file with mode: 0644]
hacks/glx/surfaces.man [new file with mode: 0644]
hacks/glx/texfont.c
hacks/glx/topblock.c
hacks/glx/topblock.man
hacks/glx/voronoi.c
hacks/glx/xlock-gl-utils.c
hacks/goop.c
hacks/juggle.man [deleted file]
hacks/metaballs.man
hacks/munge-ad.pl
hacks/noseguy.c
hacks/phosphor.c
hacks/shadebobs.c
hacks/truchet.man
hacks/vermiculate.c
hacks/webcollage
hacks/webcollage-helper-cocoa.m
po/Makefile.in.in
po/POTFILES.in
setup.com
utils/._colors.c [new file with mode: 0644]
utils/Makefile.in
utils/version.h
utils/visual-gl.c
xscreensaver.spec
xscreensaver.xcodeproj/project.pbxproj

diff --git a/OSX/._InvertedSlider.m b/OSX/._InvertedSlider.m
new file mode 100644 (file)
index 0000000..072bc5c
Binary files /dev/null and b/OSX/._InvertedSlider.m differ
diff --git a/OSX/._PrefsReader.m b/OSX/._PrefsReader.m
deleted file mode 100644 (file)
index 3d666b3..0000000
Binary files a/OSX/._PrefsReader.m and /dev/null differ
diff --git a/OSX/._SaverTester.m b/OSX/._SaverTester.m
new file mode 100644 (file)
index 0000000..dae644c
Binary files /dev/null and b/OSX/._SaverTester.m differ
index 4ec02b270045e5c5d5031f8f1541f0ba26027fd1..d28a0afd23fdf63259eab051a901ac3c9b925491 100644 (file)
Binary files a/OSX/._XScreenSaver.icns and b/OSX/._XScreenSaver.icns differ
diff --git a/OSX/._XScreenSaverView.m b/OSX/._XScreenSaverView.m
new file mode 100644 (file)
index 0000000..5e2d01f
Binary files /dev/null and b/OSX/._XScreenSaverView.m differ
diff --git a/OSX/._osxgrabscreen.m b/OSX/._osxgrabscreen.m
new file mode 100644 (file)
index 0000000..bf488b2
Binary files /dev/null and b/OSX/._osxgrabscreen.m differ
index e5c23b28abd28daaeac503b50bcd2e88fe0669f8..d2060d950abf0128f937db282434e97c810edf4a 100644 (file)
@@ -70,7 +70,7 @@
 /* Implment all setter methods in terms of "setDoubleValue", above.
  */
 
--(void) setFloatValue:(double)v
+-(void) setFloatValue:(float)v
 {
   [self setDoubleValue:(double)v];
 }
index c1ad1fb7c995163f778f7745c6f057278525fb00..03fc9899a522387620ec083c5f09087f6c5589d7 100644 (file)
@@ -103,7 +103,9 @@ dmg:: distdepend check_versions
                                                                              \
   retired=`perl -0 -ne                                                       \
      's/\\\\\\n//g; m/^RETIRED_EXES\s*=\s*(.*)$$/m && print "$$1\n"'         \
-      ../hacks/Makefile.in                                                   \
+      ../hacks/Makefile.in ;                                                 \
+      perl -0 -ne                                                            \
+     's/\\\\\\n//g; m/^RETIRED_GL_EXES\s*=\s*(.*)$$/m && print "$$1\n"'              \
       ../hacks/glx/Makefile.in` ;                                            \
                                                                              \
   for f in $$SRC/*.saver ; do                                                \
index e3be145696d796f25f9c84fb0f42bdc84646f315..507a557b09b5cbdc498d77f2c6b48f4a370ed923 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 2006-2008 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 2006-2009 Jamie Zawinski <jwz@jwz.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
     strcpy (result, result+1);
   }
 
+  // Kludge: assume that any string that begins with "~" and has a "/"
+  // anywhere in it should be expanded as if it is a pathname.
+  if (result[0] == '~' && strchr (result, '/')) {
+    os = [NSString stringWithCString:result encoding:NSUTF8StringEncoding];
+    free (result);
+    result = strdup ([[os stringByExpandingTildeInPath]
+                       cStringUsingEncoding:NSUTF8StringEncoding]);
+  }
+
   return result;
 }
 
index 4ea79aaae06933b72fefdbfb29e111c41abee197..a2ab493756581e8bc669dbe0694a2f67050bb2c1 100644 (file)
@@ -184,7 +184,7 @@ find_saverView (NSView *v)
     [NSUserDefaultsController sharedUserDefaultsController];
   [prefs addObserver:self
          forKeyPath:key
-            options:nil
+            options:0
             context:@selector(selectedSaverDidChange:)];
   [popup   bind:@"selectedObject"
        toObject:prefs
index 4a5dcba74ca7478cc163d32c7da17c3878e3e3df..edcbb3583219bfff058557bd0e33b4c4f2fa6d25 100644 (file)
        <key>CFBundlePackageType</key>
        <string>APPL</string>
        <key>CFBundleShortVersionString</key>
-       <string>5.08</string>
+       <string>5.09</string>
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleVersion</key>
-       <string>5.08</string>
+       <string>5.09</string>
        <key>LSMinimumSystemVersion</key>
-       <string>10.4.0</string>
+       <string>10.4</string>
        <key>NSMainNibFile</key>
        <string>SaverTester</string>
        <key>NSPrincipalClass</key>
index 48fcdd0d139c363442dac1ea7654da79af6f0368..c3f76020cc4348a8a466abc0ab9013810f5ada0c 100644 (file)
        <key>CFBundlePackageType</key>
        <string>BNDL</string>
        <key>CFBundleShortVersionString</key>
-       <string>5.08</string>
+       <string>5.09</string>
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleVersion</key>
-       <string>5.08</string>
+       <string>5.09</string>
        <key>LSMinimumSystemVersion</key>
-       <string>10.4.0</string>
+       <string>10.4</string>
        <key>NSMainNibFile</key>
        <string>SaverTester</string>
        <key>NSPrincipalClass</key>
index 06804c70429b915d84eb34dcbe30ad90fde0889c..40b638c8e4f90156ebf54135acc0529fdfc101b0 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 2006-2008 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 2006-2009 Jamie Zawinski <jwz@jwz.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
@@ -483,7 +483,7 @@ do_file_selector (NSTextField *txt, BOOL dirs_p)
                                      types:nil];
   if (result == NSOKButton) {
     NSArray *files = [panel filenames];
-    NSString *file = ([files count] > 0 ? [files objectAtIndex:0] : @"");
+    file = ([files count] > 0 ? [files objectAtIndex:0] : @"");
     file = [file stringByAbbreviatingWithTildeInPath];
     [txt setStringValue:file];
 
@@ -1047,6 +1047,7 @@ static char *
 anchorize (const char *url)
 {
   const char *wiki = "http://en.wikipedia.org/wiki/";
+  const char *math = "http://mathworld.wolfram.com/";
   if (!strncmp (wiki, url, strlen(wiki))) {
     char *anchor = (char *) malloc (strlen(url) * 3 + 10);
     strcpy (anchor, "Wikipedia: \"");
@@ -1076,6 +1077,29 @@ anchorize (const char *url)
     *out = 0;
     return anchor;
 
+  } else if (!strncmp (math, url, strlen(math))) {
+    char *anchor = (char *) malloc (strlen(url) * 3 + 10);
+    strcpy (anchor, "MathWorld: \"");
+    const char *start = url + strlen(wiki);
+    const char *in = start;
+    char *out = anchor + strlen(anchor);
+    while (*in) {
+      if (*in == '_') {
+        *out++ = ' ';
+      } else if (in != start && *in >= 'A' && *in <= 'Z') {
+        *out++ = ' ';
+        *out++ = *in;
+      } else if (!strncmp (in, ".htm", 4)) {
+        break;
+      } else {
+        *out++ = *in;
+      }
+      in++;
+    }
+    *out++ = '"';
+    *out = 0;
+    return anchor;
+
   } else {
     return strdup (url);
   }
@@ -1606,6 +1630,10 @@ fix_contentview_size (NSView *parent)
   f = [text frame];
   float dh = f.size.height - oh;
   f.origin.y += dh;
+
+  // #### This is needed in OSX 10.5, but is wrong in OSX 10.6.  WTF??
+  //      If we do this in 10.6, the text field moves down, off the window.
+  //      So instead we repair it at the end, at the "WTF2" comment.
   [text setFrame:f];
 
   // Also adjust the parent height by the change in height of the text field.
@@ -1643,6 +1671,25 @@ fix_contentview_size (NSView *parent)
 //          f.origin.y + f.size.height, [kid class]);
   }
   
+/*
+Bad:
+ parent: 420 x 541 @   0   0
+ text:   380 x 100 @  20  22  miny=-501
+
+Good:
+ parent: 420 x 541 @   0   0
+ text:   380 x 100 @  20  50  miny=-501
+*/
+
+  // #### WTF2: See "WTF" above.  If the text field is off the screen,
+  //      move it up.  We need this on 10.6 but not on 10.5.  Auugh.
+  //
+  f = [text frame];
+  if (f.origin.y < 50) {    // magic numbers, yay
+    f.origin.y = 50;
+    [text setFrame:f];
+  }
+
   /* Set the kids to track the top left corner of the window when resized.
      Set the NSText to track the bottom right corner as well.
    */
index 1f3ac35b91d482b823c952b810b46fde04536e6f..1b9f270eb050a115ec7c8c7de8239f0ab53f497c 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 2006 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 2006-2009 Jamie Zawinski <jwz@jwz.org>
 *
 * Permission to use, copy, modify, distribute, and sell this software and its
 * documentation for any purpose is hereby granted without fee, provided that
  */
 
 #import "XScreenSaverView.h"
-#import <AGL/agl.h>
+#import <AppKit/NSOpenGL.h>
 
 @interface XScreenSaverGLView : XScreenSaverView
 {
-  AGLContext agl_ctx;      // OpenGL rendering context
+  NSOpenGLContext *ogl_ctx;      // OpenGL rendering context
 }
 
 @end
index b7ac9c1e49dad4b1e02251f4d27db94d84ab3c42..6168e3de85ff75b340f697b6f88f9bbe8878f5cb 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 2006-2008 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 2006-2009 Jamie Zawinski <jwz@jwz.org>
 *
 * Permission to use, copy, modify, distribute, and sell this software and its
 * documentation for any purpose is hereby granted without fee, provided that
@@ -33,12 +33,13 @@ extern void check_gl_error (const char *type);
 
 @implementation XScreenSaverGLView
 
+#if 0
 - (void) dealloc
 {
-  if (agl_ctx)
-    aglDestroyContext (agl_ctx);
+  /* #### Do we have to destroy ogl_ctx? */
   [super dealloc];
 }
+#endif
 
 
 - (void)stopAnimation
@@ -48,70 +49,50 @@ extern void check_gl_error (const char *type);
   // Without this, the GL frame stays on screen when switching tabs
   // in System Preferences.
   //
-  if (agl_ctx) {
-    aglSetCurrentContext (NULL);
-    aglDestroyContext (agl_ctx);
-    agl_ctx = 0;
-  }
+  [NSOpenGLContext clearCurrentContext];
 }
 
 
 // #### maybe this could/should just be on 'lockFocus' instead?
 - (void) prepareContext
 {
-  if (agl_ctx)
-    if (!aglSetCurrentContext (agl_ctx)) {
-      check_gl_error ("aglSetCurrentContext");
-      abort();
-    }
+  if (ogl_ctx) {
+    [ogl_ctx makeCurrentContext];
+//    check_gl_error ("makeCurrentContext");
+    [ogl_ctx update];
+  }
 }
-      
+
+
 - (void) resizeContext
 {
-  if (! agl_ctx) 
-    return;
-
-  /* Constrain the AGL context to the rectangle of this view
-     (not of our parent window).
-   */
-  GLint aglrect[4];
-  NSRect rect = [[[self window] contentView] convertRect:[self frame]
-                                                fromView:self];
-  aglrect[0] = rect.origin.x;
-  aglrect[1] = rect.origin.y;
-  aglrect[2] = rect.size.width;
-  aglrect[3] = rect.size.height;
-  aglEnable (agl_ctx, AGL_BUFFER_RECT);
-  aglSetInteger (agl_ctx, AGL_BUFFER_RECT, aglrect);
-  aglUpdateContext (agl_ctx);
+  if (ogl_ctx) 
+    [ogl_ctx setView:self];
 }
 
 
 - (void)drawRect:(NSRect)rect
 {
-  if (! agl_ctx)
+  if (! ogl_ctx)
     [super drawRect:rect];
 }
 
 
-- (AGLContext) aglContext
+- (NSOpenGLContext *) oglContext
 {
-  return agl_ctx;
+  return ogl_ctx;
 }
 
-- (void) setAglContext: (AGLContext) ctx
+
+- (void) setOglContext: (NSOpenGLContext *) ctx
 {
-  if (agl_ctx)
-    if (! aglDestroyContext (agl_ctx)) {
-      check_gl_error("aglDestroyContext");
-      abort();
-    }
-  agl_ctx = ctx;
+  ogl_ctx = ctx;
   [self resizeContext];
 }
 
 @end
 
+
 /* Utility functions...
  */
 
@@ -123,35 +104,38 @@ init_GL (ModeInfo *mi)
 {
   Window win = mi->window;
   XScreenSaverGLView *view = (XScreenSaverGLView *) jwxyz_window_view (win);
-  
-  GLint agl_attrs[] = {
-    AGL_RGBA,
-    AGL_DOUBLEBUFFER,
-    AGL_DEPTH_SIZE, 16,
-    0 };
-  AGLPixelFormat aglpixf = aglChoosePixelFormat (NULL, 0, agl_attrs);
-  AGLContext ctx = aglCreateContext (aglpixf, NULL);
-  aglDestroyPixelFormat (aglpixf);
-  if (! ctx) {
-    check_gl_error("aglCreateContext");
-    abort();
-  }
-  
-  if (! aglSetDrawable (ctx, GetWindowPort ([[view window] windowRef]))) {
-    check_gl_error("aglSetDrawable");
-    abort();
+  NSOpenGLContext *ctx = [view oglContext];
+
+  if (!ctx) {
+
+    NSOpenGLPixelFormatAttribute attrs[] = {
+      NSOpenGLPFADoubleBuffer,
+      NSOpenGLPFAColorSize, 24,
+      NSOpenGLPFAAlphaSize, 8,
+      NSOpenGLPFADepthSize, 16,
+      0 };
+    NSOpenGLPixelFormat *pixfmt = [[NSOpenGLPixelFormat alloc] 
+                                    initWithAttributes:attrs];
+
+    ctx = [[NSOpenGLContext alloc] 
+            initWithFormat:pixfmt
+              shareContext:nil];
   }
 
-  if (! aglSetCurrentContext (ctx)) {
-    check_gl_error("aglSetCurrentContext");
-    abort();
-  }
-
-  [view setAglContext:ctx];
-
   // Sync refreshes to the vertical blanking interval
   GLint r = 1;
-  aglSetInteger (ctx, AGL_SWAP_INTERVAL, &r);
+  [ctx setValues:&r forParameter:NSOpenGLCPSwapInterval];
+
+  [ctx makeCurrentContext];
+  check_gl_error ("makeCurrentContext");
+
+  [view setOglContext:ctx];
+
+  // Clear frame buffer ASAP, else there are bits left over from other apps.
+  glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+//  glFinish ();
+//  glXSwapBuffers (mi->dpy, mi->window);
+
 
   // Enable multi-threading, if possible.  This runs most OpenGL commands
   // and GPU management on a second CPU.
@@ -166,6 +150,7 @@ init_GL (ModeInfo *mi)
     }
   }
 
+
   // Caller expects a pointer to an opaque struct...  which it dereferences.
   // Don't ask me, it's historical...
   static int blort = -1;
@@ -179,11 +164,11 @@ void
 glXSwapBuffers (Display *dpy, Window window)
 {
   XScreenSaverGLView *view = (XScreenSaverGLView *) jwxyz_window_view (window);
-  AGLContext ctx = [view aglContext];
-  if (ctx) aglSwapBuffers (ctx);
+  NSOpenGLContext *ctx = [view oglContext];
+  if (ctx) [ctx flushBuffer]; // despite name, this actually swaps
 }
 
-/* Does nothing
+/* Does nothing - prepareContext already did the work.
  */
 void
 glXMakeCurrent (Display *dpy, Window window, GLXContext context)
@@ -197,41 +182,6 @@ clear_gl_error (void)
 {
   while (glGetError() != GL_NO_ERROR)
     ;
-  while (aglGetError() != AGL_NO_ERROR)
-    ;
-}
-
-static void
-check_agl_error (const char *type)
-{
-  char buf[100];
-  GLenum i;
-  const char *e;
-  switch ((i = aglGetError())) {
-    case AGL_NO_ERROR: return;
-    case AGL_BAD_ATTRIBUTE:        e = "bad attribute";        break;
-    case AGL_BAD_PROPERTY:         e = "bad propery";  break;
-    case AGL_BAD_PIXELFMT:         e = "bad pixelfmt"; break;
-    case AGL_BAD_RENDINFO:         e = "bad rendinfo"; break;
-    case AGL_BAD_CONTEXT:          e = "bad context";  break;
-    case AGL_BAD_DRAWABLE:         e = "bad drawable"; break;
-    case AGL_BAD_GDEV:             e = "bad gdev";     break;
-    case AGL_BAD_STATE:            e = "bad state";    break;
-    case AGL_BAD_VALUE:            e = "bad value";    break;
-    case AGL_BAD_MATCH:            e = "bad match";    break;
-    case AGL_BAD_ENUM:             e = "bad enum";     break;
-    case AGL_BAD_OFFSCREEN:        e = "bad offscreen";        break;
-    case AGL_BAD_FULLSCREEN:       e = "bad fullscreen";break;
-    case AGL_BAD_WINDOW:           e = "bad window";   break;
-    case AGL_BAD_POINTER:          e = "bad pointer";  break;
-    case AGL_BAD_MODULE:           e = "bad module";   break;
-    case AGL_BAD_ALLOC:            e = "bad alloc";    break;
-    case AGL_BAD_CONNECTION:       e = "bad connection";break;
-    default:
-      e = buf; sprintf (buf, "unknown AGL error %d", (int) i); break;
-  }
-  NSLog (@"%s AGL error: %s", type, e);
-  exit (1);
 }
 
 
@@ -239,8 +189,6 @@ check_agl_error (const char *type)
 void
 check_gl_error (const char *type)
 {
-  check_agl_error (type);
-  
   char buf[100];
   GLenum i;
   const char *e;
index 932e7db776b680ca156010b03f4f4e295427f55b..528c4f6c5b0a36e3032445aea201d4a230a35957 100644 (file)
@@ -81,7 +81,7 @@ int mono_p = 0;
     perror ("putenv");
     abort();
   }
-  free (npath);
+//  free (npath);   // Oops, don't free this! putenv() does not copy it!
 }
 
 
index 76dca61fa1eb993e4d38eb2aca62ca7336002e6c..df0a92098637c27ec1325ef7ba146b6735f47735 100644 (file)
@@ -15,7 +15,7 @@ XScreenSaver
 \f1\b0 \
 by Jamie Zawinski \uc0\u8232 and many others\
 \
-version 5.08 \uc0\u8232 27-Dec-2008\
+version 5.09 \uc0\u8232 03-Sep-2009\
 \
 {\field{\*\fldinst{HYPERLINK "http://www.jwz.org/xscreensaver/"}}{\fldrslt \cf2 \ul \ulc2 http://www.jwz.org/xscreensaver/}}\
 \pard\pardeftab720\li720
index 150c638db073b185c94b94f8e925957a1fd89044..966a40fae58bc44ef749a5fce8d9ee10c1d91681 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1991-2008 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 1991-2009 Jamie Zawinski <jwz@jwz.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
@@ -409,10 +409,6 @@ extern int visual_class (Screen *, Visual *);
 // also declared in utils/grabclient.h
 extern Bool use_subwindow_mode_p (Screen *, Window);
 
-// for aglUseFont
-extern int jwxyz_font_info (Font, int *size_ret, int *face_ret);
-
-
 struct jwxyz_Visual {
   VisualID visualid;   /* visual id of this visual */
   int class;           /* class of screen (monochrome, etc.) */
index 17a37734f24e47cae5d63e91bf2806ffa56c31e5..37290ecf8c9ed9454b50a081de010d907aa915ba 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1991-2008 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 1991-2009 Jamie Zawinski <jwz@jwz.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
@@ -17,6 +17,7 @@
  */
 
 #import <stdlib.h>
+#import <stdint.h>
 #import <Cocoa/Cocoa.h>
 #import "jwxyz.h"
 #import "jwxyz-timers.h"
@@ -1175,7 +1176,9 @@ Status
 XAllocColor (Display *dpy, Colormap cmap, XColor *color)
 {
   // store 32 bit ARGB in the pixel field.
-  color->pixel = ((                       0xFF  << 24) |
+  // (The uint32_t is so that 0xFF000000 doesn't become 0xFFFFFFFFFF000000)
+  color->pixel = (uint32_t)
+                 ((                       0xFF  << 24) |
                   (((color->red   >> 8) & 0xFF) << 16) |
                   (((color->green >> 8) & 0xFF) <<  8) |
                   (((color->blue  >> 8) & 0xFF)      ));
@@ -1309,17 +1312,18 @@ ximage_putpixel_1 (XImage *ximage, int x, int y, unsigned long pixel)
 static unsigned long
 ximage_getpixel_32 (XImage *ximage, int x, int y)
 {
-  return *((unsigned long *) ximage->data +
-           (y * (ximage->bytes_per_line >> 2)) +
-           x);
+  return ((unsigned long)
+          *((uint32_t *) ximage->data +
+            (y * (ximage->bytes_per_line >> 2)) +
+            x));
 }
 
 static int
 ximage_putpixel_32 (XImage *ximage, int x, int y, unsigned long pixel)
 {
-  *((unsigned long *) ximage->data +
+  *((uint32_t *) ximage->data +
     (y * (ximage->bytes_per_line >> 2)) +
-    x) = pixel;
+    x) = (uint32_t) pixel;
   return 0;
 }
 
@@ -1615,7 +1619,7 @@ XGetImage (Display *dpy, Drawable d, int x, int y,
            unsigned long plane_mask, int format)
 {
   const unsigned char *data = 0;
-  int depth, ibpp, ibpl;
+  int depth, ibpp, ibpl, alpha_first_p;
   NSBitmapImageRep *bm = 0;
   
   Assert ((width  < 65535), "improbably large width");
@@ -1639,6 +1643,7 @@ XGetImage (Display *dpy, Drawable d, int x, int y,
     nsfrom.size.height = height;
     [bm initWithFocusedViewRect:nsfrom];
     depth = 32;
+    alpha_first_p = ([bm bitmapFormat] & NSAlphaFirstBitmapFormat);
     ibpp = [bm bitsPerPixel];
     ibpl = [bm bytesPerRow];
     data = [bm bitmapData];
@@ -1658,6 +1663,10 @@ XGetImage (Display *dpy, Drawable d, int x, int y,
   /* both PPC and Intel use word-ordered ARGB frame buffers, which
      means that on Intel it is BGRA when viewed by bytes (And BGR
      when using 24bpp packing).
+
+     BUT! Intel-64 stores alpha at the other end! 32bit=RGBA, 64bit=ARGB.
+     The NSAlphaFirstBitmapFormat bit in bitmapFormat seems to be the
+     indicator of this latest kink.
    */
   int xx, yy;
   if (depth == 1) {
@@ -1667,10 +1676,10 @@ XGetImage (Display *dpy, Drawable d, int x, int y,
       const unsigned char *iline2 = iline;
       for (xx = 0; xx < width; xx++) {
 
-        iline2++;                     // ignore b or a
-        iline2++;                     // ignore g or r
-        unsigned char r = *iline2++;  //        r or g
-        if (ibpp == 32) iline2++;     // ignore a or b
+        iline2++;                     // ignore R  or  A  or  A  or  B
+        iline2++;                     // ignore G  or  B  or  R  or  G
+        unsigned char r = *iline2++;  // use    B  or  G  or  G  or  R
+        if (ibpp == 32) iline2++;     // ignore A  or  R  or  B  or  A
 
         XPutPixel (image, xx, yy, (r ? 1 : 0));
       }
@@ -1684,19 +1693,34 @@ XGetImage (Display *dpy, Drawable d, int x, int y,
 
       const unsigned char *iline2 = iline;
       unsigned char *oline2 = oline;
-      for (xx = 0; xx < width; xx++) {
 
-        unsigned char a = (ibpp == 32 ? (*iline2++) : 0xFF);
-        unsigned char r = *iline2++;
-        unsigned char g = *iline2++;
-        unsigned char b = *iline2++;
-        unsigned long pixel = ((a << 24) |
-                               (r << 16) |
-                               (g <<  8) |
-                               (b <<  0));
-        *((unsigned int *) oline2) = pixel;
-        oline2 += 4;
-      }
+      if (alpha_first_p)                       // ARGB
+        for (xx = 0; xx < width; xx++) {
+          unsigned char a = (ibpp == 32 ? (*iline2++) : 0xFF);
+          unsigned char r = *iline2++;
+          unsigned char g = *iline2++;
+          unsigned char b = *iline2++;
+          uint32_t pixel = ((a << 24) |
+                            (r << 16) |
+                            (g <<  8) |
+                            (b <<  0));
+          *((uint32_t *) oline2) = pixel;
+          oline2 += 4;
+        }
+      else                                     // RGBA
+        for (xx = 0; xx < width; xx++) {
+          unsigned char r = *iline2++;
+          unsigned char g = *iline2++;
+          unsigned char b = *iline2++;
+          unsigned char a = (ibpp == 32 ? (*iline2++) : 0xFF);
+          uint32_t pixel = ((a << 24) |
+                            (r << 16) |
+                            (g <<  8) |
+                            (b <<  0));
+          *((uint32_t *) oline2) = pixel;
+          oline2 += 4;
+        }
+
       oline += obpl;
       iline += ibpl;
     }
@@ -2326,40 +2350,6 @@ XLoadFont (Display *dpy, const char *name)
 }
 
 
-/* This translates the NSFont into the numbers that aglUseFont() wants.
- */
-int
-jwxyz_font_info (Font f, int *size_ret, int *face_ret)
-{
-  char *name = strdup (f->ps_name);
-  char *dash = strchr (name, '-');
-  int flags = 0;
-  int size = f->size;
-  if (dash) {
-    // 0 = plain; 1=B; 2=I; 3=BI; 4=U; 5=UB; etc.
-    if (strcasestr (dash, "bold"))    flags |= 1;
-    if (strcasestr (dash, "italic"))  flags |= 2;
-    if (strcasestr (dash, "oblique")) flags |= 2;
-    *dash = 0;
-  }
-  NSString *nname = [NSString stringWithCString:name
-                                       encoding:NSUTF8StringEncoding];
-  ATSFontFamilyRef id =
-    ATSFontFamilyFindFromName ((CFStringRef) nname, kATSOptionFlagsDefault);
-
-
-  // WTF?  aglUseFont gets a BadValue if size is small!!
-  if (size < 9) size = 9;
-
-  //NSLog (@"font %s %.1f => %d %d %d", f->ps_name, f->size, id, flags, size);
-  Assert (id >= 0, "no ATS font family");
-
-  *size_ret = size;
-  *face_ret = flags;
-  return id;
-}
-
-
 XFontStruct *
 XLoadQueryFont (Display *dpy, const char *name)
 {
@@ -2504,8 +2494,8 @@ draw_string (Display *dpy, Drawable d, GC gc, int x, int y,
   set_font (d->cgc, gc);
 
   CGContextSetTextDrawingMode (d->cgc, kCGTextFill);
-  if (gc->gcv.antialias_p)
-    CGContextSetShouldAntialias (d->cgc, YES);  // always antialias text
+  if (gc->gcv.antialias_p)
+    CGContextSetShouldAntialias (d->cgc, YES);
   CGContextShowTextAtPoint (d->cgc,
                             wr.origin.x + x,
                             wr.origin.y + wr.size.height - y,
index 980db62d6377d2cf1077269a428de3a23697a984..c636754d88560e1c8bf0904c33d75f7fb38cdbfc 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1992-2006 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 1992-2009 Jamie Zawinski <jwz@jwz.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
@@ -13,6 +13,7 @@
  */
 
 #import <stdlib.h>
+#import <stdint.h>
 #import <Cocoa/Cocoa.h>
 #import "jwxyz.h"
 #import "grabscreen.h"
@@ -36,7 +37,7 @@ copy_framebuffer_to_ximage (CGDirectDisplayID cgdpy, XImage *xim,
   int ximw = xim->width;
   int ximh = xim->height;
 
-  unsigned long *odata = (unsigned long *) xim->data;
+  uint32_t *odata = (uint32_t *) xim->data;
 
   switch (bpp) {
   case 32:
@@ -56,10 +57,10 @@ copy_framebuffer_to_ximage (CGDirectDisplayID cgdpy, XImage *xim,
     if (spp != 3) abort();
     if (bps != 5) abort();
     for (y = 0; y < ximh; y++) {
-      unsigned short *ip = (unsigned short *) data;
+      uint16_t *ip = (uint16_t *) data;
       int x;
       for (x = 0; x < ximw; x++) {
-        unsigned short p = *ip++;
+        uint16_t p = *ip++;
         // This should be ok on both PPC and Intel (ARGB, word order)
         unsigned char r = (p >> 10) & 0x1F;
         unsigned char g = (p >>  5) & 0x1F;
@@ -67,7 +68,7 @@ copy_framebuffer_to_ximage (CGDirectDisplayID cgdpy, XImage *xim,
         r = (r << 3) | (r >> 2);
         g = (g << 3) | (g >> 2);
         b = (b << 3) | (b >> 2);
-        unsigned long pixel = 0xFF000000 | (r << 16) | (g << 8) | b;
+        uint32_t pixel = 0xFF000000 | (r << 16) | (g << 8) | b;
         // XPutPixel (xim, x, y, pixel);
         *odata++ = pixel;
       }
@@ -81,13 +82,13 @@ copy_framebuffer_to_ximage (CGDirectDisplayID cgdpy, XImage *xim,
       CGDirectPaletteRef pal = CGPaletteCreateWithDisplay (cgdpy);
 
       /* Map it to 32bpp pixels */
-      unsigned long map[256];
+      uint32_t map[256];
       for (y = 0; y < 256; y++) {
         CGDeviceColor c = CGPaletteGetColorAtIndex (pal, y);
         unsigned char r = c.red   * 255.0;
         unsigned char g = c.green * 255.0;
         unsigned char b = c.blue  * 255.0;
-        unsigned long pixel = 0xFF000000 | (r << 16) | (g << 8) | b;
+        uint32_t pixel = 0xFF000000 | (r << 16) | (g << 8) | b;
         map[y] = pixel;
       }
 
@@ -254,3 +255,4 @@ osx_load_image_file (Screen *screen, Window xwindow, Drawable drawable,
   [img release];
   return True;
 }
+
index 069d0c3b6ea47f5c246a43f0503362f7fab51e0b..3f39bd09df1aeeea554d9f3c5865cf0d3515a2e1 100755 (executable)
@@ -1,5 +1,5 @@
 #!/usr/bin/perl -w
-# Copyright Â© 2006-2008 Jamie Zawinski <jwz@jwz.org>
+# Copyright Â© 2006-2009 Jamie Zawinski <jwz@jwz.org>
 #
 # Permission to use, copy, modify, distribute, and sell this software and its
 # documentation for any purpose is hereby granted without fee, provided that
@@ -23,7 +23,7 @@ require 5;
 use strict;
 
 my $progname = $0; $progname =~ s@.*/@@g;
-my $version = q{ $Revision: 1.10 $ }; $version =~ s/^[^0-9]+([0-9.]+).*$/$1/;
+my $version = q{ $Revision: 1.13 $ }; $version =~ s/^[^0-9]+([0-9.]+).*$/$1/;
 
 my $verbose = 1;
 
@@ -72,6 +72,7 @@ sub update_saver_xml($$) {
   $desc =~ s/\s*$//s;
 
   # in case it's done already...
+  $desc =~ s@<!--.*?-->@@gs;
   $desc =~ s/^.* version \d[^\n]*\n//s;
   $desc =~ s/^From the XScreenSaver.*\n//m;
   $desc =~ s@^http://www\.jwz\.org/xscreensaver.*\n@@m;
@@ -108,7 +109,7 @@ sub update_saver_xml($$) {
   #
   my $curator = "Jamie Zawinski";
   if (! ($authors =~ m/$curator/si)) {
-    if ($authors =~ m@^(.*),? and (.*)$@s) {
+    if ($authors =~ m@^(.*?),? and (.*)$@s) {
       $authors = "$1, $2, and $curator";
     } else {
       $authors .= " and $curator";
@@ -217,7 +218,7 @@ sub update($) {
   $copyright =~ s/\b\d{4}-(\d{4})\b/$1/;
 
   # Lose the Wikipedia URLs.
-  $info_str =~ s@http:.*\bwikipedia\b[^\s]+[ \t]*\n?@@gm;
+  $info_str =~ s@http:.*?\b(wikipedia|mathworld)\b[^\s]+[ \t]*\n?@@gm;
 
   $info_str =~ s/(\n\n)\n+/$1/gs;
   $info_str =~ s/(^\s+|\s+$)//gs;
diff --git a/README b/README
index 98179791e736906824543f9e5b15a7cdc5065aec..82edc8092554672ea49d0c489382e5e74b2b6128 100644 (file)
--- a/README
+++ b/README
@@ -38,6 +38,18 @@ XScreenSaver has an extensive manual -- please read it!
 
 ===============================================================================
 
+Changes since 5.08:   * Ported to MacOS 10.6, including various 64-bit fixes.
+                      * New hack, `rubikblocks'.
+                      * Fixed another potential RANDR crash.
+                      * Use correct proxy server on MacOS.
+                      * `molecule' now correctly displays PDB 3.2 files.
+                      * Updates to `mirrorblob', `glhanoi', and `sonar'.
+                      * Rewritten version of `klein' hack.
+                      * New hack, `surfaces', incorporating objects from old
+                        `klein' hack, plus new ones.
+                      * Merged `juggle' and `juggler3d' hacks.
+                      * Fixed compilation under gcc 4.4.0 (strict aliasing).
+                      * Fixed intermittent failure in `xscreensaver-command'.
 Changes since 5.07:   * New hack, `photopile'.
                       * Rewrote `sonar' and `jigsaw' as OpenGL programs.
                       * Minor tweaks to `maze', `m6502', `hypnowheel', and
@@ -56,7 +68,7 @@ Changes since 5.07:   * New hack, `photopile'.
                         `lissie', `rotor', `sphere', `spiral', `t3d', `vines',
                         `whirlygig', and `worm'.
                       * Merged `munch' and `mismunch'.
-                      * Updated `webcollage' to use twitpics.com as well.
+                      * Updated `webcollage' to use twitpic.com as well.
 Changes since 5.06:   * Xinerama/RANDR tweaks for old-style multi-screen.
                       * Added bumpy skin and cel shading to `skytentacles'.
                       * `flipflop' can load images onto the tiles.
index 6cfcde629e362b5195cc6c743b9e3617284a9f58..ef93b539e264bb53864e6360154cb320745cb422 100644 (file)
@@ -252,7 +252,10 @@ AC_DEFUN(AM_GLIB_WITH_NLS,
 
     AC_OUTPUT_COMMANDS(
       [case "$CONFIG_FILES" in *po/Makefile.in*)
+        rm -f po/stamp-it po/stamp-it.tmp
+        > po/stamp-it.tmp
         sed -e "/POTFILES =/r po/POTFILES" po/Makefile.in > po/Makefile
+        mv po/stamp-it.tmp po/stamp-it
       esac])
 
     dnl These rules are solely for the distribution goal.  While doing this
index fe4156a97fa289425a3a117eaa072e0a3233a90e..70cc74f4cd6184faac800b3664dab4e82c8633df 100755 (executable)
--- a/configure
+++ b/configure
@@ -759,6 +759,7 @@ LOCK_SRCS
 LOCK_OBJS
 JPEG_EXES
 GL_EXES
+RETIRED_GL_EXES
 SUID_EXES
 GL_UTIL_EXES
 GL_MEN
@@ -3505,7 +3506,14 @@ echo "${ECHO_T}$ac_cv_gcc_accepts_no_cpp_precomp" >&6; }
   fi
 
 if test -n "$GCC"; then
-   if test -n "$GCC"; then
+
+  case "$host" in
+    *-darwin* )
+      # Fucking Apple let // comments sneak into OpenGL headers, so
+      # we *must* allow // comments when compiling on Mac OS 10.6!  FUCK!
+    ;;
+   *)
+     if test -n "$GCC"; then
    { echo "$as_me:$LINENO: checking whether gcc accepts -std=c89" >&5
 echo $ECHO_N "checking whether gcc accepts -std=c89... $ECHO_C" >&6; }
 if test "${ac_cv_gcc_accepts_std+set}" = set; then
@@ -3526,6 +3534,9 @@ echo "${ECHO_T}$ac_cv_gcc_accepts_std" >&6; }
    ac_gcc_accepts_std="$ac_cv_gcc_accepts_std"
   fi
 
+   ;;
+  esac
+
    { echo "$as_me:$LINENO: result: Disabling C++ comments in ANSI C code." >&5
 echo "${ECHO_T}Disabling C++ comments in ANSI C code." >&6; }
    #
@@ -4385,7 +4396,7 @@ if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
 else
   ac_cv_header_stdc=no
 fi
-rm -rf conftest*
+rm -f -r conftest*
 
 fi
 
@@ -4406,7 +4417,7 @@ if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
 else
   ac_cv_header_stdc=no
 fi
-rm -rf conftest*
+rm -f -r conftest*
 
 fi
 
@@ -6142,7 +6153,7 @@ _ACEOF
       eval "ac_im_$ac_var=\`\${MAKE-make} $ac_var 2>/dev/null | sed -n 's/^$ac_var=//p'\`"
     done
     # Open Windows xmkmf reportedly sets LIBDIR instead of USRLIBDIR.
-    for ac_extension in a so sl; do
+    for ac_extension in a so sl dylib la dll; do
       if test ! -f "$ac_im_usrlibdir/libX11.$ac_extension" &&
         test -f "$ac_im_libdir/libX11.$ac_extension"; then
        ac_im_usrlibdir=$ac_im_libdir; break
@@ -6295,7 +6306,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
 for ac_dir in `echo "$ac_x_includes $ac_x_header_dirs" | sed s/include/lib/g`
 do
   # Don't even attempt the hair of trying to link an X program!
-  for ac_extension in a so sl; do
+  for ac_extension in a so sl dylib la dll; do
     if test -r "$ac_dir/libX11.$ac_extension"; then
       ac_x_libraries=$ac_dir
       break 2
@@ -8263,7 +8274,7 @@ if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
 else
   ac_cv_os_cray=no
 fi
-rm -rf conftest*
+rm -f -r conftest*
 
 fi
 { echo "$as_me:$LINENO: result: $ac_cv_os_cray" >&5
@@ -12487,62 +12498,46 @@ _ACEOF
 
 
     # Now check for version 1.2 in the same libs.
+    # Try to compile, since on MacOS 10.5.7, headers are older than libs!
+    { echo "$as_me:$LINENO: checking for XRRGetScreenResources" >&5
+echo $ECHO_N "checking for XRRGetScreenResources... $ECHO_C" >&6; }
+if test "${ac_cv_randr_12+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_randr_12=no
 
   ac_save_CPPFLAGS="$CPPFLAGS"
-  ac_save_LDFLAGS="$LDFLAGS"
-#  ac_save_LIBS="$LIBS"
-
   if test \! -z "$includedir" ; then
     CPPFLAGS="$CPPFLAGS -I$includedir"
   fi
-  # note: $X_CFLAGS includes $x_includes
   CPPFLAGS="$CPPFLAGS $X_CFLAGS"
-
-  if test \! -z "$libdir" ; then
-    LDFLAGS="$LDFLAGS -L$libdir"
-  fi
-  # note: $X_LIBS includes $x_libraries
-  LDFLAGS="$LDFLAGS $X_LIBS $X_EXTRA_LIBS"
-
   CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS`
-  LDFLAGS=`eval eval eval eval eval eval eval eval eval echo $LDFLAGS`
-  { echo "$as_me:$LINENO: checking for XRRGetOutputInfo in -lc" >&5
-echo $ECHO_N "checking for XRRGetOutputInfo in -lc... $ECHO_C" >&6; }
-if test "${ac_cv_lib_c_XRRGetOutputInfo+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  ac_check_lib_save_LIBS=$LIBS
-LIBS="-lc $SAVER_LIBS $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
+  cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char XRRGetOutputInfo ();
+#include <stdlib.h>
+                         #include <X11/Xlib.h>
+                         #include <X11/extensions/Xrandr.h>
 int
 main ()
 {
-return XRRGetOutputInfo ();
+XRRScreenResources *res =
+                           XRRGetScreenResources (0, 0);
   ;
   return 0;
 }
 _ACEOF
-rm -rf conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
+rm -rf conftest.$ac_objext
+if { (ac_try="$ac_compile"
 case "(($ac_try" in
   *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
   *) ac_try_echo=$ac_try;;
 esac
 eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
+  (eval "$ac_compile") 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -rf conftest.er1
@@ -12551,35 +12546,28 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
   (exit $ac_status); } && {
         test -z "$ac_c_werror_flag" ||
         test ! -s conftest.err
-       } && test -s conftest$ac_exeext &&
-       $as_test_x conftest$ac_exeext; then
-  ac_cv_lib_c_XRRGetOutputInfo=yes
+       } && test -s conftest.$ac_objext; then
+  ac_cv_randr_12=yes
 else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-       ac_cv_lib_c_XRRGetOutputInfo=no
+       ac_cv_randr_12=no
 fi
 
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
-      conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  CPPFLAGS="$ac_save_CPPFLAGS"
 fi
-{ echo "$as_me:$LINENO: result: $ac_cv_lib_c_XRRGetOutputInfo" >&5
-echo "${ECHO_T}$ac_cv_lib_c_XRRGetOutputInfo" >&6; }
-if test $ac_cv_lib_c_XRRGetOutputInfo = yes; then
-  cat >>confdefs.h <<\_ACEOF
+{ echo "$as_me:$LINENO: result: $ac_cv_randr_12" >&5
+echo "${ECHO_T}$ac_cv_randr_12" >&6; }
+    if test "$ac_cv_randr_12" = yes ; then
+      cat >>confdefs.h <<\_ACEOF
 #define HAVE_RANDR_12 1
 _ACEOF
 
-else
-  true
-fi
-
-  CPPFLAGS="$ac_save_CPPFLAGS"
-  LDFLAGS="$ac_save_LDFLAGS"
-#  LIBS="$ac_save_LIBS"
-
+    fi
+#   AC_CHECK_X_LIB(c, XRRGetOutputInfo, [AC_DEFINE(HAVE_RANDR_12)],
+#                  [true], $SAVER_LIBS)
   fi
 
 
@@ -12735,7 +12723,7 @@ else
   { echo "$as_me:$LINENO: result: no" >&5
 echo "${ECHO_T}no" >&6; }
 fi
-rm -rf conftest*
+rm -f -r conftest*
 
   CPPFLAGS="$ac_save_CPPFLAGS"
 
@@ -16431,7 +16419,7 @@ if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
   $EGREP "Mesa|MESA" >/dev/null 2>&1; then
   ac_cv_have_mesa_gl=yes
 fi
-rm -rf conftest*
+rm -f -r conftest*
 
   CPPFLAGS="$ac_save_CPPFLAGS"
        fi
@@ -16765,7 +16753,7 @@ if test "${ac_cv_mesagl_version_string+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 16772 "configure"
+#line 16760 "configure"
 #include "confdefs.h"
 #include <GL/gl.h>
 #ifndef MESA_MAJOR_VERSION
@@ -20315,7 +20303,7 @@ tab='   '
 if test "$have_gl" = yes; then
   GL_EXES='$(GL_EXES)'
   SUID_EXES='$(SUID_EXES)'
-  RETIRED_GL_EXES='$(RETIRED_EXES)'
+  RETIRED_GL_EXES='$(RETIRED_GL_EXES)'
   GL_UTIL_EXES='$(GL_UTIL_EXES)'
   GL_MEN='$(GL_MEN)'
   GL_KLUDGE=" "
@@ -20458,6 +20446,7 @@ INCLUDES=`echo "$INCLUDES" | sed 's@ -I${prefix}/include@@g;'`
 
 
 
+
 
 
 APPDEFAULTS=$ac_x_app_defaults
@@ -21299,6 +21288,7 @@ LOCK_SRCS!$LOCK_SRCS$ac_delim
 LOCK_OBJS!$LOCK_OBJS$ac_delim
 JPEG_EXES!$JPEG_EXES$ac_delim
 GL_EXES!$GL_EXES$ac_delim
+RETIRED_GL_EXES!$RETIRED_GL_EXES$ac_delim
 SUID_EXES!$SUID_EXES$ac_delim
 GL_UTIL_EXES!$GL_UTIL_EXES$ac_delim
 GL_MEN!$GL_MEN$ac_delim
@@ -21322,7 +21312,7 @@ LIBOBJS!$LIBOBJS$ac_delim
 LTLIBOBJS!$LTLIBOBJS$ac_delim
 _ACEOF
 
-  if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 70; then
+  if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 71; then
     break
   elif $ac_last_try; then
     { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
@@ -21756,7 +21746,10 @@ chmod u+w intltool-update
 
  ;;
     "default-2":C) case "$CONFIG_FILES" in *po/Makefile.in*)
+        rm -f po/stamp-it po/stamp-it.tmp
+        > po/stamp-it.tmp
         sed -e "/POTFILES =/r po/POTFILES" po/Makefile.in > po/Makefile
+        mv po/stamp-it.tmp po/stamp-it
       esac ;;
 
   esac
index 25c5d29cc009fca5cbdc987f5c1507e40a7057a2..7ef834aa6f7273e6c0b423b34f098b91d0e02635 100644 (file)
@@ -434,8 +434,17 @@ AC_DEFUN(AC_NO_OBJECTIVE_C,
 #
 ###############################################################################
 
-AC_DEFUN(AC_GCC_ACCEPTS_STD,
-         [AC_CHECK_GCC_ARG(std, -std=c89)])
+AC_DEFUN(AC_GCC_ACCEPTS_STD, [
+  case "$host" in
+    *-darwin* )
+      # Fucking Apple let // comments sneak into OpenGL headers, so
+      # we *must* allow // comments when compiling on Mac OS 10.6!  FUCK!
+    ;;
+   *)
+     AC_CHECK_GCC_ARG(std, -std=c89)
+   ;;
+  esac
+])
 
 AC_DEFUN(AC_NO_CPLUSPLUS_COMMENTS_IN_C_CODE,
  [if test -n "$GCC"; then
@@ -1691,8 +1700,21 @@ if test "$with_randr" = yes; then
     AC_DEFINE(HAVE_RANDR)
 
     # Now check for version 1.2 in the same libs.
-    AC_CHECK_X_LIB(c, XRRGetOutputInfo, [AC_DEFINE(HAVE_RANDR_12)],
-                   [true], $SAVER_LIBS)
+    # Try to compile, since on MacOS 10.5.7, headers are older than libs!
+    AC_CACHE_CHECK([for XRRGetScreenResources], ac_cv_randr_12,
+      [ac_cv_randr_12=no
+       AC_TRY_X_COMPILE([#include <stdlib.h>
+                         #include <X11/Xlib.h>
+                         #include <X11/extensions/Xrandr.h>],
+                        [XRRScreenResources *res = 
+                           XRRGetScreenResources (0, 0);],
+                        [ac_cv_randr_12=yes],
+                        [ac_cv_randr_12=no])])
+    if test "$ac_cv_randr_12" = yes ; then
+      AC_DEFINE(HAVE_RANDR_12)
+    fi
+#   AC_CHECK_X_LIB(c, XRRGetOutputInfo, [AC_DEFINE(HAVE_RANDR_12)],
+#                  [true], $SAVER_LIBS)
   fi
 
 
@@ -3601,7 +3623,7 @@ tab='     '
 if test "$have_gl" = yes; then
   GL_EXES='$(GL_EXES)'
   SUID_EXES='$(SUID_EXES)'
-  RETIRED_GL_EXES='$(RETIRED_EXES)'
+  RETIRED_GL_EXES='$(RETIRED_GL_EXES)'
   GL_UTIL_EXES='$(GL_UTIL_EXES)'
   GL_MEN='$(GL_MEN)'
   GL_KLUDGE=" "
@@ -3728,6 +3750,7 @@ AC_SUBST(LOCK_SRCS)
 AC_SUBST(LOCK_OBJS)
 AC_SUBST(JPEG_EXES)
 AC_SUBST(GL_EXES)
+AC_SUBST(RETIRED_GL_EXES)
 AC_SUBST(SUID_EXES)
 AC_SUBST(GL_UTIL_EXES)
 AC_SUBST(GL_MEN)
index 746dd1a8955af970ce522f04b6eabf2d74e32ef8..a6348f1c4439e4d6c62a28dcad55864491f5405a 100644 (file)
@@ -866,152 +866,3 @@ xdpyinfo: xdpyinfo.o
 #
 # DO NOT DELETE: updated by make distdepend
 
-demo-Gtk-conf.o: ../config.h
-demo-Gtk-conf.o: $(srcdir)/demo-Gtk-conf.h
-demo-Gtk-conf.o: $(UTILS_SRC)/xscreensaver-intl.h
-demo-Gtk.o: XScreenSaver_ad.h
-demo-Gtk.o: ../config.h
-demo-Gtk.o: $(srcdir)/demo-Gtk-conf.h
-demo-Gtk.o: $(srcdir)/demo-Gtk-support.h
-demo-Gtk.o: $(srcdir)/demo-Gtk-widgets.h
-demo-Gtk.o: $(srcdir)/prefs.h
-demo-Gtk.o: $(srcdir)/remote.h
-demo-Gtk.o: $(srcdir)/types.h
-demo-Gtk.o: $(UTILS_SRC)/images/logo-180.xpm
-demo-Gtk.o: $(UTILS_SRC)/images/logo-50.xpm
-demo-Gtk.o: $(UTILS_SRC)/resources.h
-demo-Gtk.o: $(UTILS_SRC)/usleep.h
-demo-Gtk.o: $(UTILS_SRC)/version.h
-demo-Gtk.o: $(UTILS_SRC)/visual.h
-demo-Gtk.o: $(UTILS_SRC)/xscreensaver-intl.h
-demo-Gtk-support.o: ../config.h
-demo-Gtk-support.o: $(srcdir)/demo-Gtk-support.h
-demo-Gtk-widgets.o: ../config.h
-demo-Gtk-widgets.o: $(srcdir)/demo-Gtk-stubs.h
-demo-Gtk-widgets.o: $(srcdir)/demo-Gtk-support.h
-demo-Gtk-widgets.o: $(srcdir)/demo-Gtk-widgets.h
-demo-Xm.o: ../config.h
-demo-Xm-widgets.o: ../config.h
-dpms.o: ../config.h
-dpms.o: $(srcdir)/prefs.h
-dpms.o: $(srcdir)/types.h
-dpms.o: $(srcdir)/xscreensaver.h
-exec.o: ../config.h
-exec.o: $(srcdir)/exec.h
-lock.o: $(srcdir)/auth.h
-lock.o: ../config.h
-lock.o: $(srcdir)/mlstring.h
-lock.o: $(srcdir)/prefs.h
-lock.o: $(srcdir)/types.h
-lock.o: $(UTILS_SRC)/resources.h
-lock.o: $(srcdir)/xscreensaver.h
-mlstring.o: $(srcdir)/mlstring.h
-passwd.o: $(srcdir)/auth.h
-passwd.o: ../config.h
-passwd.o: $(srcdir)/prefs.h
-passwd.o: $(srcdir)/types.h
-passwd.o: $(srcdir)/xscreensaver.h
-passwd-pwent.o: ../config.h
-prefs.o: ../config.h
-prefs.o: $(srcdir)/prefs.h
-prefs.o: $(srcdir)/types.h
-prefs.o: $(UTILS_SRC)/resources.h
-remote.o: ../config.h
-remote.o: $(srcdir)/remote.h
-screens.o: ../config.h
-screens.o: $(srcdir)/prefs.h
-screens.o: $(srcdir)/types.h
-screens.o: $(UTILS_SRC)/visual.h
-screens.o: $(srcdir)/xscreensaver.h
-setuid.o: ../config.h
-setuid.o: $(srcdir)/prefs.h
-setuid.o: $(srcdir)/types.h
-setuid.o: $(srcdir)/xscreensaver.h
-splash.o: ../config.h
-splash.o: $(srcdir)/prefs.h
-splash.o: $(srcdir)/types.h
-splash.o: $(UTILS_SRC)/resources.h
-splash.o: $(srcdir)/xscreensaver.h
-stderr.o: ../config.h
-stderr.o: $(srcdir)/prefs.h
-stderr.o: $(srcdir)/types.h
-stderr.o: $(UTILS_SRC)/resources.h
-stderr.o: $(UTILS_SRC)/visual.h
-stderr.o: $(srcdir)/xscreensaver.h
-subprocs.o: ../config.h
-subprocs.o: $(srcdir)/exec.h
-subprocs.o: $(srcdir)/prefs.h
-subprocs.o: $(srcdir)/types.h
-subprocs.o: $(UTILS_SRC)/visual.h
-subprocs.o: $(UTILS_SRC)/yarandom.h
-subprocs.o: $(srcdir)/xscreensaver.h
-test-apm.o: ../config.h
-test-fade.o: ../config.h
-test-fade.o: $(srcdir)/prefs.h
-test-fade.o: $(srcdir)/types.h
-test-fade.o: $(UTILS_SRC)/fade.h
-test-fade.o: $(srcdir)/xscreensaver.h
-test-grab.o: ../config.h
-test-mlstring.o: $(srcdir)/mlstring.c
-test-mlstring.o: $(srcdir)/mlstring.h
-test-passwd.o: XScreenSaver_ad.h
-test-passwd.o: $(srcdir)/auth.h
-test-passwd.o: ../config.h
-test-passwd.o: $(srcdir)/prefs.h
-test-passwd.o: $(srcdir)/types.h
-test-passwd.o: $(UTILS_SRC)/resources.h
-test-passwd.o: $(UTILS_SRC)/version.h
-test-passwd.o: $(UTILS_SRC)/visual.h
-test-passwd.o: $(srcdir)/xscreensaver.h
-test-randr.o: ../config.h
-test-screens.o: ../config.h
-test-screens.o: $(srcdir)/prefs.h
-test-screens.o: $(srcdir)/screens.c
-test-screens.o: $(srcdir)/types.h
-test-screens.o: $(UTILS_SRC)/visual.h
-test-screens.o: $(srcdir)/xscreensaver.h
-test-uid.o: ../config.h
-test-vp.o: ../config.h
-test-xdpms.o: ../config.h
-test-xinerama.o: ../config.h
-timers.o: ../config.h
-timers.o: $(srcdir)/prefs.h
-timers.o: $(srcdir)/types.h
-timers.o: $(srcdir)/xscreensaver.h
-windows.o: ../config.h
-windows.o: $(srcdir)/prefs.h
-windows.o: $(srcdir)/types.h
-windows.o: $(UTILS_SRC)/fade.h
-windows.o: $(UTILS_SRC)/visual.h
-windows.o: $(srcdir)/xscreensaver.h
-xscreensaver-command.o: ../config.h
-xscreensaver-command.o: $(srcdir)/remote.h
-xscreensaver-command.o: $(UTILS_SRC)/version.h
-xscreensaver-getimage.o: ../config.h
-xscreensaver-getimage.o: XScreenSaver_ad.h
-xscreensaver-getimage.o: $(srcdir)/prefs.h
-xscreensaver-getimage.o: $(srcdir)/types.h
-xscreensaver-getimage.o: $(UTILS_SRC)/colorbars.h
-xscreensaver-getimage.o: $(UTILS_SRC)/grabscreen.h
-xscreensaver-getimage.o: $(UTILS_SRC)/resources.h
-xscreensaver-getimage.o: $(UTILS_SRC)/utils.h
-xscreensaver-getimage.o: $(UTILS_SRC)/version.h
-xscreensaver-getimage.o: $(UTILS_SRC)/visual.h
-xscreensaver-getimage.o: $(UTILS_SRC)/vroot.h
-xscreensaver-getimage.o: $(UTILS_SRC)/yarandom.h
-xscreensaver.o: XScreenSaver_ad.h
-xscreensaver.o: $(srcdir)/auth.h
-xscreensaver.o: ../config.h
-xscreensaver.o: $(srcdir)/prefs.h
-xscreensaver.o: $(srcdir)/types.h
-xscreensaver.o: $(UTILS_SRC)/resources.h
-xscreensaver.o: $(UTILS_SRC)/usleep.h
-xscreensaver.o: $(UTILS_SRC)/version.h
-xscreensaver.o: $(UTILS_SRC)/visual.h
-xscreensaver.o: $(UTILS_SRC)/yarandom.h
-xscreensaver.o: $(srcdir)/xscreensaver.h
-xset.o: ../config.h
-xset.o: $(srcdir)/prefs.h
-xset.o: $(srcdir)/types.h
-xset.o: $(srcdir)/xscreensaver.h
-
index af651d73db8ef798b6549bbc83f027eeb8254170..12ca54f22749e76e172575a5b809dac5bc8818d9 100644 (file)
@@ -4,8 +4,8 @@
 !            a screen saver and locker for the X window system
 !                            by Jamie Zawinski
 !
-!                              version 5.08
-!                              27-Dec-2008
+!                              version 5.09
+!                              03-Sep-2009
 !
 ! See "man xscreensaver" for more info.  The latest version is always
 ! available at http://www.jwz.org/xscreensaver/
@@ -272,7 +272,7 @@ GetViewPortIsFullOfLies: False
 - GL:                          glblur -root                                \n\
 @GL_KLUDGE@ GL:                                glsnake -root                               \n\
                                halftone -root                              \n\
--                              juggle -root                                \n\
+@GL_KLUDGE@ GL:                                juggler3d -root                             \n\
 @GL_KLUDGE@ GL:                                lavalite -root                              \n\
 -                              polyominoes -root                           \n\
 @GL_KLUDGE@ GL:                                queens -root                                \n\
@@ -299,13 +299,13 @@ GetViewPortIsFullOfLies: False
 - GL:                          glslideshow -root                           \n\
 @GL_KLUDGE@ GL:                                hypertorus -root                            \n\
 - GL:                          jigglypuff -root                            \n\
-@GL_KLUDGE@ GL:                                klein -root                                 \n\
                                metaballs -root                             \n\
 @GL_KLUDGE@ GL:                                mirrorblob -root                            \n\
                                piecewise -root                             \n\
 @GL_KLUDGE@ GL:                                polytopes -root                             \n\
                                pong -root                                  \n\
                                popsquares -root                            \n\
+@GL_KLUDGE@ GL:                                surfaces -root                              \n\
                                xanalogtv -root                             \n\
 -                              abstractile -root                           \n\
                                anemotaxis -root                            \n\
@@ -332,7 +332,6 @@ GetViewPortIsFullOfLies: False
                                fiberlamp -root                             \n\
 @GL_KLUDGE@ GL:                                fliptext -root                              \n\
 @GL_KLUDGE@ GL:                                glhanoi -root                               \n\
-@GL_KLUDGE@ GL:                                juggler3d -root                             \n\
 @GL_KLUDGE@ GL:                                tangram -root                               \n\
 @GL_KLUDGE@ GL:                                timetunnel -root                            \n\
 @GL_KLUDGE@ GL:                                glschool -root                              \n\
@@ -346,9 +345,11 @@ GetViewPortIsFullOfLies: False
 @GL_KLUDGE@ GL:                                moebiusgears -root                          \n\
 @GL_KLUDGE@ GL:                                voronoi -root                               \n\
 @GL_KLUDGE@ GL:                                hypnowheel -root                            \n\
+@GL_KLUDGE@ GL:                                klein -root                                 \n\
 -                              lcdscrub -root                              \n\
 @GL_KLUDGE@ GL:                                photopile -root                             \n\
-@GL_KLUDGE@ GL:                                skytentacles -root                          \n
+@GL_KLUDGE@ GL:                                skytentacles -root                          \n\
+@GL_KLUDGE@ GL:                                rubikblocks -root                           \n
 
 
 
@@ -469,6 +470,7 @@ XScreenSaver.bourneShell:           /bin/sh
 *hacks.rd-bomb.name:        RDbomb
 *hacks.rdbomb.name:         RDbomb
 *hacks.rotzoomer.name:      RotZoomer
+*hacks.rubikblocks.name:    RubikBlocks
 *hacks.sballs.name:         SBalls
 *hacks.shadebobs.name:      ShadeBobs
 *hacks.sierpinski3d.name:   Sierpinski3D
index 8255fa0e93078c7caa95d29833118b13ef932f1e..d08c1816714258333e6fab0a510c1a4b790a0bde 100644 (file)
 - GL:                          glblur -root                                \\n\
   GL:                          glsnake -root                               \\n\
                                halftone -root                              \\n\
--                              juggle -root                                \\n\
+  GL:                          juggler3d -root                             \\n\
   GL:                          lavalite -root                              \\n\
 -                              polyominoes -root                           \\n\
   GL:                          queens -root                                \\n\
 - GL:                          glslideshow -root                           \\n\
   GL:                          hypertorus -root                            \\n\
 - GL:                          jigglypuff -root                            \\n\
-  GL:                          klein -root                                 \\n\
                                metaballs -root                             \\n\
   GL:                          mirrorblob -root                            \\n\
                                piecewise -root                             \\n\
   GL:                          polytopes -root                             \\n\
                                pong -root                                  \\n\
                                popsquares -root                            \\n\
+  GL:                          surfaces -root                              \\n\
                                xanalogtv -root                             \\n\
 -                              abstractile -root                           \\n\
                                anemotaxis -root                            \\n\
                                fiberlamp -root                             \\n\
   GL:                          fliptext -root                              \\n\
   GL:                          glhanoi -root                               \\n\
-  GL:                          juggler3d -root                             \\n\
   GL:                          tangram -root                               \\n\
   GL:                          timetunnel -root                            \\n\
   GL:                          glschool -root                              \\n\
   GL:                          moebiusgears -root                          \\n\
   GL:                          voronoi -root                               \\n\
   GL:                          hypnowheel -root                            \\n\
+  GL:                          klein -root                                 \\n\
 -                              lcdscrub -root                              \\n\
   GL:                          photopile -root                             \\n\
-  GL:                          skytentacles -root                          \\n",
+  GL:                          skytentacles -root                          \\n\
+  GL:                          rubikblocks -root                           \\n",
 "XScreenSaver.pointerPollTime:         0:00:05",
 "XScreenSaver.pointerHysteresis:               10",
 "XScreenSaver.initialDelay:            0:00:00",
 "*hacks.rd-bomb.name:        RDbomb",
 "*hacks.rdbomb.name:         RDbomb",
 "*hacks.rotzoomer.name:      RotZoomer",
+"*hacks.rubikblocks.name:    RubikBlocks",
 "*hacks.sballs.name:         SBalls",
 "*hacks.shadebobs.name:      ShadeBobs",
 "*hacks.sierpinski3d.name:   Sierpinski3D",
index b45f4d2f2e130bb60174753cd945457eb37cb7c6..526c4bdedb84a3bcd30b6dea84db6b95f4807df3 100644 (file)
@@ -1,5 +1,5 @@
 /* dpms.c --- syncing the X Display Power Management values
- * xscreensaver, Copyright (c) 2001, 2005 Jamie Zawinski <jwz@jwz.org>
+ * xscreensaver, Copyright (c) 2001-2009 Jamie Zawinski <jwz@jwz.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
@@ -55,7 +55,7 @@
 
 # include <X11/Xproto.h>
 # include <X11/extensions/dpms.h>
-# include <X11/extensions/dpmsstr.h>
+/*# include <X11/extensions/dpmsstr.h>*/
 
   /* Why this crap is not in a header file somewhere, I have no idea.  Losers!
    */
index d6df8443d2c610a895b140f86aad787224aaac8f..fdba1ee5d08cc7c9b424ddf7ab9b921faadd2e02 100644 (file)
@@ -2,7 +2,7 @@
  * (c) 2007, Quest Software, Inc. All rights reserved.
  *
  * This file is part of XScreenSaver,
- * Copyright (c) 1993-2004 Jamie Zawinski <jwz@jwz.org>
+ * Copyright (c) 1993-2009 Jamie Zawinski <jwz@jwz.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
@@ -153,6 +153,8 @@ mlstring_wrap(mlstring *mstring, XFontStruct *font, Dimension width)
          
          if (wrap_at == -1) /* No space found, hard wrap */
            wrap_at = line_length;
+         else
+           wrap_at++; /* Leave the space at the end of the line. */
 
          newml = calloc(1, sizeof(*newml));
          if (!newml) /* OOM, don't bother trying to wrap */
index 507da6b73cb9878e8756b37e729c859133b380a5..1e67c973f730ee39fe17fedf0d61e51a17ece6da 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver-command, Copyright (c) 1991-2005 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver-command, Copyright (c) 1991-2009 Jamie Zawinski <jwz@jwz.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
@@ -357,135 +357,121 @@ send_xscreensaver_command (Display *dpy, Atom command, long arg,
 }
 
 
+static Bool
+xscreensaver_command_event_p (Display *dpy, XEvent *event, XPointer arg)
+{
+  return (event->xany.type == PropertyNotify &&
+          event->xproperty.state == PropertyNewValue &&
+          event->xproperty.atom == XA_SCREENSAVER_RESPONSE);
+}
+
+
 static int
 xscreensaver_command_response (Display *dpy, Window window,
                                Bool verbose_p, Bool exiting_p,
                                char **error_ret)
 {
-  int fd = ConnectionNumber (dpy);
-  int timeout = 10;
-  int status;
-  fd_set fds;
-  struct timeval tv;
+  int sleep_count = 0;
   char err[2048];
+  XEvent event;
+  Bool got_event = False;
 
-  while (1)
+  while (!(got_event = XCheckIfEvent(dpy, &event,
+                                    &xscreensaver_command_event_p, 0)) &&
+        sleep_count++ < 10)
     {
-      FD_ZERO(&fds);
-      FD_SET(fd, &fds);
-      memset(&tv, 0, sizeof(tv));
-      tv.tv_sec = timeout;
-      status = select (fd+1, &fds, 0, &fds, &tv);
+      sleep(1);
+    }
 
-      if (status < 0)
-       {
-         char buf[1024];
-          if (error_ret)
-            {
-              sprintf (buf, "error waiting for reply");
-              *error_ret = strdup (buf);
-            }
-          else
-            {
-              sprintf (buf, "%s: error waiting for reply", progname);
-              perror (buf);
-            }
-         return status;
-       }
-      else if (status == 0)
+  if (!got_event)
+    {
+      sprintf (err, "no response to command.");
+      if (error_ret)
+       *error_ret = strdup (err);
+      else
+       fprintf (stderr, "%s: %s\n", progname, err);
+
+      return -1;
+    }
+  else
+    {
+      Status st2;
+      Atom type;
+      int format;
+      unsigned long nitems, bytesafter;
+      unsigned char *msg = 0;
+
+      XSync (dpy, False);
+      if (old_handler) abort();
+      old_handler = XSetErrorHandler (BadWindow_ehandler);
+      st2 = XGetWindowProperty (dpy, window,
+                               XA_SCREENSAVER_RESPONSE,
+                               0, 1024, True,
+                               AnyPropertyType,
+                               &type, &format, &nitems, &bytesafter,
+                               &msg);
+      XSync (dpy, False);
+      XSetErrorHandler (old_handler);
+      old_handler = 0;
+
+      if (got_badwindow)
        {
-         sprintf (err, "no response to command.");
-          if (error_ret)
-            *error_ret = strdup (err);
-          else
-            fprintf (stderr, "%s: %s\n", progname, err);
+         if (exiting_p)
+           return 0;
+
+         sprintf (err, "xscreensaver window unexpectedly deleted.");
+
+         if (error_ret)
+           *error_ret = strdup (err);
+         else
+           fprintf (stderr, "%s: %s\n", progname, err);
+
          return -1;
        }
-      else
+
+      if (st2 == Success && type != None)
        {
-         XEvent event;
-         XNextEvent (dpy, &event);
-         if (event.xany.type == PropertyNotify &&
-             event.xproperty.state == PropertyNewValue &&
-             event.xproperty.atom == XA_SCREENSAVER_RESPONSE)
+         if (type != XA_STRING || format != 8)
            {
-             Status st2;
-             Atom type;
-             int format;
-             unsigned long nitems, bytesafter;
-             unsigned char *msg = 0;
-
-             XSync (dpy, False);
-              if (old_handler) abort();
-             old_handler = XSetErrorHandler (BadWindow_ehandler);
-             st2 = XGetWindowProperty (dpy, window,
-                                       XA_SCREENSAVER_RESPONSE,
-                                       0, 1024, True,
-                                       AnyPropertyType,
-                                       &type, &format, &nitems, &bytesafter,
-                                       &msg);
-             XSync (dpy, False);
-              XSetErrorHandler (old_handler);
-              old_handler = 0;
-
-             if (got_badwindow)
-               {
-                  if (exiting_p)
-                    return 0;
+             sprintf (err, "unrecognized response property.");
 
-                  sprintf (err, "xscreensaver window unexpectedly deleted.");
+             if (error_ret)
+               *error_ret = strdup (err);
+             else
+               fprintf (stderr, "%s: %s\n", progname, err);
 
-                  if (error_ret)
-                    *error_ret = strdup (err);
-                  else
-                    fprintf (stderr, "%s: %s\n", progname, err);
+             if (msg) XFree (msg);
+             return -1;
+           }
+         else if (!msg || (msg[0] != '+' && msg[0] != '-'))
+           {
+             sprintf (err, "unrecognized response message.");
 
-                 return -1;
-               }
+             if (error_ret)
+               *error_ret = strdup (err);
+             else  
+               fprintf (stderr, "%s: %s\n", progname, err);
 
-             if (st2 == Success && type != None)
-               {
-                 if (type != XA_STRING || format != 8)
-                   {
-                     sprintf (err, "unrecognized response property.");
-
-                      if (error_ret)
-                        *error_ret = strdup (err);
-                      else
-                        fprintf (stderr, "%s: %s\n", progname, err);
-
-                     if (msg) XFree (msg);
-                     return -1;
-                   }
-                 else if (!msg || (msg[0] != '+' && msg[0] != '-'))
-                   {
-                     sprintf (err, "unrecognized response message.");
-
-                      if (error_ret)
-                        *error_ret = strdup (err);
-                      else  
-                        fprintf (stderr, "%s: %s\n", progname, err);
-
-                     if (msg) XFree (msg);
-                     return -1;
-                   }
-                 else
-                   {
-                     int ret = (msg[0] == '+' ? 0 : -1);
-                      sprintf (err, "%s: %s\n", progname, (char *) msg+1);
-
-                      if (error_ret)
-                        *error_ret = strdup (err);
-                      else if (verbose_p || ret != 0)
-                       fprintf ((ret < 0 ? stderr : stdout), "%s\n", err);
-
-                     XFree (msg);
-                     return ret;
-                   }
-               }
+             if (msg) XFree (msg);
+             return -1;
+           }
+         else
+           {
+             int ret = (msg[0] == '+' ? 0 : -1);
+             sprintf (err, "%s: %s\n", progname, (char *) msg+1);
+
+             if (error_ret)
+               *error_ret = strdup (err);
+             else if (verbose_p || ret != 0)
+               fprintf ((ret < 0 ? stderr : stdout), "%s\n", err);
+
+             XFree (msg);
+             return ret;
            }
        }
     }
+
+  return -1;  /* warning suppression: not actually reached */
 }
 
 
index 689e26982c2be7d9b1ddb922019f22e0b5dc15cf..0a7eade847183601e61ffe5fbc754c9023c25f2d 100644 (file)
@@ -436,7 +436,7 @@ randr_scan_monitors (Display *dpy, char **errP)
               XRROutputInfo *rroi = XRRGetOutputInfo (dpy, res, 
                                                       res->outputs[k]);
               RRCrtc crtc = (rroi->crtc  ? rroi->crtc :
-                             rroi->crtcs ? rroi->crtcs[0] : 0);
+                             rroi->ncrtc ? rroi->crtcs[0] : 0);
               XRRCrtcInfo *crtci = (crtc ? XRRGetCrtcInfo(dpy, res, crtc) : 0);
 
               monitors[j] = m;
index 9ab7ae6e050586f2620f9502721b1c99da7a131d..97a26c02a39c5f4060135b51bda27fb217602d15 100644 (file)
@@ -669,7 +669,20 @@ void
 sleep_until_idle (saver_info *si, Bool until_idle_p)
 {
   saver_preferences *p = &si->prefs;
-  XEvent event;
+
+  /* We have to go through this union bullshit because gcc-4.4.0 has
+     stricter struct-aliasing rules.  Without this, the optimizer
+     can fuck things up.
+   */
+  union {
+    XEvent x_event;
+# ifdef HAVE_RANDR
+    XRRScreenChangeNotifyEvent xrr_event;
+# endif /* HAVE_RANDR */
+# ifdef HAVE_MIT_SAVER_EXTENSION
+    XScreenSaverNotifyEvent sevent;
+# endif /* HAVE_MIT_SAVER_EXTENSION */
+  } event;
 
   /* We need to select events on all windows if we're not using any extensions.
      Otherwise, we don't need to. */
@@ -713,9 +726,9 @@ sleep_until_idle (saver_info *si, Bool until_idle_p)
 
   while (1)
     {
-      XtAppNextEvent (si->app, &event);
+      XtAppNextEvent (si->app, &event.x_event);
 
-      switch (event.xany.type) {
+      switch (event.x_event.xany.type) {
       case 0:          /* our synthetic "timeout" event has been signalled */
        if (until_idle_p)
          {
@@ -803,7 +816,7 @@ sleep_until_idle (saver_info *si, Bool until_idle_p)
        break;
 
       case ClientMessage:
-       if (handle_clientmessage (si, &event, until_idle_p))
+       if (handle_clientmessage (si, &event.x_event, until_idle_p))
          goto DONE;
        break;
 
@@ -812,7 +825,7 @@ sleep_until_idle (saver_info *si, Bool until_idle_p)
            supposed to scan all windows for events, prepare this window. */
        if (scanning_all_windows)
          {
-            Window w = event.xcreatewindow.window;
+            Window w = event.x_event.xcreatewindow.window;
            start_notice_events_timer (si, w, p->debug_p);
          }
        break;
@@ -831,28 +844,28 @@ sleep_until_idle (saver_info *si, Bool until_idle_p)
             Window root=0, window=0;
             int x=-1, y=-1;
             const char *type = 0;
-           if (event.xany.type == MotionNotify)
+           if (event.x_event.xany.type == MotionNotify)
               {
                 /*type = "MotionNotify";*/
-                root = event.xmotion.root;
-                window = event.xmotion.window;
-                x = event.xmotion.x_root;
-                y = event.xmotion.y_root;
+                root = event.x_event.xmotion.root;
+                window = event.x_event.xmotion.window;
+                x = event.x_event.xmotion.x_root;
+                y = event.x_event.xmotion.y_root;
               }
-           else if (event.xany.type == KeyPress)
+           else if (event.x_event.xany.type == KeyPress)
               {
                 type = "KeyPress";
-                root = event.xkey.root;
-                window = event.xkey.window;
+                root = event.x_event.xkey.root;
+                window = event.x_event.xkey.window;
                 x = y = -1;
               }
-           else if (event.xany.type == ButtonPress)
+           else if (event.x_event.xany.type == ButtonPress)
               {
                 type = "ButtonPress";
-                root = event.xkey.root;
-                window = event.xkey.window;
-                x = event.xmotion.x_root;
-                y = event.xmotion.y_root;
+                root = event.x_event.xkey.root;
+                window = event.x_event.xkey.window;
+                x = event.x_event.xmotion.x_root;
+                y = event.x_event.xmotion.y_root;
               }
 
             if (type)
@@ -866,13 +879,13 @@ sleep_until_idle (saver_info *si, Bool until_idle_p)
 
                 /* Be careful never to do this unless in -debug mode, as
                    this could expose characters from the unlock password. */
-                if (p->debug_p && event.xany.type == KeyPress)
+                if (p->debug_p && event.x_event.xany.type == KeyPress)
                   {
                     KeySym keysym;
                     char c = 0;
-                    XLookupString (&event.xkey, &c, 1, &keysym, 0);
+                    XLookupString (&event.x_event.xkey, &c, 1, &keysym, 0);
                     fprintf (stderr, " (%s%s)",
-                             (event.xkey.send_event ? "synthetic " : ""),
+                             (event.x_event.xkey.send_event ? "synthetic " : ""),
                              XKeysymToString (keysym));
                   }
 
@@ -884,7 +897,7 @@ sleep_until_idle (saver_info *si, Bool until_idle_p)
          }
 
        /* If any widgets want to handle this event, let them. */
-       dispatch_event (si, &event);
+       dispatch_event (si, &event.x_event);
 
         
         /* If we got a MotionNotify event, figure out what screen it
@@ -892,11 +905,11 @@ sleep_until_idle (saver_info *si, Bool until_idle_p)
            far enough to count as "real" motion, then ignore this
            event.
          */
-        if (event.xany.type == MotionNotify)
+        if (event.x_event.xany.type == MotionNotify)
           {
             int i;
             for (i = 0; i < si->nscreens; i++)
-              if (event.xmotion.root ==
+              if (event.x_event.xmotion.root ==
                   RootWindowOfScreen (si->screens[i].screen))
                 break;
             if (i < si->nscreens)
@@ -915,8 +928,8 @@ sleep_until_idle (saver_info *si, Bool until_idle_p)
        if (!until_idle_p)
          {
            if (si->demoing_p &&
-               (event.xany.type == MotionNotify ||
-                event.xany.type == KeyRelease))
+               (event.x_event.xany.type == MotionNotify ||
+                event.x_event.xany.type == KeyRelease))
              /* When we're demoing a single hack, mouse motion doesn't
                 cause deactivation.  Only clicks and keypresses do. */
              ;
@@ -933,16 +946,14 @@ sleep_until_idle (saver_info *si, Bool until_idle_p)
       default:
 
 #ifdef HAVE_MIT_SAVER_EXTENSION
-       if (event.type == si->mit_saver_ext_event_number)
+       if (event.x_event.type == si->mit_saver_ext_event_number)
          {
             /* This event's number is that of the MIT-SCREEN-SAVER server
                extension.  This extension has one event number, and the event
                itself contains sub-codes that say what kind of event it was
                (an "idle" or "not-idle" event.)
              */
-           XScreenSaverNotifyEvent *sevent =
-             (XScreenSaverNotifyEvent *) &event;
-           if (sevent->state == ScreenSaverOn)
+           if (event.sevent.state == ScreenSaverOn)
              {
                int i = 0;
                if (p->verbose_p)
@@ -960,7 +971,7 @@ sleep_until_idle (saver_info *si, Bool until_idle_p)
                      XUnmapWindow (si->dpy, ssi->server_mit_saver_window);
                  }
 
-               if (sevent->kind != ScreenSaverExternal)
+               if (event.sevent.kind != ScreenSaverExternal)
                  {
                    fprintf (stderr,
                         "%s: ScreenSaverOn event wasn't of type External!\n",
@@ -970,7 +981,7 @@ sleep_until_idle (saver_info *si, Bool until_idle_p)
                if (until_idle_p)
                  goto DONE;
              }
-           else if (sevent->state == ScreenSaverOff)
+           else if (event.sevent.state == ScreenSaverOff)
              {
                if (p->verbose_p)
                  fprintf (stderr, "%s: MIT ScreenSaverOff event received.\n",
@@ -981,7 +992,7 @@ sleep_until_idle (saver_info *si, Bool until_idle_p)
            else
              fprintf (stderr,
                       "%s: unknown MIT-SCREEN-SAVER event %d received!\n",
-                      blurb(), sevent->state);
+                      blurb(), event.sevent.state);
          }
        else
 
@@ -989,7 +1000,7 @@ sleep_until_idle (saver_info *si, Bool until_idle_p)
 
 
 #ifdef HAVE_SGI_SAVER_EXTENSION
-       if (event.type == (si->sgi_saver_ext_event_number + ScreenSaverStart))
+       if (event.x_event.type == (si->sgi_saver_ext_event_number + ScreenSaverStart))
          {
             /* The SGI SCREEN_SAVER server extension has two event numbers,
                and this event matches the "idle" event. */
@@ -1000,7 +1011,7 @@ sleep_until_idle (saver_info *si, Bool until_idle_p)
            if (until_idle_p)
              goto DONE;
          }
-       else if (event.type == (si->sgi_saver_ext_event_number +
+       else if (event.x_event.type == (si->sgi_saver_ext_event_number +
                                ScreenSaverEnd))
          {
             /* The SGI SCREEN_SAVER server extension has two event numbers,
@@ -1015,25 +1026,22 @@ sleep_until_idle (saver_info *si, Bool until_idle_p)
 #endif /* HAVE_SGI_SAVER_EXTENSION */
 
 #ifdef HAVE_RANDR
-        if (event.type == (si->randr_event_number + RRScreenChangeNotify))
+        if (event.x_event.type == (si->randr_event_number + RRScreenChangeNotify))
           {
             /* The Resize and Rotate extension sends an event when the
                size, rotation, or refresh rate of any screen has changed.
              */
-            XRRScreenChangeNotifyEvent *xrr_event =
-              (XRRScreenChangeNotifyEvent *) &event;
-
             if (p->verbose_p)
               {
                 /* XRRRootToScreen is in Xrandr.h 1.4, 2001/06/07 */
-                int screen = XRRRootToScreen (si->dpy, xrr_event->window);
+                int screen = XRRRootToScreen (si->dpy, event.xrr_event.window);
                 fprintf (stderr, "%s: %d: screen change event received\n",
                          blurb(), screen);
               }
 
 # ifdef RRScreenChangeNotifyMask
             /* Inform Xlib that it's ok to update its data structures. */
-            XRRUpdateConfiguration (&event); /* Xrandr.h 1.9, 2002/09/29 */
+            XRRUpdateConfiguration (&event.x_event); /* Xrandr.h 1.9, 2002/09/29 */
 # endif /* RRScreenChangeNotifyMask */
 
             /* Resize the existing xscreensaver windows and cached ssi data. */
@@ -1051,7 +1059,7 @@ sleep_until_idle (saver_info *si, Bool until_idle_p)
 #endif /* HAVE_RANDR */
 
           /* Just some random event.  Let the Widgets handle it, if desired. */
-         dispatch_event (si, &event);
+         dispatch_event (si, &event.x_event);
       }
     }
  DONE:
@@ -1066,11 +1074,11 @@ sleep_until_idle (saver_info *si, Bool until_idle_p)
      there's only one event generated by user activity, not two.)
    */
   if (!until_idle_p && si->locked_p)
-    swallow_unlock_typeahead_events (si, &event);
+    swallow_unlock_typeahead_events (si, &event.x_event);
   else
     while (XCheckMaskEvent (si->dpy,
                             (KeyPressMask|ButtonPressMask|PointerMotionMask),
-                     &event))
+                     &event.x_event))
       ;
 
 
index 2961a91fa49e9c776626d05b71f4f9230a4e3ff9..6dd262e8ccbdbadf3726def033f7876401ab4dd3 100755 (executable)
@@ -1,5 +1,5 @@
 #!/usr/bin/perl -w
-# Copyright Â© 2001-2008 Jamie Zawinski <jwz@jwz.org>.
+# Copyright Â© 2001-2009 Jamie Zawinski <jwz@jwz.org>.
 #
 # Permission to use, copy, modify, distribute, and sell this software and its
 # documentation for any purpose is hereby granted without fee, provided that
@@ -35,14 +35,16 @@ use Fcntl;
 use Fcntl ':flock'; # import LOCK_* constants
 
 use POSIX ':fcntl_h';                          # S_ISDIR was here in Perl 5.6
-import Fcntl ':mode' unless defined &S_ISDIR;  # but it is here in Perl 5.8
+import Fcntl ':mode' unless defined &S_ISUID;  # but it is here in Perl 5.8
+       # but in Perl 5.10, both of these load, and cause errors!
+       # So we have to check for S_ISUID instead of S_ISDIR?  WTF?
 
 use bytes;  # Larry can take Unicode and shove it up his ass sideways.
             # Perl 5.8.0 causes us to start getting incomprehensible
             # errors about UTF-8 all over the place without this.
 
 my $progname = $0; $progname =~ s@.*/@@g;
-my $version = q{ $Revision: 1.26 $ }; $version =~ s/^[^0-9]+([0-9.]+).*$/$1/;
+my $version = q{ $Revision: 1.27 $ }; $version =~ s/^[^0-9]+([0-9.]+).*$/$1/;
 
 my $verbose = 0;
 
@@ -236,14 +238,14 @@ sub read_cache($) {
     $cache_file_name = "$ENV{HOME}/.xscreensaver-getimage.cache";
   }
 
+  print STDERR "$progname: awaiting lock: $cache_file_name\n"
+    if ($verbose > 1);
+
   my $file = $cache_file_name;
   open (CACHE_FILE, "+>>$file") || error ("unable to write $file: $!");
   flock (CACHE_FILE, LOCK_EX)   || error ("unable to lock $file: $!");
   seek (CACHE_FILE, 0, 0)       || error ("unable to rewind $file: $!");
 
-  print STDERR "$progname: reading cache $cache_file_name\n"
-    if ($verbose > 1);
-
   my $mtime = (stat(CACHE_FILE))[9];
 
   if ($mtime + $cache_max_age < time) {
index 8eeaf8968e8002f547f50d66d58e5546bb16e95a..fbcb9ee1879fd7b9d7e9b078da26f60daad53569 100755 (executable)
@@ -1,5 +1,5 @@
 #!/usr/bin/perl -w
-# Copyright Â© 2005-2008 Jamie Zawinski <jwz@jwz.org>
+# Copyright Â© 2005-2009 Jamie Zawinski <jwz@jwz.org>
 #
 # Permission to use, copy, modify, distribute, and sell this software and its
 # documentation for any purpose is hereby granted without fee, provided that
@@ -30,7 +30,7 @@ use Text::Wrap qw(wrap);
 use bytes;
 
 my $progname = $0; $progname =~ s@.*/@@g;
-my $version = q{ $Revision: 1.17 $ }; $version =~ s/^[^0-9]+([0-9.]+).*$/$1/;
+my $version = q{ $Revision: 1.18 $ }; $version =~ s/^[^0-9]+([0-9.]+).*$/$1/;
 
 my $verbose = 0;
 my $http_proxy = undef;
@@ -751,17 +751,42 @@ sub reformat_text($) {
 }
 
 
-sub get_url_text($) {
-  my ($url) = @_;
+# Figure out what the proxy server should be, either from environment
+# variables or by parsing the output of the (MacOS) program "scutil",
+# which tells us what the system-wide proxy settings are.
+#
+sub set_proxy() {
 
   # historical suckage: the environment variable name is lower case.
   $http_proxy = $ENV{http_proxy} || $ENV{HTTP_PROXY};
 
-  if ($http_proxy && $http_proxy =~ m@^http://([^/]*)/?$@ ) {
-    # historical suckage: allow "http://host:port" as well as "host:port".
-    $http_proxy = $1;
+  if (defined ($http_proxy)) {
+    if ($http_proxy && $http_proxy =~ m@^http://([^/]*)/?$@ ) {
+      # historical suckage: allow "http://host:port" as well as "host:port".
+      $http_proxy = $1;
+    }
+
+  } else {
+    my $proxy_data = `scutil --proxy 2>/dev/null`;
+    my ($server) = ($proxy_data =~ m/\bHTTPProxy\s*:\s*([^\s]+)/s);
+    my ($port)   = ($proxy_data =~ m/\bHTTPPort\s*:\s*([^\s]+)/s);
+    # Note: this ignores the "ExceptionsList".
+    if ($server) {
+      $http_proxy = $server;
+      $http_proxy .= ":$port" if $port;
+    }
   }
 
+  print STDERR "$progname: proxy server: $http_proxy\n" 
+    if ($verbose > 2 && $http_proxy);
+}
+
+
+sub get_url_text($) {
+  my ($url) = @_;
+
+  set_proxy();
+
   my ($ct, $body) = get_url ($url);
 
   $ct = guess_content_type ($ct, $body);
@@ -827,16 +852,16 @@ sub main() {
     elsif (m/^--?date$/)    { $text_mode = 'date';
                               $load_p = 0; }
     elsif (m/^--?text$/)    { $text_mode = 'literal';
-                              $text_literal = shift @ARGV;
+                              $text_literal = shift @ARGV || '';
                               $load_p = 0; }
     elsif (m/^--?file$/)    { $text_mode = 'file';
-                              $text_file = shift @ARGV;
+                              $text_file = shift @ARGV || '';
                               $load_p = 0; }
     elsif (m/^--?program$/) { $text_mode = 'program';
-                              $text_program = shift @ARGV;
+                              $text_program = shift @ARGV || '';
                               $load_p = 0; }
     elsif (m/^--?url$/)     { $text_mode = 'url';
-                              $text_url = shift @ARGV;
+                              $text_url = shift @ARGV || '';
                               $load_p = 0; }
     elsif (m/^--?col(umn)?s?$/) { $wrap_columns = 0 + shift @ARGV; }
     elsif (m/^--?cocoa$/)   { $cocoa_id = shift @ARGV; }
diff --git a/hacks/._fps.c b/hacks/._fps.c
new file mode 100644 (file)
index 0000000..ebffbac
Binary files /dev/null and b/hacks/._fps.c differ
index 148a7624685faa4750cb022272d9999a3a0b59d0..cf9b74118e01e114666d68f3e693da96193d9856 100644 (file)
@@ -166,7 +166,7 @@ EXES                = attraction blitspin bouboule braid decayscreen deco \
                  ccurve blaster bumps ripples xspirograph \
                  nerverot xrayswarm hyperball zoom whirlwindwarp rotzoomer \
                  speedmine vermiculate twang apollonian euler2d \
-                 juggle polyominoes thornbird  fluidballs anemone halftone \
+                 polyominoes thornbird  fluidballs anemone halftone \
                  metaballs eruption popsquares barcode piecewise cloudlife \
                  fontglide apple2 xanalogtv pong  wormhole \
                  pacman fuzzyflakes anemotaxis memscroller substrate \
@@ -177,7 +177,7 @@ JPEG_EXES   = webcollage-helper
 
 RETIRED_EXES   = ant bubbles critical flag forest laser lightning lisa \
                  lissie lmorph rotor sphere spiral t3d vines whirlygig \
-                 worm xsublim
+                 worm xsublim juggle
 
 HACK_OBJS_1    = fps.o $(UTILS_BIN)/resources.o $(UTILS_BIN)/visual.o \
                  $(UTILS_BIN)/usleep.o $(UTILS_BIN)/yarandom.o @XMU_OBJS@
@@ -201,7 +201,7 @@ MEN         = anemone.man apollonian.man attraction.man \
                  flame.man flow.man fluidballs.man galaxy.man \
                  goop.man grav.man greynetic.man halo.man helix.man \
                  hopalong.man hyperball.man hypercube.man ifs.man imsmap.man \
-                 interference.man juggle.man julia.man \
+                 interference.man julia.man \
                  kaleidescope.man kumppa.man \
                  loop.man maze.man moire.man \
                  moire2.man mountain.man munch.man nerverot.man noseguy.man \
@@ -228,7 +228,7 @@ MEN         = anemone.man apollonian.man attraction.man \
 RETIRED_MEN    = ant.man bubbles.man critical.man flag.man forest.man \
                  laser.man lightning.man lisa.man lissie.man lmorph.man \
                  rotor.man sphere.man spiral.man t3d.man vines.man \
-                 whirlygig.man worm.man xsublim.man
+                 whirlygig.man worm.man xsublim.man juggle.man
 
 STAR           = *
 EXTRAS         = README Makefile.in xml2man.pl m6502.sh .gdbinit \
@@ -349,13 +349,13 @@ install-xml:
        done
 
 uninstall-program:
-       @for program in $(EXES) $(SCRIPTS); do                          \
+       @for program in $(EXES) $(RETIRED_EXES) $(SCRIPTS); do          \
          echo rm -f $(install_prefix)$(HACKDIR)/$$program ;            \
          rm -f $(install_prefix)$(HACKDIR)/$$program ;                 \
        done
 
 uninstall-man:
-       @men="$(MEN)" ;                                                 \
+       @men="$(MEN) $(RETIRED_MEN)" ;                                  \
        for man in $$men; do                                            \
          instname=`echo $$man | sed 's/\.man$$/\.$(mansuffix)/'` ;     \
          echo rm -f $(install_prefix)$(manNdir)/$$instname* ;          \
@@ -364,13 +364,13 @@ uninstall-man:
 
 uninstall-xml:
        @dest=$(install_prefix)$(HACK_CONF_DIR) ;                       \
-        for file in $(EXES) $(SCRIPTS) $(EXTERNALS) ; do               \
+        for file in $(EXES) $(RETIRED_EXES) $(SCRIPTS) $(EXTERNALS) ; do \
             echo rm -f $$dest/$$file.xml ;                             \
                  rm -f $$dest/$$file.xml ;                             \
        done
 
 clean:
-       -rm -f *.o a.out core $(EXES) m6502.h
+       -rm -f *.o a.out core $(EXES) $(RETIRED_EXES) m6502.h
 
 distclean: clean
        -rm -f Makefile TAGS *~ "#"*
@@ -968,1829 +968,3 @@ webcollage-helper: webcollage-helper.o
 #
 # DO NOT DELETE: updated by make distdepend
 
-abstractile.o: ../config.h
-abstractile.o: $(srcdir)/fps.h
-abstractile.o: $(srcdir)/screenhackI.h
-abstractile.o: $(srcdir)/screenhack.h
-abstractile.o: $(UTILS_SRC)/colors.h
-abstractile.o: $(UTILS_SRC)/grabscreen.h
-abstractile.o: $(UTILS_SRC)/hsv.h
-abstractile.o: $(UTILS_SRC)/resources.h
-abstractile.o: $(UTILS_SRC)/usleep.h
-abstractile.o: $(UTILS_SRC)/visual.h
-abstractile.o: $(UTILS_SRC)/yarandom.h
-analogtv.o: $(srcdir)/analogtv.h
-analogtv.o: ../config.h
-analogtv.o: $(srcdir)/images/6x10font.xbm
-analogtv.o: $(UTILS_SRC)/grabscreen.h
-analogtv.o: $(UTILS_SRC)/resources.h
-analogtv.o: $(UTILS_SRC)/utils.h
-analogtv.o: $(UTILS_SRC)/xshm.h
-analogtv.o: $(UTILS_SRC)/yarandom.h
-anemone.o: ../config.h
-anemone.o: $(srcdir)/fps.h
-anemone.o: $(srcdir)/screenhackI.h
-anemone.o: $(srcdir)/screenhack.h
-anemone.o: $(UTILS_SRC)/colors.h
-anemone.o: $(UTILS_SRC)/grabscreen.h
-anemone.o: $(UTILS_SRC)/hsv.h
-anemone.o: $(UTILS_SRC)/resources.h
-anemone.o: $(UTILS_SRC)/usleep.h
-anemone.o: $(UTILS_SRC)/visual.h
-anemone.o: $(UTILS_SRC)/xdbe.h
-anemone.o: $(UTILS_SRC)/yarandom.h
-anemotaxis.o: ../config.h
-anemotaxis.o: $(srcdir)/fps.h
-anemotaxis.o: $(srcdir)/screenhackI.h
-anemotaxis.o: $(srcdir)/screenhack.h
-anemotaxis.o: $(UTILS_SRC)/colors.h
-anemotaxis.o: $(UTILS_SRC)/grabscreen.h
-anemotaxis.o: $(UTILS_SRC)/hsv.h
-anemotaxis.o: $(UTILS_SRC)/resources.h
-anemotaxis.o: $(UTILS_SRC)/usleep.h
-anemotaxis.o: $(UTILS_SRC)/visual.h
-anemotaxis.o: $(UTILS_SRC)/xdbe.h
-anemotaxis.o: $(UTILS_SRC)/yarandom.h
-ant.o: $(srcdir)/automata.h
-ant.o: ../config.h
-ant.o: $(srcdir)/fps.h
-ant.o: $(srcdir)/screenhackI.h
-ant.o: $(UTILS_SRC)/colors.h
-ant.o: $(UTILS_SRC)/erase.h
-ant.o: $(UTILS_SRC)/grabscreen.h
-ant.o: $(UTILS_SRC)/hsv.h
-ant.o: $(UTILS_SRC)/resources.h
-ant.o: $(UTILS_SRC)/usleep.h
-ant.o: $(UTILS_SRC)/visual.h
-ant.o: $(UTILS_SRC)/xshm.h
-ant.o: $(UTILS_SRC)/yarandom.h
-ant.o: $(srcdir)/xlockmoreI.h
-ant.o: $(srcdir)/xlockmore.h
-apollonian.o: ../config.h
-apollonian.o: $(srcdir)/fps.h
-apollonian.o: $(srcdir)/screenhackI.h
-apollonian.o: $(UTILS_SRC)/colors.h
-apollonian.o: $(UTILS_SRC)/erase.h
-apollonian.o: $(UTILS_SRC)/grabscreen.h
-apollonian.o: $(UTILS_SRC)/hsv.h
-apollonian.o: $(UTILS_SRC)/resources.h
-apollonian.o: $(UTILS_SRC)/usleep.h
-apollonian.o: $(UTILS_SRC)/visual.h
-apollonian.o: $(UTILS_SRC)/xshm.h
-apollonian.o: $(UTILS_SRC)/yarandom.h
-apollonian.o: $(srcdir)/xlockmoreI.h
-apollonian.o: $(srcdir)/xlockmore.h
-apple2-main.o: $(srcdir)/analogtv.h
-apple2-main.o: $(srcdir)/apple2.h
-apple2-main.o: ../config.h
-apple2-main.o: $(srcdir)/fps.h
-apple2-main.o: $(srcdir)/screenhackI.h
-apple2-main.o: $(srcdir)/screenhack.h
-apple2-main.o: $(UTILS_SRC)/colors.h
-apple2-main.o: $(UTILS_SRC)/grabscreen.h
-apple2-main.o: $(UTILS_SRC)/hsv.h
-apple2-main.o: $(UTILS_SRC)/resources.h
-apple2-main.o: $(UTILS_SRC)/usleep.h
-apple2-main.o: $(UTILS_SRC)/visual.h
-apple2-main.o: $(UTILS_SRC)/xshm.h
-apple2-main.o: $(UTILS_SRC)/yarandom.h
-apple2.o: $(srcdir)/analogtv.h
-apple2.o: $(srcdir)/apple2.h
-apple2.o: ../config.h
-apple2.o: $(srcdir)/fps.h
-apple2.o: $(srcdir)/images/apple2font.xbm
-apple2.o: $(srcdir)/screenhackI.h
-apple2.o: $(UTILS_SRC)/colors.h
-apple2.o: $(UTILS_SRC)/grabscreen.h
-apple2.o: $(UTILS_SRC)/hsv.h
-apple2.o: $(UTILS_SRC)/resources.h
-apple2.o: $(UTILS_SRC)/usleep.h
-apple2.o: $(UTILS_SRC)/visual.h
-apple2.o: $(UTILS_SRC)/xshm.h
-apple2.o: $(UTILS_SRC)/yarandom.h
-asm6502.o: $(srcdir)/asm6502.h
-attraction.o: ../config.h
-attraction.o: $(srcdir)/fps.h
-attraction.o: $(srcdir)/screenhackI.h
-attraction.o: $(srcdir)/screenhack.h
-attraction.o: $(UTILS_SRC)/colors.h
-attraction.o: $(UTILS_SRC)/grabscreen.h
-attraction.o: $(UTILS_SRC)/hsv.h
-attraction.o: $(UTILS_SRC)/resources.h
-attraction.o: $(UTILS_SRC)/spline.h
-attraction.o: $(UTILS_SRC)/usleep.h
-attraction.o: $(UTILS_SRC)/visual.h
-attraction.o: $(UTILS_SRC)/yarandom.h
-barcode.o: ../config.h
-barcode.o: $(srcdir)/fps.h
-barcode.o: $(srcdir)/screenhackI.h
-barcode.o: $(srcdir)/screenhack.h
-barcode.o: $(UTILS_SRC)/colors.h
-barcode.o: $(UTILS_SRC)/grabscreen.h
-barcode.o: $(UTILS_SRC)/hsv.h
-barcode.o: $(UTILS_SRC)/resources.h
-barcode.o: $(UTILS_SRC)/usleep.h
-barcode.o: $(UTILS_SRC)/visual.h
-barcode.o: $(UTILS_SRC)/yarandom.h
-blaster.o: ../config.h
-blaster.o: $(srcdir)/fps.h
-blaster.o: $(srcdir)/screenhackI.h
-blaster.o: $(srcdir)/screenhack.h
-blaster.o: $(UTILS_SRC)/colors.h
-blaster.o: $(UTILS_SRC)/grabscreen.h
-blaster.o: $(UTILS_SRC)/hsv.h
-blaster.o: $(UTILS_SRC)/resources.h
-blaster.o: $(UTILS_SRC)/usleep.h
-blaster.o: $(UTILS_SRC)/visual.h
-blaster.o: $(UTILS_SRC)/yarandom.h
-blitspin.o: ../config.h
-blitspin.o: $(srcdir)/fps.h
-blitspin.o: $(srcdir)/images/som.xbm
-blitspin.o: $(srcdir)/screenhackI.h
-blitspin.o: $(srcdir)/screenhack.h
-blitspin.o: $(UTILS_SRC)/colors.h
-blitspin.o: $(UTILS_SRC)/grabscreen.h
-blitspin.o: $(UTILS_SRC)/hsv.h
-blitspin.o: $(UTILS_SRC)/resources.h
-blitspin.o: $(UTILS_SRC)/usleep.h
-blitspin.o: $(UTILS_SRC)/visual.h
-blitspin.o: $(UTILS_SRC)/yarandom.h
-blitspin.o: $(srcdir)/xpm-pixmap.h
-bouboule.o: ../config.h
-bouboule.o: $(srcdir)/fps.h
-bouboule.o: $(srcdir)/screenhackI.h
-bouboule.o: $(UTILS_SRC)/colors.h
-bouboule.o: $(UTILS_SRC)/grabscreen.h
-bouboule.o: $(UTILS_SRC)/hsv.h
-bouboule.o: $(UTILS_SRC)/resources.h
-bouboule.o: $(UTILS_SRC)/usleep.h
-bouboule.o: $(UTILS_SRC)/visual.h
-bouboule.o: $(UTILS_SRC)/xshm.h
-bouboule.o: $(UTILS_SRC)/yarandom.h
-bouboule.o: $(srcdir)/xlockmoreI.h
-bouboule.o: $(srcdir)/xlockmore.h
-boxfit.o: ../config.h
-boxfit.o: $(srcdir)/fps.h
-boxfit.o: $(srcdir)/screenhackI.h
-boxfit.o: $(srcdir)/screenhack.h
-boxfit.o: $(UTILS_SRC)/colors.h
-boxfit.o: $(UTILS_SRC)/grabscreen.h
-boxfit.o: $(UTILS_SRC)/hsv.h
-boxfit.o: $(UTILS_SRC)/resources.h
-boxfit.o: $(UTILS_SRC)/usleep.h
-boxfit.o: $(UTILS_SRC)/visual.h
-boxfit.o: $(UTILS_SRC)/yarandom.h
-boxfit.o: $(srcdir)/xpm-pixmap.h
-braid.o: ../config.h
-braid.o: $(srcdir)/fps.h
-braid.o: $(srcdir)/screenhackI.h
-braid.o: $(UTILS_SRC)/colors.h
-braid.o: $(UTILS_SRC)/erase.h
-braid.o: $(UTILS_SRC)/grabscreen.h
-braid.o: $(UTILS_SRC)/hsv.h
-braid.o: $(UTILS_SRC)/resources.h
-braid.o: $(UTILS_SRC)/usleep.h
-braid.o: $(UTILS_SRC)/visual.h
-braid.o: $(UTILS_SRC)/xshm.h
-braid.o: $(UTILS_SRC)/yarandom.h
-braid.o: $(srcdir)/xlockmoreI.h
-braid.o: $(srcdir)/xlockmore.h
-bsod.o: $(srcdir)/analogtv.h
-bsod.o: $(srcdir)/apple2.h
-bsod.o: ../config.h
-bsod.o: $(srcdir)/fps.h
-bsod.o: $(srcdir)/images/amiga.xpm
-bsod.o: $(srcdir)/images/atari.xbm
-bsod.o: $(srcdir)/images/atm.xbm
-bsod.o: $(srcdir)/images/hmac.xpm
-bsod.o: $(srcdir)/images/macbomb.xbm
-bsod.o: $(srcdir)/images/mac.xbm
-bsod.o: $(srcdir)/images/osx_10_2.xpm
-bsod.o: $(srcdir)/images/osx_10_3.xpm
-bsod.o: $(srcdir)/screenhackI.h
-bsod.o: $(srcdir)/screenhack.h
-bsod.o: $(UTILS_SRC)/colors.h
-bsod.o: $(UTILS_SRC)/grabscreen.h
-bsod.o: $(UTILS_SRC)/hsv.h
-bsod.o: $(UTILS_SRC)/resources.h
-bsod.o: $(UTILS_SRC)/usleep.h
-bsod.o: $(UTILS_SRC)/visual.h
-bsod.o: $(UTILS_SRC)/xshm.h
-bsod.o: $(UTILS_SRC)/yarandom.h
-bsod.o: $(srcdir)/xpm-pixmap.h
-bubbles-default.o: $(srcdir)/bubbles.h
-bubbles-default.o: ../config.h
-bubbles-default.o: $(srcdir)/images/bubbles/blood10.xpm
-bubbles-default.o: $(srcdir)/images/bubbles/blood11.xpm
-bubbles-default.o: $(srcdir)/images/bubbles/blood1.xpm
-bubbles-default.o: $(srcdir)/images/bubbles/blood2.xpm
-bubbles-default.o: $(srcdir)/images/bubbles/blood3.xpm
-bubbles-default.o: $(srcdir)/images/bubbles/blood4.xpm
-bubbles-default.o: $(srcdir)/images/bubbles/blood5.xpm
-bubbles-default.o: $(srcdir)/images/bubbles/blood6.xpm
-bubbles-default.o: $(srcdir)/images/bubbles/blood7.xpm
-bubbles-default.o: $(srcdir)/images/bubbles/blood8.xpm
-bubbles-default.o: $(srcdir)/images/bubbles/blood9.xpm
-bubbles-default.o: $(srcdir)/images/bubbles/blue10.xpm
-bubbles-default.o: $(srcdir)/images/bubbles/blue11.xpm
-bubbles-default.o: $(srcdir)/images/bubbles/blue1.xpm
-bubbles-default.o: $(srcdir)/images/bubbles/blue2.xpm
-bubbles-default.o: $(srcdir)/images/bubbles/blue3.xpm
-bubbles-default.o: $(srcdir)/images/bubbles/blue4.xpm
-bubbles-default.o: $(srcdir)/images/bubbles/blue5.xpm
-bubbles-default.o: $(srcdir)/images/bubbles/blue6.xpm
-bubbles-default.o: $(srcdir)/images/bubbles/blue7.xpm
-bubbles-default.o: $(srcdir)/images/bubbles/blue8.xpm
-bubbles-default.o: $(srcdir)/images/bubbles/blue9.xpm
-bubbles-default.o: $(srcdir)/images/bubbles/glass10.xpm
-bubbles-default.o: $(srcdir)/images/bubbles/glass11.xpm
-bubbles-default.o: $(srcdir)/images/bubbles/glass1.xpm
-bubbles-default.o: $(srcdir)/images/bubbles/glass2.xpm
-bubbles-default.o: $(srcdir)/images/bubbles/glass3.xpm
-bubbles-default.o: $(srcdir)/images/bubbles/glass4.xpm
-bubbles-default.o: $(srcdir)/images/bubbles/glass5.xpm
-bubbles-default.o: $(srcdir)/images/bubbles/glass6.xpm
-bubbles-default.o: $(srcdir)/images/bubbles/glass7.xpm
-bubbles-default.o: $(srcdir)/images/bubbles/glass8.xpm
-bubbles-default.o: $(srcdir)/images/bubbles/glass9.xpm
-bubbles-default.o: $(srcdir)/images/bubbles/jade10.xpm
-bubbles-default.o: $(srcdir)/images/bubbles/jade11.xpm
-bubbles-default.o: $(srcdir)/images/bubbles/jade1.xpm
-bubbles-default.o: $(srcdir)/images/bubbles/jade2.xpm
-bubbles-default.o: $(srcdir)/images/bubbles/jade3.xpm
-bubbles-default.o: $(srcdir)/images/bubbles/jade4.xpm
-bubbles-default.o: $(srcdir)/images/bubbles/jade5.xpm
-bubbles-default.o: $(srcdir)/images/bubbles/jade6.xpm
-bubbles-default.o: $(srcdir)/images/bubbles/jade7.xpm
-bubbles-default.o: $(srcdir)/images/bubbles/jade8.xpm
-bubbles-default.o: $(srcdir)/images/bubbles/jade9.xpm
-bubbles-default.o: $(UTILS_SRC)/yarandom.h
-bubbles.o: $(srcdir)/bubbles.h
-bubbles.o: ../config.h
-bubbles.o: $(srcdir)/fps.h
-bubbles.o: $(srcdir)/screenhackI.h
-bubbles.o: $(srcdir)/screenhack.h
-bubbles.o: $(UTILS_SRC)/colors.h
-bubbles.o: $(UTILS_SRC)/grabscreen.h
-bubbles.o: $(UTILS_SRC)/hsv.h
-bubbles.o: $(UTILS_SRC)/resources.h
-bubbles.o: $(UTILS_SRC)/usleep.h
-bubbles.o: $(UTILS_SRC)/visual.h
-bubbles.o: $(UTILS_SRC)/yarandom.h
-bubbles.o: $(srcdir)/xpm-pixmap.h
-bumps.o: ../config.h
-bumps.o: $(srcdir)/fps.h
-bumps.o: $(srcdir)/screenhackI.h
-bumps.o: $(srcdir)/screenhack.h
-bumps.o: $(UTILS_SRC)/colors.h
-bumps.o: $(UTILS_SRC)/grabscreen.h
-bumps.o: $(UTILS_SRC)/hsv.h
-bumps.o: $(UTILS_SRC)/resources.h
-bumps.o: $(UTILS_SRC)/usleep.h
-bumps.o: $(UTILS_SRC)/visual.h
-bumps.o: $(UTILS_SRC)/yarandom.h
-ccurve.o: ../config.h
-ccurve.o: $(srcdir)/fps.h
-ccurve.o: $(srcdir)/screenhackI.h
-ccurve.o: $(srcdir)/screenhack.h
-ccurve.o: $(UTILS_SRC)/colors.h
-ccurve.o: $(UTILS_SRC)/erase.h
-ccurve.o: $(UTILS_SRC)/grabscreen.h
-ccurve.o: $(UTILS_SRC)/hsv.h
-ccurve.o: $(UTILS_SRC)/resources.h
-ccurve.o: $(UTILS_SRC)/usleep.h
-ccurve.o: $(UTILS_SRC)/visual.h
-ccurve.o: $(UTILS_SRC)/yarandom.h
-celtic.o: ../config.h
-celtic.o: $(srcdir)/fps.h
-celtic.o: $(srcdir)/screenhackI.h
-celtic.o: $(srcdir)/screenhack.h
-celtic.o: $(UTILS_SRC)/colors.h
-celtic.o: $(UTILS_SRC)/erase.h
-celtic.o: $(UTILS_SRC)/grabscreen.h
-celtic.o: $(UTILS_SRC)/hsv.h
-celtic.o: $(UTILS_SRC)/resources.h
-celtic.o: $(UTILS_SRC)/usleep.h
-celtic.o: $(UTILS_SRC)/visual.h
-celtic.o: $(UTILS_SRC)/yarandom.h
-cloudlife.o: ../config.h
-cloudlife.o: $(srcdir)/fps.h
-cloudlife.o: $(srcdir)/screenhackI.h
-cloudlife.o: $(srcdir)/screenhack.h
-cloudlife.o: $(UTILS_SRC)/colors.h
-cloudlife.o: $(UTILS_SRC)/grabscreen.h
-cloudlife.o: $(UTILS_SRC)/hsv.h
-cloudlife.o: $(UTILS_SRC)/resources.h
-cloudlife.o: $(UTILS_SRC)/usleep.h
-cloudlife.o: $(UTILS_SRC)/visual.h
-cloudlife.o: $(UTILS_SRC)/yarandom.h
-compass.o: ../config.h
-compass.o: $(srcdir)/fps.h
-compass.o: $(srcdir)/screenhackI.h
-compass.o: $(srcdir)/screenhack.h
-compass.o: $(UTILS_SRC)/colors.h
-compass.o: $(UTILS_SRC)/grabscreen.h
-compass.o: $(UTILS_SRC)/hsv.h
-compass.o: $(UTILS_SRC)/resources.h
-compass.o: $(UTILS_SRC)/usleep.h
-compass.o: $(UTILS_SRC)/visual.h
-compass.o: $(UTILS_SRC)/xdbe.h
-compass.o: $(UTILS_SRC)/yarandom.h
-coral.o: ../config.h
-coral.o: $(srcdir)/fps.h
-coral.o: $(srcdir)/screenhackI.h
-coral.o: $(srcdir)/screenhack.h
-coral.o: $(UTILS_SRC)/colors.h
-coral.o: $(UTILS_SRC)/erase.h
-coral.o: $(UTILS_SRC)/grabscreen.h
-coral.o: $(UTILS_SRC)/hsv.h
-coral.o: $(UTILS_SRC)/resources.h
-coral.o: $(UTILS_SRC)/usleep.h
-coral.o: $(UTILS_SRC)/visual.h
-coral.o: $(UTILS_SRC)/yarandom.h
-critical.o: ../config.h
-critical.o: $(srcdir)/fps.h
-critical.o: $(srcdir)/screenhackI.h
-critical.o: $(srcdir)/screenhack.h
-critical.o: $(UTILS_SRC)/colors.h
-critical.o: $(UTILS_SRC)/erase.h
-critical.o: $(UTILS_SRC)/grabscreen.h
-critical.o: $(UTILS_SRC)/hsv.h
-critical.o: $(UTILS_SRC)/resources.h
-critical.o: $(UTILS_SRC)/usleep.h
-critical.o: $(UTILS_SRC)/visual.h
-critical.o: $(UTILS_SRC)/yarandom.h
-crystal.o: ../config.h
-crystal.o: $(srcdir)/fps.h
-crystal.o: $(srcdir)/screenhackI.h
-crystal.o: $(UTILS_SRC)/colors.h
-crystal.o: $(UTILS_SRC)/grabscreen.h
-crystal.o: $(UTILS_SRC)/hsv.h
-crystal.o: $(UTILS_SRC)/resources.h
-crystal.o: $(UTILS_SRC)/usleep.h
-crystal.o: $(UTILS_SRC)/visual.h
-crystal.o: $(UTILS_SRC)/xshm.h
-crystal.o: $(UTILS_SRC)/yarandom.h
-crystal.o: $(srcdir)/xlockmoreI.h
-crystal.o: $(srcdir)/xlockmore.h
-cwaves.o: ../config.h
-cwaves.o: $(srcdir)/fps.h
-cwaves.o: $(srcdir)/screenhackI.h
-cwaves.o: $(srcdir)/screenhack.h
-cwaves.o: $(UTILS_SRC)/colors.h
-cwaves.o: $(UTILS_SRC)/grabscreen.h
-cwaves.o: $(UTILS_SRC)/hsv.h
-cwaves.o: $(UTILS_SRC)/resources.h
-cwaves.o: $(UTILS_SRC)/usleep.h
-cwaves.o: $(UTILS_SRC)/visual.h
-cwaves.o: $(UTILS_SRC)/yarandom.h
-cwaves.o: $(srcdir)/xpm-pixmap.h
-cynosure.o: ../config.h
-cynosure.o: $(srcdir)/fps.h
-cynosure.o: $(srcdir)/screenhackI.h
-cynosure.o: $(srcdir)/screenhack.h
-cynosure.o: $(UTILS_SRC)/colors.h
-cynosure.o: $(UTILS_SRC)/grabscreen.h
-cynosure.o: $(UTILS_SRC)/hsv.h
-cynosure.o: $(UTILS_SRC)/resources.h
-cynosure.o: $(UTILS_SRC)/usleep.h
-cynosure.o: $(UTILS_SRC)/visual.h
-cynosure.o: $(UTILS_SRC)/yarandom.h
-decayscreen.o: ../config.h
-decayscreen.o: $(srcdir)/fps.h
-decayscreen.o: $(srcdir)/screenhackI.h
-decayscreen.o: $(srcdir)/screenhack.h
-decayscreen.o: $(UTILS_SRC)/colors.h
-decayscreen.o: $(UTILS_SRC)/grabscreen.h
-decayscreen.o: $(UTILS_SRC)/hsv.h
-decayscreen.o: $(UTILS_SRC)/resources.h
-decayscreen.o: $(UTILS_SRC)/usleep.h
-decayscreen.o: $(UTILS_SRC)/visual.h
-decayscreen.o: $(UTILS_SRC)/yarandom.h
-deco.o: ../config.h
-deco.o: $(srcdir)/fps.h
-deco.o: $(srcdir)/screenhackI.h
-deco.o: $(srcdir)/screenhack.h
-deco.o: $(UTILS_SRC)/colors.h
-deco.o: $(UTILS_SRC)/grabscreen.h
-deco.o: $(UTILS_SRC)/hsv.h
-deco.o: $(UTILS_SRC)/resources.h
-deco.o: $(UTILS_SRC)/usleep.h
-deco.o: $(UTILS_SRC)/visual.h
-deco.o: $(UTILS_SRC)/yarandom.h
-deluxe.o: ../config.h
-deluxe.o: $(srcdir)/fps.h
-deluxe.o: $(srcdir)/screenhackI.h
-deluxe.o: $(srcdir)/screenhack.h
-deluxe.o: $(UTILS_SRC)/alpha.h
-deluxe.o: $(UTILS_SRC)/colors.h
-deluxe.o: $(UTILS_SRC)/grabscreen.h
-deluxe.o: $(UTILS_SRC)/hsv.h
-deluxe.o: $(UTILS_SRC)/resources.h
-deluxe.o: $(UTILS_SRC)/usleep.h
-deluxe.o: $(UTILS_SRC)/visual.h
-deluxe.o: $(UTILS_SRC)/xdbe.h
-deluxe.o: $(UTILS_SRC)/yarandom.h
-demon.o: $(srcdir)/automata.h
-demon.o: ../config.h
-demon.o: $(srcdir)/fps.h
-demon.o: $(srcdir)/screenhackI.h
-demon.o: $(UTILS_SRC)/colors.h
-demon.o: $(UTILS_SRC)/grabscreen.h
-demon.o: $(UTILS_SRC)/hsv.h
-demon.o: $(UTILS_SRC)/resources.h
-demon.o: $(UTILS_SRC)/usleep.h
-demon.o: $(UTILS_SRC)/visual.h
-demon.o: $(UTILS_SRC)/xshm.h
-demon.o: $(UTILS_SRC)/yarandom.h
-demon.o: $(srcdir)/xlockmoreI.h
-demon.o: $(srcdir)/xlockmore.h
-discrete.o: ../config.h
-discrete.o: $(srcdir)/fps.h
-discrete.o: $(srcdir)/screenhackI.h
-discrete.o: $(UTILS_SRC)/colors.h
-discrete.o: $(UTILS_SRC)/erase.h
-discrete.o: $(UTILS_SRC)/grabscreen.h
-discrete.o: $(UTILS_SRC)/hsv.h
-discrete.o: $(UTILS_SRC)/resources.h
-discrete.o: $(UTILS_SRC)/usleep.h
-discrete.o: $(UTILS_SRC)/visual.h
-discrete.o: $(UTILS_SRC)/xshm.h
-discrete.o: $(UTILS_SRC)/yarandom.h
-discrete.o: $(srcdir)/xlockmoreI.h
-discrete.o: $(srcdir)/xlockmore.h
-distort.o: ../config.h
-distort.o: $(srcdir)/fps.h
-distort.o: $(srcdir)/screenhackI.h
-distort.o: $(srcdir)/screenhack.h
-distort.o: $(UTILS_SRC)/colors.h
-distort.o: $(UTILS_SRC)/grabscreen.h
-distort.o: $(UTILS_SRC)/hsv.h
-distort.o: $(UTILS_SRC)/resources.h
-distort.o: $(UTILS_SRC)/usleep.h
-distort.o: $(UTILS_SRC)/visual.h
-distort.o: $(UTILS_SRC)/yarandom.h
-drift.o: ../config.h
-drift.o: $(srcdir)/fps.h
-drift.o: $(srcdir)/screenhackI.h
-drift.o: $(UTILS_SRC)/colors.h
-drift.o: $(UTILS_SRC)/erase.h
-drift.o: $(UTILS_SRC)/grabscreen.h
-drift.o: $(UTILS_SRC)/hsv.h
-drift.o: $(UTILS_SRC)/resources.h
-drift.o: $(UTILS_SRC)/usleep.h
-drift.o: $(UTILS_SRC)/visual.h
-drift.o: $(UTILS_SRC)/xshm.h
-drift.o: $(UTILS_SRC)/yarandom.h
-drift.o: $(srcdir)/xlockmoreI.h
-drift.o: $(srcdir)/xlockmore.h
-epicycle.o: ../config.h
-epicycle.o: $(srcdir)/fps.h
-epicycle.o: $(srcdir)/screenhackI.h
-epicycle.o: $(srcdir)/screenhack.h
-epicycle.o: $(UTILS_SRC)/colors.h
-epicycle.o: $(UTILS_SRC)/erase.h
-epicycle.o: $(UTILS_SRC)/grabscreen.h
-epicycle.o: $(UTILS_SRC)/hsv.h
-epicycle.o: $(UTILS_SRC)/resources.h
-epicycle.o: $(UTILS_SRC)/usleep.h
-epicycle.o: $(UTILS_SRC)/visual.h
-epicycle.o: $(UTILS_SRC)/yarandom.h
-eruption.o: ../config.h
-eruption.o: $(srcdir)/fps.h
-eruption.o: $(srcdir)/screenhackI.h
-eruption.o: $(srcdir)/screenhack.h
-eruption.o: $(UTILS_SRC)/colors.h
-eruption.o: $(UTILS_SRC)/grabscreen.h
-eruption.o: $(UTILS_SRC)/hsv.h
-eruption.o: $(UTILS_SRC)/resources.h
-eruption.o: $(UTILS_SRC)/usleep.h
-eruption.o: $(UTILS_SRC)/visual.h
-eruption.o: $(UTILS_SRC)/yarandom.h
-euler2d.o: ../config.h
-euler2d.o: $(srcdir)/fps.h
-euler2d.o: $(srcdir)/screenhackI.h
-euler2d.o: $(UTILS_SRC)/colors.h
-euler2d.o: $(UTILS_SRC)/grabscreen.h
-euler2d.o: $(UTILS_SRC)/hsv.h
-euler2d.o: $(UTILS_SRC)/resources.h
-euler2d.o: $(UTILS_SRC)/usleep.h
-euler2d.o: $(UTILS_SRC)/visual.h
-euler2d.o: $(UTILS_SRC)/xshm.h
-euler2d.o: $(UTILS_SRC)/yarandom.h
-euler2d.o: $(srcdir)/xlockmoreI.h
-euler2d.o: $(srcdir)/xlockmore.h
-fadeplot.o: ../config.h
-fadeplot.o: $(srcdir)/fps.h
-fadeplot.o: $(srcdir)/screenhackI.h
-fadeplot.o: $(UTILS_SRC)/colors.h
-fadeplot.o: $(UTILS_SRC)/grabscreen.h
-fadeplot.o: $(UTILS_SRC)/hsv.h
-fadeplot.o: $(UTILS_SRC)/resources.h
-fadeplot.o: $(UTILS_SRC)/usleep.h
-fadeplot.o: $(UTILS_SRC)/visual.h
-fadeplot.o: $(UTILS_SRC)/xshm.h
-fadeplot.o: $(UTILS_SRC)/yarandom.h
-fadeplot.o: $(srcdir)/xlockmoreI.h
-fadeplot.o: $(srcdir)/xlockmore.h
-fiberlamp.o: ../config.h
-fiberlamp.o: $(srcdir)/fps.h
-fiberlamp.o: $(srcdir)/screenhackI.h
-fiberlamp.o: $(UTILS_SRC)/colors.h
-fiberlamp.o: $(UTILS_SRC)/grabscreen.h
-fiberlamp.o: $(UTILS_SRC)/hsv.h
-fiberlamp.o: $(UTILS_SRC)/resources.h
-fiberlamp.o: $(UTILS_SRC)/usleep.h
-fiberlamp.o: $(UTILS_SRC)/visual.h
-fiberlamp.o: $(UTILS_SRC)/xshm.h
-fiberlamp.o: $(UTILS_SRC)/yarandom.h
-fiberlamp.o: $(srcdir)/xlockmoreI.h
-fiberlamp.o: $(srcdir)/xlockmore.h
-fireworkx.o: ../config.h
-fireworkx.o: $(srcdir)/fps.h
-fireworkx.o: $(srcdir)/screenhackI.h
-fireworkx.o: $(srcdir)/screenhack.h
-fireworkx.o: $(UTILS_SRC)/colors.h
-fireworkx.o: $(UTILS_SRC)/grabscreen.h
-fireworkx.o: $(UTILS_SRC)/hsv.h
-fireworkx.o: $(UTILS_SRC)/resources.h
-fireworkx.o: $(UTILS_SRC)/usleep.h
-fireworkx.o: $(UTILS_SRC)/visual.h
-fireworkx.o: $(UTILS_SRC)/yarandom.h
-flag.o: ../config.h
-flag.o: $(srcdir)/fps.h
-flag.o: $(srcdir)/images/bob.xbm
-flag.o: $(srcdir)/screenhackI.h
-flag.o: $(UTILS_SRC)/colors.h
-flag.o: $(UTILS_SRC)/grabscreen.h
-flag.o: $(UTILS_SRC)/hsv.h
-flag.o: $(UTILS_SRC)/resources.h
-flag.o: $(UTILS_SRC)/usleep.h
-flag.o: $(UTILS_SRC)/visual.h
-flag.o: $(UTILS_SRC)/xshm.h
-flag.o: $(UTILS_SRC)/yarandom.h
-flag.o: $(srcdir)/xlockmoreI.h
-flag.o: $(srcdir)/xlockmore.h
-flag.o: $(srcdir)/xpm-pixmap.h
-flame.o: ../config.h
-flame.o: $(srcdir)/fps.h
-flame.o: $(srcdir)/screenhackI.h
-flame.o: $(srcdir)/screenhack.h
-flame.o: $(UTILS_SRC)/colors.h
-flame.o: $(UTILS_SRC)/grabscreen.h
-flame.o: $(UTILS_SRC)/hsv.h
-flame.o: $(UTILS_SRC)/resources.h
-flame.o: $(UTILS_SRC)/usleep.h
-flame.o: $(UTILS_SRC)/visual.h
-flame.o: $(UTILS_SRC)/yarandom.h
-flow.o: ../config.h
-flow.o: $(srcdir)/fps.h
-flow.o: $(srcdir)/screenhackI.h
-flow.o: $(UTILS_SRC)/colors.h
-flow.o: $(UTILS_SRC)/grabscreen.h
-flow.o: $(UTILS_SRC)/hsv.h
-flow.o: $(UTILS_SRC)/resources.h
-flow.o: $(UTILS_SRC)/usleep.h
-flow.o: $(UTILS_SRC)/visual.h
-flow.o: $(UTILS_SRC)/xshm.h
-flow.o: $(UTILS_SRC)/yarandom.h
-flow.o: $(srcdir)/xlockmoreI.h
-flow.o: $(srcdir)/xlockmore.h
-fluidballs.o: ../config.h
-fluidballs.o: $(srcdir)/fps.h
-fluidballs.o: $(srcdir)/screenhackI.h
-fluidballs.o: $(srcdir)/screenhack.h
-fluidballs.o: $(UTILS_SRC)/colors.h
-fluidballs.o: $(UTILS_SRC)/grabscreen.h
-fluidballs.o: $(UTILS_SRC)/hsv.h
-fluidballs.o: $(UTILS_SRC)/resources.h
-fluidballs.o: $(UTILS_SRC)/usleep.h
-fluidballs.o: $(UTILS_SRC)/visual.h
-fluidballs.o: $(UTILS_SRC)/xdbe.h
-fluidballs.o: $(UTILS_SRC)/yarandom.h
-fontglide.o: ../config.h
-fontglide.o: $(srcdir)/fps.h
-fontglide.o: $(srcdir)/screenhackI.h
-fontglide.o: $(srcdir)/screenhack.h
-fontglide.o: $(UTILS_SRC)/colors.h
-fontglide.o: $(UTILS_SRC)/grabscreen.h
-fontglide.o: $(UTILS_SRC)/hsv.h
-fontglide.o: $(UTILS_SRC)/resources.h
-fontglide.o: $(UTILS_SRC)/usleep.h
-fontglide.o: $(UTILS_SRC)/visual.h
-fontglide.o: $(UTILS_SRC)/xdbe.h
-fontglide.o: $(UTILS_SRC)/yarandom.h
-forest.o: ../config.h
-forest.o: $(srcdir)/fps.h
-forest.o: $(srcdir)/screenhackI.h
-forest.o: $(UTILS_SRC)/colors.h
-forest.o: $(UTILS_SRC)/grabscreen.h
-forest.o: $(UTILS_SRC)/hsv.h
-forest.o: $(UTILS_SRC)/resources.h
-forest.o: $(UTILS_SRC)/usleep.h
-forest.o: $(UTILS_SRC)/visual.h
-forest.o: $(UTILS_SRC)/xshm.h
-forest.o: $(UTILS_SRC)/yarandom.h
-forest.o: $(srcdir)/xlockmoreI.h
-forest.o: $(srcdir)/xlockmore.h
-fps.o: ../config.h
-fps.o: $(srcdir)/fpsI.h
-fps.o: $(srcdir)/fps.h
-fps.o: $(srcdir)/screenhackI.h
-fps.o: $(UTILS_SRC)/colors.h
-fps.o: $(UTILS_SRC)/grabscreen.h
-fps.o: $(UTILS_SRC)/hsv.h
-fps.o: $(UTILS_SRC)/resources.h
-fps.o: $(UTILS_SRC)/usleep.h
-fps.o: $(UTILS_SRC)/visual.h
-fps.o: $(UTILS_SRC)/yarandom.h
-fuzzyflakes.o: ../config.h
-fuzzyflakes.o: $(srcdir)/fps.h
-fuzzyflakes.o: $(srcdir)/screenhackI.h
-fuzzyflakes.o: $(srcdir)/screenhack.h
-fuzzyflakes.o: $(UTILS_SRC)/colors.h
-fuzzyflakes.o: $(UTILS_SRC)/grabscreen.h
-fuzzyflakes.o: $(UTILS_SRC)/hsv.h
-fuzzyflakes.o: $(UTILS_SRC)/resources.h
-fuzzyflakes.o: $(UTILS_SRC)/usleep.h
-fuzzyflakes.o: $(UTILS_SRC)/visual.h
-fuzzyflakes.o: $(UTILS_SRC)/yarandom.h
-galaxy.o: ../config.h
-galaxy.o: $(srcdir)/fps.h
-galaxy.o: $(srcdir)/screenhackI.h
-galaxy.o: $(UTILS_SRC)/colors.h
-galaxy.o: $(UTILS_SRC)/grabscreen.h
-galaxy.o: $(UTILS_SRC)/hsv.h
-galaxy.o: $(UTILS_SRC)/resources.h
-galaxy.o: $(UTILS_SRC)/usleep.h
-galaxy.o: $(UTILS_SRC)/visual.h
-galaxy.o: $(UTILS_SRC)/xshm.h
-galaxy.o: $(UTILS_SRC)/yarandom.h
-galaxy.o: $(srcdir)/xlockmoreI.h
-galaxy.o: $(srcdir)/xlockmore.h
-goop.o: ../config.h
-goop.o: $(srcdir)/fps.h
-goop.o: $(srcdir)/screenhackI.h
-goop.o: $(srcdir)/screenhack.h
-goop.o: $(UTILS_SRC)/alpha.h
-goop.o: $(UTILS_SRC)/colors.h
-goop.o: $(UTILS_SRC)/grabscreen.h
-goop.o: $(UTILS_SRC)/hsv.h
-goop.o: $(UTILS_SRC)/resources.h
-goop.o: $(UTILS_SRC)/spline.h
-goop.o: $(UTILS_SRC)/usleep.h
-goop.o: $(UTILS_SRC)/visual.h
-goop.o: $(UTILS_SRC)/yarandom.h
-grav.o: ../config.h
-grav.o: $(srcdir)/fps.h
-grav.o: $(srcdir)/screenhackI.h
-grav.o: $(UTILS_SRC)/colors.h
-grav.o: $(UTILS_SRC)/grabscreen.h
-grav.o: $(UTILS_SRC)/hsv.h
-grav.o: $(UTILS_SRC)/resources.h
-grav.o: $(UTILS_SRC)/usleep.h
-grav.o: $(UTILS_SRC)/visual.h
-grav.o: $(UTILS_SRC)/xshm.h
-grav.o: $(UTILS_SRC)/yarandom.h
-grav.o: $(srcdir)/xlockmoreI.h
-grav.o: $(srcdir)/xlockmore.h
-greynetic.o: ../config.h
-greynetic.o: $(srcdir)/fps.h
-greynetic.o: $(srcdir)/screenhackI.h
-greynetic.o: $(srcdir)/screenhack.h
-greynetic.o: $(UTILS_SRC)/colors.h
-greynetic.o: $(UTILS_SRC)/grabscreen.h
-greynetic.o: $(UTILS_SRC)/hsv.h
-greynetic.o: $(UTILS_SRC)/resources.h
-greynetic.o: $(UTILS_SRC)/usleep.h
-greynetic.o: $(UTILS_SRC)/visual.h
-greynetic.o: $(UTILS_SRC)/yarandom.h
-halftone.o: ../config.h
-halftone.o: $(srcdir)/fps.h
-halftone.o: $(srcdir)/screenhackI.h
-halftone.o: $(srcdir)/screenhack.h
-halftone.o: $(UTILS_SRC)/colors.h
-halftone.o: $(UTILS_SRC)/grabscreen.h
-halftone.o: $(UTILS_SRC)/hsv.h
-halftone.o: $(UTILS_SRC)/resources.h
-halftone.o: $(UTILS_SRC)/usleep.h
-halftone.o: $(UTILS_SRC)/visual.h
-halftone.o: $(UTILS_SRC)/yarandom.h
-halo.o: ../config.h
-halo.o: $(srcdir)/fps.h
-halo.o: $(srcdir)/screenhackI.h
-halo.o: $(srcdir)/screenhack.h
-halo.o: $(UTILS_SRC)/colors.h
-halo.o: $(UTILS_SRC)/grabscreen.h
-halo.o: $(UTILS_SRC)/hsv.h
-halo.o: $(UTILS_SRC)/resources.h
-halo.o: $(UTILS_SRC)/usleep.h
-halo.o: $(UTILS_SRC)/visual.h
-halo.o: $(UTILS_SRC)/yarandom.h
-helix.o: ../config.h
-helix.o: $(srcdir)/fps.h
-helix.o: $(srcdir)/screenhackI.h
-helix.o: $(srcdir)/screenhack.h
-helix.o: $(UTILS_SRC)/colors.h
-helix.o: $(UTILS_SRC)/erase.h
-helix.o: $(UTILS_SRC)/grabscreen.h
-helix.o: $(UTILS_SRC)/hsv.h
-helix.o: $(UTILS_SRC)/resources.h
-helix.o: $(UTILS_SRC)/usleep.h
-helix.o: $(UTILS_SRC)/visual.h
-helix.o: $(UTILS_SRC)/yarandom.h
-hopalong.o: ../config.h
-hopalong.o: $(srcdir)/fps.h
-hopalong.o: $(srcdir)/screenhackI.h
-hopalong.o: $(UTILS_SRC)/colors.h
-hopalong.o: $(UTILS_SRC)/erase.h
-hopalong.o: $(UTILS_SRC)/grabscreen.h
-hopalong.o: $(UTILS_SRC)/hsv.h
-hopalong.o: $(UTILS_SRC)/resources.h
-hopalong.o: $(UTILS_SRC)/usleep.h
-hopalong.o: $(UTILS_SRC)/visual.h
-hopalong.o: $(UTILS_SRC)/xshm.h
-hopalong.o: $(UTILS_SRC)/yarandom.h
-hopalong.o: $(srcdir)/xlockmoreI.h
-hopalong.o: $(srcdir)/xlockmore.h
-hyperball.o: ../config.h
-hyperball.o: $(srcdir)/fps.h
-hyperball.o: $(srcdir)/screenhackI.h
-hyperball.o: $(srcdir)/screenhack.h
-hyperball.o: $(UTILS_SRC)/colors.h
-hyperball.o: $(UTILS_SRC)/grabscreen.h
-hyperball.o: $(UTILS_SRC)/hsv.h
-hyperball.o: $(UTILS_SRC)/resources.h
-hyperball.o: $(UTILS_SRC)/usleep.h
-hyperball.o: $(UTILS_SRC)/visual.h
-hyperball.o: $(UTILS_SRC)/yarandom.h
-hypercube.o: ../config.h
-hypercube.o: $(srcdir)/fps.h
-hypercube.o: $(srcdir)/screenhackI.h
-hypercube.o: $(srcdir)/screenhack.h
-hypercube.o: $(UTILS_SRC)/colors.h
-hypercube.o: $(UTILS_SRC)/grabscreen.h
-hypercube.o: $(UTILS_SRC)/hsv.h
-hypercube.o: $(UTILS_SRC)/resources.h
-hypercube.o: $(UTILS_SRC)/usleep.h
-hypercube.o: $(UTILS_SRC)/visual.h
-hypercube.o: $(UTILS_SRC)/yarandom.h
-ifs.o: ../config.h
-ifs.o: $(srcdir)/fps.h
-ifs.o: $(srcdir)/screenhackI.h
-ifs.o: $(srcdir)/screenhack.h
-ifs.o: $(UTILS_SRC)/colors.h
-ifs.o: $(UTILS_SRC)/grabscreen.h
-ifs.o: $(UTILS_SRC)/hsv.h
-ifs.o: $(UTILS_SRC)/resources.h
-ifs.o: $(UTILS_SRC)/usleep.h
-ifs.o: $(UTILS_SRC)/visual.h
-ifs.o: $(UTILS_SRC)/yarandom.h
-imsmap.o: ../config.h
-imsmap.o: $(srcdir)/fps.h
-imsmap.o: $(srcdir)/screenhackI.h
-imsmap.o: $(srcdir)/screenhack.h
-imsmap.o: $(UTILS_SRC)/colors.h
-imsmap.o: $(UTILS_SRC)/grabscreen.h
-imsmap.o: $(UTILS_SRC)/hsv.h
-imsmap.o: $(UTILS_SRC)/resources.h
-imsmap.o: $(UTILS_SRC)/usleep.h
-imsmap.o: $(UTILS_SRC)/visual.h
-imsmap.o: $(UTILS_SRC)/yarandom.h
-interaggregate.o: ../config.h
-interaggregate.o: $(srcdir)/fps.h
-interaggregate.o: $(srcdir)/screenhackI.h
-interaggregate.o: $(srcdir)/screenhack.h
-interaggregate.o: $(UTILS_SRC)/colors.h
-interaggregate.o: $(UTILS_SRC)/grabscreen.h
-interaggregate.o: $(UTILS_SRC)/hsv.h
-interaggregate.o: $(UTILS_SRC)/resources.h
-interaggregate.o: $(UTILS_SRC)/usleep.h
-interaggregate.o: $(UTILS_SRC)/visual.h
-interaggregate.o: $(UTILS_SRC)/yarandom.h
-interference.o: ../config.h
-interference.o: $(srcdir)/fps.h
-interference.o: $(srcdir)/screenhackI.h
-interference.o: $(srcdir)/screenhack.h
-interference.o: $(UTILS_SRC)/colors.h
-interference.o: $(UTILS_SRC)/grabscreen.h
-interference.o: $(UTILS_SRC)/hsv.h
-interference.o: $(UTILS_SRC)/resources.h
-interference.o: $(UTILS_SRC)/usleep.h
-interference.o: $(UTILS_SRC)/visual.h
-interference.o: $(UTILS_SRC)/xdbe.h
-interference.o: $(UTILS_SRC)/yarandom.h
-intermomentary.o: ../config.h
-intermomentary.o: $(srcdir)/fps.h
-intermomentary.o: $(srcdir)/screenhackI.h
-intermomentary.o: $(srcdir)/screenhack.h
-intermomentary.o: $(UTILS_SRC)/colors.h
-intermomentary.o: $(UTILS_SRC)/grabscreen.h
-intermomentary.o: $(UTILS_SRC)/hsv.h
-intermomentary.o: $(UTILS_SRC)/resources.h
-intermomentary.o: $(UTILS_SRC)/usleep.h
-intermomentary.o: $(UTILS_SRC)/visual.h
-intermomentary.o: $(UTILS_SRC)/yarandom.h
-juggle.o: ../config.h
-juggle.o: $(srcdir)/fps.h
-juggle.o: $(srcdir)/screenhackI.h
-juggle.o: $(UTILS_SRC)/colors.h
-juggle.o: $(UTILS_SRC)/grabscreen.h
-juggle.o: $(UTILS_SRC)/hsv.h
-juggle.o: $(UTILS_SRC)/resources.h
-juggle.o: $(UTILS_SRC)/usleep.h
-juggle.o: $(UTILS_SRC)/visual.h
-juggle.o: $(UTILS_SRC)/xshm.h
-juggle.o: $(UTILS_SRC)/yarandom.h
-juggle.o: $(srcdir)/xlockmoreI.h
-juggle.o: $(srcdir)/xlockmore.h
-julia.o: ../config.h
-julia.o: $(srcdir)/fps.h
-julia.o: $(srcdir)/screenhackI.h
-julia.o: $(UTILS_SRC)/colors.h
-julia.o: $(UTILS_SRC)/grabscreen.h
-julia.o: $(UTILS_SRC)/hsv.h
-julia.o: $(UTILS_SRC)/resources.h
-julia.o: $(UTILS_SRC)/usleep.h
-julia.o: $(UTILS_SRC)/visual.h
-julia.o: $(UTILS_SRC)/xshm.h
-julia.o: $(UTILS_SRC)/yarandom.h
-julia.o: $(srcdir)/xlockmoreI.h
-julia.o: $(srcdir)/xlockmore.h
-kaleidescope.o: ../config.h
-kaleidescope.o: $(srcdir)/fps.h
-kaleidescope.o: $(srcdir)/screenhackI.h
-kaleidescope.o: $(srcdir)/screenhack.h
-kaleidescope.o: $(UTILS_SRC)/colors.h
-kaleidescope.o: $(UTILS_SRC)/grabscreen.h
-kaleidescope.o: $(UTILS_SRC)/hsv.h
-kaleidescope.o: $(UTILS_SRC)/resources.h
-kaleidescope.o: $(UTILS_SRC)/spline.h
-kaleidescope.o: $(UTILS_SRC)/usleep.h
-kaleidescope.o: $(UTILS_SRC)/visual.h
-kaleidescope.o: $(UTILS_SRC)/yarandom.h
-kumppa.o: ../config.h
-kumppa.o: $(srcdir)/fps.h
-kumppa.o: $(srcdir)/screenhackI.h
-kumppa.o: $(srcdir)/screenhack.h
-kumppa.o: $(UTILS_SRC)/colors.h
-kumppa.o: $(UTILS_SRC)/grabscreen.h
-kumppa.o: $(UTILS_SRC)/hsv.h
-kumppa.o: $(UTILS_SRC)/resources.h
-kumppa.o: $(UTILS_SRC)/usleep.h
-kumppa.o: $(UTILS_SRC)/visual.h
-kumppa.o: $(UTILS_SRC)/xdbe.h
-kumppa.o: $(UTILS_SRC)/yarandom.h
-laser.o: ../config.h
-laser.o: $(srcdir)/fps.h
-laser.o: $(srcdir)/screenhackI.h
-laser.o: $(UTILS_SRC)/colors.h
-laser.o: $(UTILS_SRC)/grabscreen.h
-laser.o: $(UTILS_SRC)/hsv.h
-laser.o: $(UTILS_SRC)/resources.h
-laser.o: $(UTILS_SRC)/usleep.h
-laser.o: $(UTILS_SRC)/visual.h
-laser.o: $(UTILS_SRC)/xshm.h
-laser.o: $(UTILS_SRC)/yarandom.h
-laser.o: $(srcdir)/xlockmoreI.h
-laser.o: $(srcdir)/xlockmore.h
-lcdscrub.o: ../config.h
-lcdscrub.o: $(srcdir)/fps.h
-lcdscrub.o: $(srcdir)/screenhackI.h
-lcdscrub.o: $(srcdir)/screenhack.h
-lcdscrub.o: $(UTILS_SRC)/colors.h
-lcdscrub.o: $(UTILS_SRC)/grabscreen.h
-lcdscrub.o: $(UTILS_SRC)/hsv.h
-lcdscrub.o: $(UTILS_SRC)/resources.h
-lcdscrub.o: $(UTILS_SRC)/usleep.h
-lcdscrub.o: $(UTILS_SRC)/visual.h
-lcdscrub.o: $(UTILS_SRC)/yarandom.h
-lightning.o: ../config.h
-lightning.o: $(srcdir)/fps.h
-lightning.o: $(srcdir)/screenhackI.h
-lightning.o: $(UTILS_SRC)/colors.h
-lightning.o: $(UTILS_SRC)/grabscreen.h
-lightning.o: $(UTILS_SRC)/hsv.h
-lightning.o: $(UTILS_SRC)/resources.h
-lightning.o: $(UTILS_SRC)/usleep.h
-lightning.o: $(UTILS_SRC)/visual.h
-lightning.o: $(UTILS_SRC)/xshm.h
-lightning.o: $(UTILS_SRC)/yarandom.h
-lightning.o: $(srcdir)/xlockmoreI.h
-lightning.o: $(srcdir)/xlockmore.h
-lisa.o: ../config.h
-lisa.o: $(srcdir)/fps.h
-lisa.o: $(srcdir)/screenhackI.h
-lisa.o: $(UTILS_SRC)/colors.h
-lisa.o: $(UTILS_SRC)/grabscreen.h
-lisa.o: $(UTILS_SRC)/hsv.h
-lisa.o: $(UTILS_SRC)/resources.h
-lisa.o: $(UTILS_SRC)/usleep.h
-lisa.o: $(UTILS_SRC)/visual.h
-lisa.o: $(UTILS_SRC)/xshm.h
-lisa.o: $(UTILS_SRC)/yarandom.h
-lisa.o: $(srcdir)/xlockmoreI.h
-lisa.o: $(srcdir)/xlockmore.h
-lissie.o: ../config.h
-lissie.o: $(srcdir)/fps.h
-lissie.o: $(srcdir)/screenhackI.h
-lissie.o: $(UTILS_SRC)/colors.h
-lissie.o: $(UTILS_SRC)/grabscreen.h
-lissie.o: $(UTILS_SRC)/hsv.h
-lissie.o: $(UTILS_SRC)/resources.h
-lissie.o: $(UTILS_SRC)/usleep.h
-lissie.o: $(UTILS_SRC)/visual.h
-lissie.o: $(UTILS_SRC)/xshm.h
-lissie.o: $(UTILS_SRC)/yarandom.h
-lissie.o: $(srcdir)/xlockmoreI.h
-lissie.o: $(srcdir)/xlockmore.h
-lmorph.o: ../config.h
-lmorph.o: $(srcdir)/fps.h
-lmorph.o: $(srcdir)/screenhackI.h
-lmorph.o: $(srcdir)/screenhack.h
-lmorph.o: $(UTILS_SRC)/colors.h
-lmorph.o: $(UTILS_SRC)/grabscreen.h
-lmorph.o: $(UTILS_SRC)/hsv.h
-lmorph.o: $(UTILS_SRC)/resources.h
-lmorph.o: $(UTILS_SRC)/usleep.h
-lmorph.o: $(UTILS_SRC)/visual.h
-lmorph.o: $(UTILS_SRC)/yarandom.h
-loop.o: $(srcdir)/automata.h
-loop.o: ../config.h
-loop.o: $(srcdir)/fps.h
-loop.o: $(srcdir)/screenhackI.h
-loop.o: $(UTILS_SRC)/colors.h
-loop.o: $(UTILS_SRC)/grabscreen.h
-loop.o: $(UTILS_SRC)/hsv.h
-loop.o: $(UTILS_SRC)/resources.h
-loop.o: $(UTILS_SRC)/usleep.h
-loop.o: $(UTILS_SRC)/visual.h
-loop.o: $(UTILS_SRC)/xshm.h
-loop.o: $(UTILS_SRC)/yarandom.h
-loop.o: $(srcdir)/xlockmoreI.h
-loop.o: $(srcdir)/xlockmore.h
-m6502.o: $(srcdir)/analogtv.h
-m6502.o: $(srcdir)/asm6502.h
-m6502.o: ../config.h
-m6502.o: $(srcdir)/fps.h
-m6502.o: m6502.h
-m6502.o: $(srcdir)/screenhackI.h
-m6502.o: $(srcdir)/screenhack.h
-m6502.o: $(UTILS_SRC)/colors.h
-m6502.o: $(UTILS_SRC)/grabscreen.h
-m6502.o: $(UTILS_SRC)/hsv.h
-m6502.o: $(UTILS_SRC)/resources.h
-m6502.o: $(UTILS_SRC)/usleep.h
-m6502.o: $(UTILS_SRC)/visual.h
-m6502.o: $(UTILS_SRC)/xshm.h
-m6502.o: $(UTILS_SRC)/yarandom.h
-maze.o: ../config.h
-maze.o: $(srcdir)/fps.h
-maze.o: $(srcdir)/screenhackI.h
-maze.o: $(srcdir)/screenhack.h
-maze.o: $(UTILS_SRC)/colors.h
-maze.o: $(UTILS_SRC)/erase.h
-maze.o: $(UTILS_SRC)/grabscreen.h
-maze.o: $(UTILS_SRC)/hsv.h
-maze.o: $(UTILS_SRC)/resources.h
-maze.o: $(UTILS_SRC)/usleep.h
-maze.o: $(UTILS_SRC)/visual.h
-maze.o: $(UTILS_SRC)/yarandom.h
-memscroller.o: ../config.h
-memscroller.o: $(srcdir)/fps.h
-memscroller.o: $(srcdir)/screenhackI.h
-memscroller.o: $(srcdir)/screenhack.h
-memscroller.o: $(UTILS_SRC)/colors.h
-memscroller.o: $(UTILS_SRC)/grabscreen.h
-memscroller.o: $(UTILS_SRC)/hsv.h
-memscroller.o: $(UTILS_SRC)/resources.h
-memscroller.o: $(UTILS_SRC)/usleep.h
-memscroller.o: $(UTILS_SRC)/visual.h
-memscroller.o: $(UTILS_SRC)/yarandom.h
-metaballs.o: ../config.h
-metaballs.o: $(srcdir)/fps.h
-metaballs.o: $(srcdir)/screenhackI.h
-metaballs.o: $(srcdir)/screenhack.h
-metaballs.o: $(UTILS_SRC)/colors.h
-metaballs.o: $(UTILS_SRC)/grabscreen.h
-metaballs.o: $(UTILS_SRC)/hsv.h
-metaballs.o: $(UTILS_SRC)/resources.h
-metaballs.o: $(UTILS_SRC)/usleep.h
-metaballs.o: $(UTILS_SRC)/visual.h
-metaballs.o: $(UTILS_SRC)/yarandom.h
-moire2.o: ../config.h
-moire2.o: $(srcdir)/fps.h
-moire2.o: $(srcdir)/screenhackI.h
-moire2.o: $(srcdir)/screenhack.h
-moire2.o: $(UTILS_SRC)/colors.h
-moire2.o: $(UTILS_SRC)/grabscreen.h
-moire2.o: $(UTILS_SRC)/hsv.h
-moire2.o: $(UTILS_SRC)/resources.h
-moire2.o: $(UTILS_SRC)/usleep.h
-moire2.o: $(UTILS_SRC)/visual.h
-moire2.o: $(UTILS_SRC)/xdbe.h
-moire2.o: $(UTILS_SRC)/yarandom.h
-moire.o: ../config.h
-moire.o: $(srcdir)/fps.h
-moire.o: $(srcdir)/screenhackI.h
-moire.o: $(srcdir)/screenhack.h
-moire.o: $(UTILS_SRC)/colors.h
-moire.o: $(UTILS_SRC)/grabscreen.h
-moire.o: $(UTILS_SRC)/hsv.h
-moire.o: $(UTILS_SRC)/resources.h
-moire.o: $(UTILS_SRC)/usleep.h
-moire.o: $(UTILS_SRC)/visual.h
-moire.o: $(UTILS_SRC)/yarandom.h
-mountain.o: ../config.h
-mountain.o: $(srcdir)/fps.h
-mountain.o: $(srcdir)/screenhackI.h
-mountain.o: $(UTILS_SRC)/colors.h
-mountain.o: $(UTILS_SRC)/grabscreen.h
-mountain.o: $(UTILS_SRC)/hsv.h
-mountain.o: $(UTILS_SRC)/resources.h
-mountain.o: $(UTILS_SRC)/usleep.h
-mountain.o: $(UTILS_SRC)/visual.h
-mountain.o: $(UTILS_SRC)/xshm.h
-mountain.o: $(UTILS_SRC)/yarandom.h
-mountain.o: $(srcdir)/xlockmoreI.h
-mountain.o: $(srcdir)/xlockmore.h
-munch.o: ../config.h
-munch.o: $(srcdir)/fps.h
-munch.o: $(srcdir)/screenhackI.h
-munch.o: $(srcdir)/screenhack.h
-munch.o: $(UTILS_SRC)/colors.h
-munch.o: $(UTILS_SRC)/grabscreen.h
-munch.o: $(UTILS_SRC)/hsv.h
-munch.o: $(UTILS_SRC)/resources.h
-munch.o: $(UTILS_SRC)/usleep.h
-munch.o: $(UTILS_SRC)/visual.h
-munch.o: $(UTILS_SRC)/yarandom.h
-nerverot.o: ../config.h
-nerverot.o: $(srcdir)/fps.h
-nerverot.o: $(srcdir)/screenhackI.h
-nerverot.o: $(srcdir)/screenhack.h
-nerverot.o: $(UTILS_SRC)/colors.h
-nerverot.o: $(UTILS_SRC)/grabscreen.h
-nerverot.o: $(UTILS_SRC)/hsv.h
-nerverot.o: $(UTILS_SRC)/resources.h
-nerverot.o: $(UTILS_SRC)/usleep.h
-nerverot.o: $(UTILS_SRC)/visual.h
-nerverot.o: $(UTILS_SRC)/yarandom.h
-noseguy.o: ../config.h
-noseguy.o: $(srcdir)/fps.h
-noseguy.o: $(srcdir)/images/noseguy/nose-f1.xpm
-noseguy.o: $(srcdir)/images/noseguy/nose-f2.xpm
-noseguy.o: $(srcdir)/images/noseguy/nose-f3.xpm
-noseguy.o: $(srcdir)/images/noseguy/nose-f4.xpm
-noseguy.o: $(srcdir)/images/noseguy/nose-l1.xpm
-noseguy.o: $(srcdir)/images/noseguy/nose-l2.xpm
-noseguy.o: $(srcdir)/images/noseguy/nose-r1.xpm
-noseguy.o: $(srcdir)/images/noseguy/nose-r2.xpm
-noseguy.o: $(srcdir)/screenhackI.h
-noseguy.o: $(srcdir)/screenhack.h
-noseguy.o: $(UTILS_SRC)/colors.h
-noseguy.o: $(UTILS_SRC)/grabscreen.h
-noseguy.o: $(UTILS_SRC)/hsv.h
-noseguy.o: $(UTILS_SRC)/resources.h
-noseguy.o: $(UTILS_SRC)/usleep.h
-noseguy.o: $(UTILS_SRC)/visual.h
-noseguy.o: $(UTILS_SRC)/yarandom.h
-noseguy.o: $(srcdir)/xpm-pixmap.h
-pacman_ai.o: ../config.h
-pacman_ai.o: $(srcdir)/fps.h
-pacman_ai.o: $(srcdir)/pacman_ai.h
-pacman_ai.o: $(srcdir)/pacman.h
-pacman_ai.o: $(srcdir)/pacman_level.h
-pacman_ai.o: $(srcdir)/screenhackI.h
-pacman_ai.o: $(UTILS_SRC)/colors.h
-pacman_ai.o: $(UTILS_SRC)/grabscreen.h
-pacman_ai.o: $(UTILS_SRC)/hsv.h
-pacman_ai.o: $(UTILS_SRC)/resources.h
-pacman_ai.o: $(UTILS_SRC)/usleep.h
-pacman_ai.o: $(UTILS_SRC)/visual.h
-pacman_ai.o: $(UTILS_SRC)/xshm.h
-pacman_ai.o: $(UTILS_SRC)/yarandom.h
-pacman_ai.o: $(srcdir)/xlockmoreI.h
-pacman_ai.o: $(srcdir)/xpm-pixmap.h
-pacman_level.o: ../config.h
-pacman_level.o: $(srcdir)/fps.h
-pacman_level.o: $(srcdir)/pacman.h
-pacman_level.o: $(srcdir)/pacman_level.h
-pacman_level.o: $(srcdir)/screenhackI.h
-pacman_level.o: $(UTILS_SRC)/colors.h
-pacman_level.o: $(UTILS_SRC)/grabscreen.h
-pacman_level.o: $(UTILS_SRC)/hsv.h
-pacman_level.o: $(UTILS_SRC)/resources.h
-pacman_level.o: $(UTILS_SRC)/usleep.h
-pacman_level.o: $(UTILS_SRC)/visual.h
-pacman_level.o: $(UTILS_SRC)/xshm.h
-pacman_level.o: $(UTILS_SRC)/yarandom.h
-pacman_level.o: $(srcdir)/xlockmoreI.h
-pacman_level.o: $(srcdir)/xpm-pixmap.h
-pacman.o: ../config.h
-pacman.o: $(srcdir)/fps.h
-pacman.o: $(srcdir)/images/pacman/eyes-d.xpm
-pacman.o: $(srcdir)/images/pacman/eyes-l.xpm
-pacman.o: $(srcdir)/images/pacman/eyes-r.xpm
-pacman.o: $(srcdir)/images/pacman/eyes-u.xpm
-pacman.o: $(srcdir)/images/pacman/ghost-d1.xpm
-pacman.o: $(srcdir)/images/pacman/ghost-d2.xpm
-pacman.o: $(srcdir)/images/pacman/ghost-l1.xpm
-pacman.o: $(srcdir)/images/pacman/ghost-l2.xpm
-pacman.o: $(srcdir)/images/pacman/ghost-mask.xpm
-pacman.o: $(srcdir)/images/pacman/ghost-r1.xpm
-pacman.o: $(srcdir)/images/pacman/ghost-r2.xpm
-pacman.o: $(srcdir)/images/pacman/ghost-s1.xpm
-pacman.o: $(srcdir)/images/pacman/ghost-s2.xpm
-pacman.o: $(srcdir)/images/pacman/ghost-sf1.xpm
-pacman.o: $(srcdir)/images/pacman/ghost-sf2.xpm
-pacman.o: $(srcdir)/images/pacman/ghost-u1.xpm
-pacman.o: $(srcdir)/images/pacman/ghost-u2.xpm
-pacman.o: $(srcdir)/images/pacman/pacman-0.xpm
-pacman.o: $(srcdir)/images/pacman/pacman-d1.xpm
-pacman.o: $(srcdir)/images/pacman/pacman-d2.xpm
-pacman.o: $(srcdir)/images/pacman/pacman-ds1.xpm
-pacman.o: $(srcdir)/images/pacman/pacman-ds2.xpm
-pacman.o: $(srcdir)/images/pacman/pacman-ds3.xpm
-pacman.o: $(srcdir)/images/pacman/pacman-ds4.xpm
-pacman.o: $(srcdir)/images/pacman/pacman-ds5.xpm
-pacman.o: $(srcdir)/images/pacman/pacman-ds6.xpm
-pacman.o: $(srcdir)/images/pacman/pacman-ds7.xpm
-pacman.o: $(srcdir)/images/pacman/pacman-ds8.xpm
-pacman.o: $(srcdir)/images/pacman/pacman-l1.xpm
-pacman.o: $(srcdir)/images/pacman/pacman-l2.xpm
-pacman.o: $(srcdir)/images/pacman/pacman-r1.xpm
-pacman.o: $(srcdir)/images/pacman/pacman-r2.xpm
-pacman.o: $(srcdir)/images/pacman/pacman-u1.xpm
-pacman.o: $(srcdir)/images/pacman/pacman-u2.xpm
-pacman.o: $(srcdir)/pacman_ai.h
-pacman.o: $(srcdir)/pacman.h
-pacman.o: $(srcdir)/pacman_level.h
-pacman.o: $(srcdir)/screenhackI.h
-pacman.o: $(UTILS_SRC)/colors.h
-pacman.o: $(UTILS_SRC)/grabscreen.h
-pacman.o: $(UTILS_SRC)/hsv.h
-pacman.o: $(UTILS_SRC)/resources.h
-pacman.o: $(UTILS_SRC)/usleep.h
-pacman.o: $(UTILS_SRC)/visual.h
-pacman.o: $(UTILS_SRC)/xshm.h
-pacman.o: $(UTILS_SRC)/yarandom.h
-pacman.o: $(srcdir)/xlockmoreI.h
-pacman.o: $(srcdir)/xlockmore.h
-pacman.o: $(srcdir)/xpm-pixmap.h
-pedal.o: ../config.h
-pedal.o: $(srcdir)/fps.h
-pedal.o: $(srcdir)/screenhackI.h
-pedal.o: $(srcdir)/screenhack.h
-pedal.o: $(UTILS_SRC)/colors.h
-pedal.o: $(UTILS_SRC)/erase.h
-pedal.o: $(UTILS_SRC)/grabscreen.h
-pedal.o: $(UTILS_SRC)/hsv.h
-pedal.o: $(UTILS_SRC)/resources.h
-pedal.o: $(UTILS_SRC)/usleep.h
-pedal.o: $(UTILS_SRC)/visual.h
-pedal.o: $(UTILS_SRC)/yarandom.h
-penetrate.o: ../config.h
-penetrate.o: $(srcdir)/fps.h
-penetrate.o: $(srcdir)/screenhackI.h
-penetrate.o: $(srcdir)/screenhack.h
-penetrate.o: $(UTILS_SRC)/colors.h
-penetrate.o: $(UTILS_SRC)/grabscreen.h
-penetrate.o: $(UTILS_SRC)/hsv.h
-penetrate.o: $(UTILS_SRC)/resources.h
-penetrate.o: $(UTILS_SRC)/usleep.h
-penetrate.o: $(UTILS_SRC)/visual.h
-penetrate.o: $(UTILS_SRC)/yarandom.h
-penrose.o: ../config.h
-penrose.o: $(srcdir)/fps.h
-penrose.o: $(srcdir)/screenhackI.h
-penrose.o: $(UTILS_SRC)/colors.h
-penrose.o: $(UTILS_SRC)/grabscreen.h
-penrose.o: $(UTILS_SRC)/hsv.h
-penrose.o: $(UTILS_SRC)/resources.h
-penrose.o: $(UTILS_SRC)/usleep.h
-penrose.o: $(UTILS_SRC)/visual.h
-penrose.o: $(UTILS_SRC)/xshm.h
-penrose.o: $(UTILS_SRC)/yarandom.h
-penrose.o: $(srcdir)/xlockmoreI.h
-penrose.o: $(srcdir)/xlockmore.h
-petri.o: ../config.h
-petri.o: $(srcdir)/fps.h
-petri.o: $(srcdir)/screenhackI.h
-petri.o: $(srcdir)/screenhack.h
-petri.o: $(UTILS_SRC)/colors.h
-petri.o: $(UTILS_SRC)/grabscreen.h
-petri.o: $(UTILS_SRC)/hsv.h
-petri.o: $(UTILS_SRC)/resources.h
-petri.o: $(UTILS_SRC)/spline.h
-petri.o: $(UTILS_SRC)/usleep.h
-petri.o: $(UTILS_SRC)/visual.h
-petri.o: $(UTILS_SRC)/yarandom.h
-phosphor.o: ../config.h
-phosphor.o: $(srcdir)/fps.h
-phosphor.o: $(srcdir)/images/6x10font.xbm
-phosphor.o: $(srcdir)/screenhackI.h
-phosphor.o: $(srcdir)/screenhack.h
-phosphor.o: $(UTILS_SRC)/colors.h
-phosphor.o: $(UTILS_SRC)/grabscreen.h
-phosphor.o: $(UTILS_SRC)/hsv.h
-phosphor.o: $(UTILS_SRC)/resources.h
-phosphor.o: $(UTILS_SRC)/usleep.h
-phosphor.o: $(UTILS_SRC)/visual.h
-phosphor.o: $(UTILS_SRC)/yarandom.h
-piecewise.o: ../config.h
-piecewise.o: $(srcdir)/fps.h
-piecewise.o: $(srcdir)/screenhackI.h
-piecewise.o: $(srcdir)/screenhack.h
-piecewise.o: $(UTILS_SRC)/colors.h
-piecewise.o: $(UTILS_SRC)/grabscreen.h
-piecewise.o: $(UTILS_SRC)/hsv.h
-piecewise.o: $(UTILS_SRC)/resources.h
-piecewise.o: $(UTILS_SRC)/usleep.h
-piecewise.o: $(UTILS_SRC)/visual.h
-piecewise.o: $(UTILS_SRC)/xdbe.h
-piecewise.o: $(UTILS_SRC)/yarandom.h
-polyominoes.o: ../config.h
-polyominoes.o: $(srcdir)/fps.h
-polyominoes.o: $(srcdir)/screenhackI.h
-polyominoes.o: $(UTILS_SRC)/colors.h
-polyominoes.o: $(UTILS_SRC)/erase.h
-polyominoes.o: $(UTILS_SRC)/grabscreen.h
-polyominoes.o: $(UTILS_SRC)/hsv.h
-polyominoes.o: $(UTILS_SRC)/resources.h
-polyominoes.o: $(UTILS_SRC)/usleep.h
-polyominoes.o: $(UTILS_SRC)/visual.h
-polyominoes.o: $(UTILS_SRC)/xshm.h
-polyominoes.o: $(UTILS_SRC)/yarandom.h
-polyominoes.o: $(srcdir)/xlockmoreI.h
-polyominoes.o: $(srcdir)/xlockmore.h
-pong.o: $(srcdir)/analogtv.h
-pong.o: ../config.h
-pong.o: $(srcdir)/fps.h
-pong.o: $(srcdir)/screenhackI.h
-pong.o: $(srcdir)/screenhack.h
-pong.o: $(UTILS_SRC)/colors.h
-pong.o: $(UTILS_SRC)/grabscreen.h
-pong.o: $(UTILS_SRC)/hsv.h
-pong.o: $(UTILS_SRC)/resources.h
-pong.o: $(UTILS_SRC)/usleep.h
-pong.o: $(UTILS_SRC)/visual.h
-pong.o: $(UTILS_SRC)/xshm.h
-pong.o: $(UTILS_SRC)/yarandom.h
-popsquares.o: ../config.h
-popsquares.o: $(srcdir)/fps.h
-popsquares.o: $(srcdir)/screenhackI.h
-popsquares.o: $(srcdir)/screenhack.h
-popsquares.o: $(UTILS_SRC)/colors.h
-popsquares.o: $(UTILS_SRC)/grabscreen.h
-popsquares.o: $(UTILS_SRC)/hsv.h
-popsquares.o: $(UTILS_SRC)/resources.h
-popsquares.o: $(UTILS_SRC)/usleep.h
-popsquares.o: $(UTILS_SRC)/visual.h
-popsquares.o: $(UTILS_SRC)/xdbe.h
-popsquares.o: $(UTILS_SRC)/yarandom.h
-pyro.o: ../config.h
-pyro.o: $(srcdir)/fps.h
-pyro.o: $(srcdir)/screenhackI.h
-pyro.o: $(srcdir)/screenhack.h
-pyro.o: $(UTILS_SRC)/colors.h
-pyro.o: $(UTILS_SRC)/grabscreen.h
-pyro.o: $(UTILS_SRC)/hsv.h
-pyro.o: $(UTILS_SRC)/resources.h
-pyro.o: $(UTILS_SRC)/usleep.h
-pyro.o: $(UTILS_SRC)/visual.h
-pyro.o: $(UTILS_SRC)/yarandom.h
-qix.o: ../config.h
-qix.o: $(srcdir)/fps.h
-qix.o: $(srcdir)/screenhackI.h
-qix.o: $(srcdir)/screenhack.h
-qix.o: $(UTILS_SRC)/alpha.h
-qix.o: $(UTILS_SRC)/colors.h
-qix.o: $(UTILS_SRC)/grabscreen.h
-qix.o: $(UTILS_SRC)/hsv.h
-qix.o: $(UTILS_SRC)/resources.h
-qix.o: $(UTILS_SRC)/usleep.h
-qix.o: $(UTILS_SRC)/visual.h
-qix.o: $(UTILS_SRC)/yarandom.h
-rd-bomb.o: ../config.h
-rd-bomb.o: $(srcdir)/fps.h
-rd-bomb.o: $(srcdir)/screenhackI.h
-rd-bomb.o: $(srcdir)/screenhack.h
-rd-bomb.o: $(UTILS_SRC)/colors.h
-rd-bomb.o: $(UTILS_SRC)/grabscreen.h
-rd-bomb.o: $(UTILS_SRC)/hsv.h
-rd-bomb.o: $(UTILS_SRC)/resources.h
-rd-bomb.o: $(UTILS_SRC)/usleep.h
-rd-bomb.o: $(UTILS_SRC)/visual.h
-rd-bomb.o: $(UTILS_SRC)/yarandom.h
-ripples.o: ../config.h
-ripples.o: $(srcdir)/fps.h
-ripples.o: $(srcdir)/screenhackI.h
-ripples.o: $(srcdir)/screenhack.h
-ripples.o: $(UTILS_SRC)/colors.h
-ripples.o: $(UTILS_SRC)/grabscreen.h
-ripples.o: $(UTILS_SRC)/hsv.h
-ripples.o: $(UTILS_SRC)/resources.h
-ripples.o: $(UTILS_SRC)/usleep.h
-ripples.o: $(UTILS_SRC)/visual.h
-ripples.o: $(UTILS_SRC)/yarandom.h
-rocks.o: ../config.h
-rocks.o: $(srcdir)/fps.h
-rocks.o: $(srcdir)/screenhackI.h
-rocks.o: $(srcdir)/screenhack.h
-rocks.o: $(UTILS_SRC)/colors.h
-rocks.o: $(UTILS_SRC)/grabscreen.h
-rocks.o: $(UTILS_SRC)/hsv.h
-rocks.o: $(UTILS_SRC)/resources.h
-rocks.o: $(UTILS_SRC)/usleep.h
-rocks.o: $(UTILS_SRC)/visual.h
-rocks.o: $(UTILS_SRC)/yarandom.h
-rorschach.o: ../config.h
-rorschach.o: $(srcdir)/fps.h
-rorschach.o: $(srcdir)/screenhackI.h
-rorschach.o: $(srcdir)/screenhack.h
-rorschach.o: $(UTILS_SRC)/colors.h
-rorschach.o: $(UTILS_SRC)/erase.h
-rorschach.o: $(UTILS_SRC)/grabscreen.h
-rorschach.o: $(UTILS_SRC)/hsv.h
-rorschach.o: $(UTILS_SRC)/resources.h
-rorschach.o: $(UTILS_SRC)/usleep.h
-rorschach.o: $(UTILS_SRC)/visual.h
-rorschach.o: $(UTILS_SRC)/yarandom.h
-rotor.o: ../config.h
-rotor.o: $(srcdir)/fps.h
-rotor.o: $(srcdir)/screenhackI.h
-rotor.o: $(UTILS_SRC)/colors.h
-rotor.o: $(UTILS_SRC)/grabscreen.h
-rotor.o: $(UTILS_SRC)/hsv.h
-rotor.o: $(UTILS_SRC)/resources.h
-rotor.o: $(UTILS_SRC)/usleep.h
-rotor.o: $(UTILS_SRC)/visual.h
-rotor.o: $(UTILS_SRC)/xshm.h
-rotor.o: $(UTILS_SRC)/yarandom.h
-rotor.o: $(srcdir)/xlockmoreI.h
-rotor.o: $(srcdir)/xlockmore.h
-rotzoomer.o: ../config.h
-rotzoomer.o: $(srcdir)/fps.h
-rotzoomer.o: $(srcdir)/screenhackI.h
-rotzoomer.o: $(srcdir)/screenhack.h
-rotzoomer.o: $(UTILS_SRC)/colors.h
-rotzoomer.o: $(UTILS_SRC)/grabscreen.h
-rotzoomer.o: $(UTILS_SRC)/hsv.h
-rotzoomer.o: $(UTILS_SRC)/resources.h
-rotzoomer.o: $(UTILS_SRC)/usleep.h
-rotzoomer.o: $(UTILS_SRC)/visual.h
-rotzoomer.o: $(UTILS_SRC)/yarandom.h
-screenhack.o: ../config.h
-screenhack.o: $(srcdir)/fps.h
-screenhack.o: $(srcdir)/screenhackI.h
-screenhack.o: $(UTILS_SRC)/colors.h
-screenhack.o: $(UTILS_SRC)/grabscreen.h
-screenhack.o: $(UTILS_SRC)/hsv.h
-screenhack.o: $(UTILS_SRC)/resources.h
-screenhack.o: $(UTILS_SRC)/usleep.h
-screenhack.o: $(UTILS_SRC)/version.h
-screenhack.o: $(UTILS_SRC)/visual.h
-screenhack.o: $(UTILS_SRC)/vroot.h
-screenhack.o: $(UTILS_SRC)/xmu.h
-screenhack.o: $(UTILS_SRC)/yarandom.h
-shadebobs.o: ../config.h
-shadebobs.o: $(srcdir)/fps.h
-shadebobs.o: $(srcdir)/screenhackI.h
-shadebobs.o: $(srcdir)/screenhack.h
-shadebobs.o: $(UTILS_SRC)/colors.h
-shadebobs.o: $(UTILS_SRC)/grabscreen.h
-shadebobs.o: $(UTILS_SRC)/hsv.h
-shadebobs.o: $(UTILS_SRC)/resources.h
-shadebobs.o: $(UTILS_SRC)/usleep.h
-shadebobs.o: $(UTILS_SRC)/visual.h
-shadebobs.o: $(UTILS_SRC)/yarandom.h
-sierpinski.o: ../config.h
-sierpinski.o: $(srcdir)/fps.h
-sierpinski.o: $(srcdir)/screenhackI.h
-sierpinski.o: $(UTILS_SRC)/colors.h
-sierpinski.o: $(UTILS_SRC)/grabscreen.h
-sierpinski.o: $(UTILS_SRC)/hsv.h
-sierpinski.o: $(UTILS_SRC)/resources.h
-sierpinski.o: $(UTILS_SRC)/usleep.h
-sierpinski.o: $(UTILS_SRC)/visual.h
-sierpinski.o: $(UTILS_SRC)/xshm.h
-sierpinski.o: $(UTILS_SRC)/yarandom.h
-sierpinski.o: $(srcdir)/xlockmoreI.h
-sierpinski.o: $(srcdir)/xlockmore.h
-slidescreen.o: ../config.h
-slidescreen.o: $(srcdir)/fps.h
-slidescreen.o: $(srcdir)/screenhackI.h
-slidescreen.o: $(srcdir)/screenhack.h
-slidescreen.o: $(UTILS_SRC)/colors.h
-slidescreen.o: $(UTILS_SRC)/grabscreen.h
-slidescreen.o: $(UTILS_SRC)/hsv.h
-slidescreen.o: $(UTILS_SRC)/resources.h
-slidescreen.o: $(UTILS_SRC)/usleep.h
-slidescreen.o: $(UTILS_SRC)/visual.h
-slidescreen.o: $(UTILS_SRC)/yarandom.h
-slip.o: ../config.h
-slip.o: $(srcdir)/fps.h
-slip.o: $(srcdir)/screenhackI.h
-slip.o: $(UTILS_SRC)/colors.h
-slip.o: $(UTILS_SRC)/grabscreen.h
-slip.o: $(UTILS_SRC)/hsv.h
-slip.o: $(UTILS_SRC)/resources.h
-slip.o: $(UTILS_SRC)/usleep.h
-slip.o: $(UTILS_SRC)/visual.h
-slip.o: $(UTILS_SRC)/xshm.h
-slip.o: $(UTILS_SRC)/yarandom.h
-slip.o: $(srcdir)/xlockmoreI.h
-slip.o: $(srcdir)/xlockmore.h
-speedmine.o: ../config.h
-speedmine.o: $(srcdir)/fps.h
-speedmine.o: $(srcdir)/screenhackI.h
-speedmine.o: $(srcdir)/screenhack.h
-speedmine.o: $(UTILS_SRC)/colors.h
-speedmine.o: $(UTILS_SRC)/erase.h
-speedmine.o: $(UTILS_SRC)/grabscreen.h
-speedmine.o: $(UTILS_SRC)/hsv.h
-speedmine.o: $(UTILS_SRC)/resources.h
-speedmine.o: $(UTILS_SRC)/usleep.h
-speedmine.o: $(UTILS_SRC)/visual.h
-speedmine.o: $(UTILS_SRC)/yarandom.h
-sphere.o: ../config.h
-sphere.o: $(srcdir)/fps.h
-sphere.o: $(srcdir)/screenhackI.h
-sphere.o: $(UTILS_SRC)/colors.h
-sphere.o: $(UTILS_SRC)/grabscreen.h
-sphere.o: $(UTILS_SRC)/hsv.h
-sphere.o: $(UTILS_SRC)/resources.h
-sphere.o: $(UTILS_SRC)/usleep.h
-sphere.o: $(UTILS_SRC)/visual.h
-sphere.o: $(UTILS_SRC)/xshm.h
-sphere.o: $(UTILS_SRC)/yarandom.h
-sphere.o: $(srcdir)/xlockmoreI.h
-sphere.o: $(srcdir)/xlockmore.h
-spiral.o: ../config.h
-spiral.o: $(srcdir)/fps.h
-spiral.o: $(srcdir)/screenhackI.h
-spiral.o: $(UTILS_SRC)/colors.h
-spiral.o: $(UTILS_SRC)/grabscreen.h
-spiral.o: $(UTILS_SRC)/hsv.h
-spiral.o: $(UTILS_SRC)/resources.h
-spiral.o: $(UTILS_SRC)/usleep.h
-spiral.o: $(UTILS_SRC)/visual.h
-spiral.o: $(UTILS_SRC)/xshm.h
-spiral.o: $(UTILS_SRC)/yarandom.h
-spiral.o: $(srcdir)/xlockmoreI.h
-spiral.o: $(srcdir)/xlockmore.h
-spotlight.o: ../config.h
-spotlight.o: $(srcdir)/fps.h
-spotlight.o: $(srcdir)/screenhackI.h
-spotlight.o: $(srcdir)/screenhack.h
-spotlight.o: $(UTILS_SRC)/colors.h
-spotlight.o: $(UTILS_SRC)/grabscreen.h
-spotlight.o: $(UTILS_SRC)/hsv.h
-spotlight.o: $(UTILS_SRC)/resources.h
-spotlight.o: $(UTILS_SRC)/usleep.h
-spotlight.o: $(UTILS_SRC)/visual.h
-spotlight.o: $(UTILS_SRC)/yarandom.h
-squiral.o: ../config.h
-squiral.o: $(srcdir)/fps.h
-squiral.o: $(srcdir)/screenhackI.h
-squiral.o: $(srcdir)/screenhack.h
-squiral.o: $(UTILS_SRC)/colors.h
-squiral.o: $(UTILS_SRC)/erase.h
-squiral.o: $(UTILS_SRC)/grabscreen.h
-squiral.o: $(UTILS_SRC)/hsv.h
-squiral.o: $(UTILS_SRC)/resources.h
-squiral.o: $(UTILS_SRC)/usleep.h
-squiral.o: $(UTILS_SRC)/visual.h
-squiral.o: $(UTILS_SRC)/yarandom.h
-starfish.o: ../config.h
-starfish.o: $(srcdir)/fps.h
-starfish.o: $(srcdir)/screenhackI.h
-starfish.o: $(srcdir)/screenhack.h
-starfish.o: $(UTILS_SRC)/colors.h
-starfish.o: $(UTILS_SRC)/grabscreen.h
-starfish.o: $(UTILS_SRC)/hsv.h
-starfish.o: $(UTILS_SRC)/resources.h
-starfish.o: $(UTILS_SRC)/spline.h
-starfish.o: $(UTILS_SRC)/usleep.h
-starfish.o: $(UTILS_SRC)/visual.h
-starfish.o: $(UTILS_SRC)/yarandom.h
-strange.o: ../config.h
-strange.o: $(srcdir)/fps.h
-strange.o: $(srcdir)/screenhackI.h
-strange.o: $(UTILS_SRC)/colors.h
-strange.o: $(UTILS_SRC)/grabscreen.h
-strange.o: $(UTILS_SRC)/hsv.h
-strange.o: $(UTILS_SRC)/resources.h
-strange.o: $(UTILS_SRC)/usleep.h
-strange.o: $(UTILS_SRC)/visual.h
-strange.o: $(UTILS_SRC)/xshm.h
-strange.o: $(UTILS_SRC)/yarandom.h
-strange.o: $(srcdir)/xlockmoreI.h
-strange.o: $(srcdir)/xlockmore.h
-substrate.o: ../config.h
-substrate.o: $(srcdir)/fps.h
-substrate.o: $(srcdir)/screenhackI.h
-substrate.o: $(srcdir)/screenhack.h
-substrate.o: $(UTILS_SRC)/colors.h
-substrate.o: $(UTILS_SRC)/grabscreen.h
-substrate.o: $(UTILS_SRC)/hsv.h
-substrate.o: $(UTILS_SRC)/resources.h
-substrate.o: $(UTILS_SRC)/usleep.h
-substrate.o: $(UTILS_SRC)/visual.h
-substrate.o: $(UTILS_SRC)/yarandom.h
-swirl.o: ../config.h
-swirl.o: $(srcdir)/fps.h
-swirl.o: $(srcdir)/screenhackI.h
-swirl.o: $(UTILS_SRC)/colors.h
-swirl.o: $(UTILS_SRC)/grabscreen.h
-swirl.o: $(UTILS_SRC)/hsv.h
-swirl.o: $(UTILS_SRC)/resources.h
-swirl.o: $(UTILS_SRC)/usleep.h
-swirl.o: $(UTILS_SRC)/visual.h
-swirl.o: $(UTILS_SRC)/xshm.h
-swirl.o: $(UTILS_SRC)/yarandom.h
-swirl.o: $(srcdir)/xlockmoreI.h
-swirl.o: $(srcdir)/xlockmore.h
-t3d.o: ../config.h
-t3d.o: $(srcdir)/fps.h
-t3d.o: $(srcdir)/screenhackI.h
-t3d.o: $(srcdir)/screenhack.h
-t3d.o: $(UTILS_SRC)/colors.h
-t3d.o: $(UTILS_SRC)/grabscreen.h
-t3d.o: $(UTILS_SRC)/hsv.h
-t3d.o: $(UTILS_SRC)/resources.h
-t3d.o: $(UTILS_SRC)/usleep.h
-t3d.o: $(UTILS_SRC)/visual.h
-t3d.o: $(UTILS_SRC)/yarandom.h
-thornbird.o: ../config.h
-thornbird.o: $(srcdir)/fps.h
-thornbird.o: $(srcdir)/screenhackI.h
-thornbird.o: $(UTILS_SRC)/colors.h
-thornbird.o: $(UTILS_SRC)/grabscreen.h
-thornbird.o: $(UTILS_SRC)/hsv.h
-thornbird.o: $(UTILS_SRC)/resources.h
-thornbird.o: $(UTILS_SRC)/usleep.h
-thornbird.o: $(UTILS_SRC)/visual.h
-thornbird.o: $(UTILS_SRC)/xshm.h
-thornbird.o: $(UTILS_SRC)/yarandom.h
-thornbird.o: $(srcdir)/xlockmoreI.h
-thornbird.o: $(srcdir)/xlockmore.h
-triangle.o: ../config.h
-triangle.o: $(srcdir)/fps.h
-triangle.o: $(srcdir)/screenhackI.h
-triangle.o: $(UTILS_SRC)/colors.h
-triangle.o: $(UTILS_SRC)/grabscreen.h
-triangle.o: $(UTILS_SRC)/hsv.h
-triangle.o: $(UTILS_SRC)/resources.h
-triangle.o: $(UTILS_SRC)/usleep.h
-triangle.o: $(UTILS_SRC)/visual.h
-triangle.o: $(UTILS_SRC)/xshm.h
-triangle.o: $(UTILS_SRC)/yarandom.h
-triangle.o: $(srcdir)/xlockmoreI.h
-triangle.o: $(srcdir)/xlockmore.h
-truchet.o: ../config.h
-truchet.o: $(srcdir)/fps.h
-truchet.o: $(srcdir)/screenhackI.h
-truchet.o: $(srcdir)/screenhack.h
-truchet.o: $(UTILS_SRC)/colors.h
-truchet.o: $(UTILS_SRC)/grabscreen.h
-truchet.o: $(UTILS_SRC)/hsv.h
-truchet.o: $(UTILS_SRC)/resources.h
-truchet.o: $(UTILS_SRC)/usleep.h
-truchet.o: $(UTILS_SRC)/visual.h
-truchet.o: $(UTILS_SRC)/yarandom.h
-twang.o: ../config.h
-twang.o: $(srcdir)/fps.h
-twang.o: $(srcdir)/screenhackI.h
-twang.o: $(srcdir)/screenhack.h
-twang.o: $(UTILS_SRC)/colors.h
-twang.o: $(UTILS_SRC)/grabscreen.h
-twang.o: $(UTILS_SRC)/hsv.h
-twang.o: $(UTILS_SRC)/resources.h
-twang.o: $(UTILS_SRC)/usleep.h
-twang.o: $(UTILS_SRC)/visual.h
-twang.o: $(UTILS_SRC)/yarandom.h
-vermiculate.o: ../config.h
-vermiculate.o: $(srcdir)/fps.h
-vermiculate.o: $(srcdir)/screenhackI.h
-vermiculate.o: $(srcdir)/screenhack.h
-vermiculate.o: $(UTILS_SRC)/colors.h
-vermiculate.o: $(UTILS_SRC)/grabscreen.h
-vermiculate.o: $(UTILS_SRC)/hsv.h
-vermiculate.o: $(UTILS_SRC)/resources.h
-vermiculate.o: $(UTILS_SRC)/usleep.h
-vermiculate.o: $(UTILS_SRC)/visual.h
-vermiculate.o: $(UTILS_SRC)/yarandom.h
-vines.o: ../config.h
-vines.o: $(srcdir)/fps.h
-vines.o: $(srcdir)/screenhackI.h
-vines.o: $(UTILS_SRC)/colors.h
-vines.o: $(UTILS_SRC)/erase.h
-vines.o: $(UTILS_SRC)/grabscreen.h
-vines.o: $(UTILS_SRC)/hsv.h
-vines.o: $(UTILS_SRC)/resources.h
-vines.o: $(UTILS_SRC)/usleep.h
-vines.o: $(UTILS_SRC)/visual.h
-vines.o: $(UTILS_SRC)/xshm.h
-vines.o: $(UTILS_SRC)/yarandom.h
-vines.o: $(srcdir)/xlockmoreI.h
-vines.o: $(srcdir)/xlockmore.h
-wander.o: ../config.h
-wander.o: $(srcdir)/fps.h
-wander.o: $(srcdir)/screenhackI.h
-wander.o: $(srcdir)/screenhack.h
-wander.o: $(UTILS_SRC)/colors.h
-wander.o: $(UTILS_SRC)/erase.h
-wander.o: $(UTILS_SRC)/grabscreen.h
-wander.o: $(UTILS_SRC)/hsv.h
-wander.o: $(UTILS_SRC)/resources.h
-wander.o: $(UTILS_SRC)/usleep.h
-wander.o: $(UTILS_SRC)/visual.h
-wander.o: $(UTILS_SRC)/yarandom.h
-webcollage-cocoa.o: ../config.h
-webcollage-cocoa.o: $(srcdir)/fps.h
-webcollage-cocoa.o: $(srcdir)/screenhackI.h
-webcollage-cocoa.o: $(srcdir)/screenhack.h
-webcollage-cocoa.o: $(UTILS_SRC)/colors.h
-webcollage-cocoa.o: $(UTILS_SRC)/grabscreen.h
-webcollage-cocoa.o: $(UTILS_SRC)/hsv.h
-webcollage-cocoa.o: $(UTILS_SRC)/resources.h
-webcollage-cocoa.o: $(UTILS_SRC)/usleep.h
-webcollage-cocoa.o: $(UTILS_SRC)/visual.h
-webcollage-cocoa.o: $(UTILS_SRC)/yarandom.h
-webcollage-helper.o: ../config.h
-whirlwindwarp.o: ../config.h
-whirlwindwarp.o: $(srcdir)/fps.h
-whirlwindwarp.o: $(srcdir)/screenhackI.h
-whirlwindwarp.o: $(srcdir)/screenhack.h
-whirlwindwarp.o: $(UTILS_SRC)/colors.h
-whirlwindwarp.o: $(UTILS_SRC)/erase.h
-whirlwindwarp.o: $(UTILS_SRC)/grabscreen.h
-whirlwindwarp.o: $(UTILS_SRC)/hsv.h
-whirlwindwarp.o: $(UTILS_SRC)/resources.h
-whirlwindwarp.o: $(UTILS_SRC)/usleep.h
-whirlwindwarp.o: $(UTILS_SRC)/visual.h
-whirlwindwarp.o: $(UTILS_SRC)/yarandom.h
-whirlygig.o: ../config.h
-whirlygig.o: $(srcdir)/fps.h
-whirlygig.o: $(srcdir)/screenhackI.h
-whirlygig.o: $(srcdir)/screenhack.h
-whirlygig.o: $(UTILS_SRC)/colors.h
-whirlygig.o: $(UTILS_SRC)/grabscreen.h
-whirlygig.o: $(UTILS_SRC)/hsv.h
-whirlygig.o: $(UTILS_SRC)/resources.h
-whirlygig.o: $(UTILS_SRC)/usleep.h
-whirlygig.o: $(UTILS_SRC)/visual.h
-whirlygig.o: $(UTILS_SRC)/xdbe.h
-whirlygig.o: $(UTILS_SRC)/yarandom.h
-wormhole.o: ../config.h
-wormhole.o: $(srcdir)/fps.h
-wormhole.o: $(srcdir)/screenhackI.h
-wormhole.o: $(srcdir)/screenhack.h
-wormhole.o: $(UTILS_SRC)/colors.h
-wormhole.o: $(UTILS_SRC)/grabscreen.h
-wormhole.o: $(UTILS_SRC)/hsv.h
-wormhole.o: $(UTILS_SRC)/resources.h
-wormhole.o: $(UTILS_SRC)/usleep.h
-wormhole.o: $(UTILS_SRC)/visual.h
-wormhole.o: $(UTILS_SRC)/yarandom.h
-worm.o: ../config.h
-worm.o: $(srcdir)/fps.h
-worm.o: $(srcdir)/screenhackI.h
-worm.o: $(UTILS_SRC)/colors.h
-worm.o: $(UTILS_SRC)/grabscreen.h
-worm.o: $(UTILS_SRC)/hsv.h
-worm.o: $(UTILS_SRC)/resources.h
-worm.o: $(UTILS_SRC)/usleep.h
-worm.o: $(UTILS_SRC)/visual.h
-worm.o: $(UTILS_SRC)/xshm.h
-worm.o: $(UTILS_SRC)/yarandom.h
-worm.o: $(srcdir)/xlockmoreI.h
-worm.o: $(srcdir)/xlockmore.h
-xanalogtv.o: $(srcdir)/analogtv.h
-xanalogtv.o: ../config.h
-xanalogtv.o: $(srcdir)/fps.h
-xanalogtv.o: $(srcdir)/screenhackI.h
-xanalogtv.o: $(srcdir)/screenhack.h
-xanalogtv.o: $(UTILS_SRC)/colors.h
-xanalogtv.o: $(UTILS_SRC)/grabscreen.h
-xanalogtv.o: $(UTILS_SRC)/hsv.h
-xanalogtv.o: $(UTILS_SRC)/images/logo-50.xpm
-xanalogtv.o: $(UTILS_SRC)/resources.h
-xanalogtv.o: $(UTILS_SRC)/usleep.h
-xanalogtv.o: $(UTILS_SRC)/visual.h
-xanalogtv.o: $(UTILS_SRC)/xshm.h
-xanalogtv.o: $(UTILS_SRC)/yarandom.h
-xanalogtv.o: $(srcdir)/xpm-pixmap.h
-xflame.o: ../config.h
-xflame.o: $(srcdir)/fps.h
-xflame.o: $(srcdir)/images/bob.xbm
-xflame.o: $(srcdir)/screenhackI.h
-xflame.o: $(srcdir)/screenhack.h
-xflame.o: $(UTILS_SRC)/colors.h
-xflame.o: $(UTILS_SRC)/grabscreen.h
-xflame.o: $(UTILS_SRC)/hsv.h
-xflame.o: $(UTILS_SRC)/resources.h
-xflame.o: $(UTILS_SRC)/usleep.h
-xflame.o: $(UTILS_SRC)/visual.h
-xflame.o: $(UTILS_SRC)/yarandom.h
-xflame.o: $(srcdir)/xpm-pixmap.h
-xjack.o: ../config.h
-xjack.o: $(srcdir)/fps.h
-xjack.o: $(srcdir)/screenhackI.h
-xjack.o: $(srcdir)/screenhack.h
-xjack.o: $(UTILS_SRC)/colors.h
-xjack.o: $(UTILS_SRC)/grabscreen.h
-xjack.o: $(UTILS_SRC)/hsv.h
-xjack.o: $(UTILS_SRC)/resources.h
-xjack.o: $(UTILS_SRC)/usleep.h
-xjack.o: $(UTILS_SRC)/visual.h
-xjack.o: $(UTILS_SRC)/yarandom.h
-xlockmore.o: ../config.h
-xlockmore.o: $(srcdir)/fps.h
-xlockmore.o: $(srcdir)/screenhackI.h
-xlockmore.o: $(srcdir)/screenhack.h
-xlockmore.o: $(UTILS_SRC)/colors.h
-xlockmore.o: $(UTILS_SRC)/grabscreen.h
-xlockmore.o: $(UTILS_SRC)/hsv.h
-xlockmore.o: $(UTILS_SRC)/resources.h
-xlockmore.o: $(UTILS_SRC)/usleep.h
-xlockmore.o: $(UTILS_SRC)/visual.h
-xlockmore.o: $(UTILS_SRC)/xshm.h
-xlockmore.o: $(UTILS_SRC)/yarandom.h
-xlockmore.o: $(srcdir)/xlockmoreI.h
-xlyap.o: ../config.h
-xlyap.o: $(srcdir)/fps.h
-xlyap.o: $(srcdir)/screenhackI.h
-xlyap.o: $(srcdir)/screenhack.h
-xlyap.o: $(UTILS_SRC)/colors.h
-xlyap.o: $(UTILS_SRC)/grabscreen.h
-xlyap.o: $(UTILS_SRC)/hsv.h
-xlyap.o: $(UTILS_SRC)/resources.h
-xlyap.o: $(UTILS_SRC)/usleep.h
-xlyap.o: $(UTILS_SRC)/visual.h
-xlyap.o: $(UTILS_SRC)/yarandom.h
-xmatrix.o: ../config.h
-xmatrix.o: $(srcdir)/fps.h
-xmatrix.o: $(srcdir)/images/matrix1b.xbm
-xmatrix.o: $(srcdir)/images/matrix1b.xpm
-xmatrix.o: $(srcdir)/images/matrix1.xbm
-xmatrix.o: $(srcdir)/images/matrix1.xpm
-xmatrix.o: $(srcdir)/images/matrix2b.xbm
-xmatrix.o: $(srcdir)/images/matrix2b.xpm
-xmatrix.o: $(srcdir)/images/matrix2.xbm
-xmatrix.o: $(srcdir)/images/matrix2.xpm
-xmatrix.o: $(srcdir)/screenhackI.h
-xmatrix.o: $(srcdir)/screenhack.h
-xmatrix.o: $(UTILS_SRC)/colors.h
-xmatrix.o: $(UTILS_SRC)/grabscreen.h
-xmatrix.o: $(UTILS_SRC)/hsv.h
-xmatrix.o: $(UTILS_SRC)/resources.h
-xmatrix.o: $(UTILS_SRC)/usleep.h
-xmatrix.o: $(UTILS_SRC)/visual.h
-xmatrix.o: $(UTILS_SRC)/yarandom.h
-xmatrix.o: $(srcdir)/xpm-pixmap.h
-xpm-pixmap.o: ../config.h
-xpm-pixmap.o: $(UTILS_SRC)/visual.h
-xpm-pixmap.o: $(srcdir)/xpm-pixmap.h
-xrayswarm.o: ../config.h
-xrayswarm.o: $(srcdir)/fps.h
-xrayswarm.o: $(srcdir)/screenhackI.h
-xrayswarm.o: $(srcdir)/screenhack.h
-xrayswarm.o: $(UTILS_SRC)/colors.h
-xrayswarm.o: $(UTILS_SRC)/grabscreen.h
-xrayswarm.o: $(UTILS_SRC)/hsv.h
-xrayswarm.o: $(UTILS_SRC)/resources.h
-xrayswarm.o: $(UTILS_SRC)/usleep.h
-xrayswarm.o: $(UTILS_SRC)/visual.h
-xrayswarm.o: $(UTILS_SRC)/yarandom.h
-xscreensaver-sgigl.o: $(UTILS_SRC)/vroot.h
-xspirograph.o: ../config.h
-xspirograph.o: $(srcdir)/fps.h
-xspirograph.o: $(srcdir)/screenhackI.h
-xspirograph.o: $(srcdir)/screenhack.h
-xspirograph.o: $(UTILS_SRC)/colors.h
-xspirograph.o: $(UTILS_SRC)/erase.h
-xspirograph.o: $(UTILS_SRC)/grabscreen.h
-xspirograph.o: $(UTILS_SRC)/hsv.h
-xspirograph.o: $(UTILS_SRC)/resources.h
-xspirograph.o: $(UTILS_SRC)/usleep.h
-xspirograph.o: $(UTILS_SRC)/visual.h
-xspirograph.o: $(UTILS_SRC)/yarandom.h
-xsublim.o: $(UTILS_SRC)/resources.h
-xsublim.o: $(UTILS_SRC)/usleep.h
-xsublim.o: $(UTILS_SRC)/vroot.h
-xsublim.o: $(UTILS_SRC)/yarandom.h
-zoom.o: ../config.h
-zoom.o: $(srcdir)/fps.h
-zoom.o: $(srcdir)/screenhackI.h
-zoom.o: $(srcdir)/screenhack.h
-zoom.o: $(UTILS_SRC)/colors.h
-zoom.o: $(UTILS_SRC)/grabscreen.h
-zoom.o: $(UTILS_SRC)/hsv.h
-zoom.o: $(UTILS_SRC)/resources.h
-zoom.o: $(UTILS_SRC)/usleep.h
-zoom.o: $(UTILS_SRC)/visual.h
-zoom.o: $(UTILS_SRC)/yarandom.h
-
diff --git a/hacks/config/._klein.xml b/hacks/config/._klein.xml
new file mode 100644 (file)
index 0000000..1859a3c
Binary files /dev/null and b/hacks/config/._klein.xml differ
index 95c408a3f12bd8353f9d7acacc43ee06ac204ddd..1a131f87eecdcf0cf5a8037184821aa82fa43cc8 100644 (file)
@@ -4,8 +4,8 @@
             a screen saver and locker for the X window system
                             by Jamie Zawinski
 
-                              version 5.08
-                               27-Dec-2008
+                              version 5.09
+                               03-Sep-2009
 
                      http://www.jwz.org/xscreensaver/
 
index 74d7a1b1e35ebcecb67ac3599b00a22255fd6918..f601d8d496e166fa256e7941f240799e0e7e345a 100644 (file)
 
     <number id="spinspeed" type="slider" arg="-spinspeed %"
       _label="Spin" _low-label="Slow" _high-label="Fast"
-      low="0.5" high="4.0" default="1.0"/>  
+      low="0.01" high="4.0" default="1.0"/>
 
     <number id="wanderspeed" type="slider" arg="-wanderspeed %"
       _label="Wander" _low-label="Slow" _high-label="Fast"
-      low="0.3" high="3.0" default="1.0"/>  
+      low="0.001" high="0.1" default="0.02"/>
 
     <number id="wait" type="slider" arg="-wait %"
       _label="Linger" _low-label="Short" _high-label="Long"
@@ -63,8 +63,8 @@
 
   <_description>
 Animates a Rubik-like puzzle known as Cube 21 or Square-1.
-The rotations are chosen randomly.  See also the "Rubik" and
-"GLSnake" screen savers.
+The rotations are chosen randomly.  See also the "Rubik",
+"RubikBlocks" and "GLSnake" screen savers.
 
 http://en.wikipedia.org/wiki/Square_One_%28puzzle%29
 
index bb7cf26fed0c49cee5883e2b3d85c996a1813196..514739bc94194fef89a58ae8e7fcd4e1d0a50a09 100644 (file)
@@ -7,48 +7,44 @@
    <vgroup>
     <number id="delay" type="slider" arg="-delay %"
             _label="Frame rate" _low-label="Low" _high-label="High"
-            low="0" high="100000" default="20000"
+            low="0" high="100000" default="10000"
             convert="invert"/>
 
-    <number id="speed" type="slider" arg="-speed %" _label="Juggling speed"
-            _low-label="Slow" _high-label="Fast" low="0.5" high="5.0" default="2.2"/>
+    <number id="count" type="slider" arg="-count %"
+            _label="Speed" _low-label="Slow" _high-label="Fast"
+            low="50" high="1000" default="200"
+            convert="invert"/>
    </vgroup>
-
    <vgroup>
-    <number id="trans" type="slider" arg="-trans %" _label="Juggler horizontal speed"
-            _low-label="Slow" _high-label="Fast" low="0.05" high="2.0" default="0.1"/>
+    <number id="cycles" type="slider" arg="-cycles %"
+            _label="Performance length" _low-label="Short" _high-label="Long"
+            low="50" high="1000" default="1000"/>
 
-    <number id="spin" type="slider" arg="-spin %" _label="Juggler spin speed"
-            _low-label="Slow" _high-label="Fast" low="3.0" high="50.0" default="20.0"/>
+    <number id="tail" type="slider" arg="-tail %"
+            _label="Trail length" _low-label="None" _high-label="Long"
+            low="0" high="100" default="1"/>
    </vgroup>
   </hgroup>
 
   <hgroup>
-   <vgroup>
-    <number id="minobjs" type="spinbutton" arg="-minobjs %" _label="Min objects"
-      low="3" high="35" default="3"/>
+    <boolean id="balls" _label="Balls" arg-unset="-no-balls"/>
+    <boolean id="clubs" _label="Clubs" arg-unset="-no-clubs"/>
+    <boolean id="rings" _label="Rings" arg-unset="-no-rings"/>
+    <boolean id="knives" _label="Knives" arg-unset="-no-knives"/>
+<!--<boolean id="torches" _label="Flaming torches" arg-unset="-no-torches"/>-->
+    <boolean id="bballs" _label="Bowling balls" arg-unset="-no-bballs"/>
+  </hgroup>
 
-    <number id="maxobjs" type="spinbutton" arg="-maxobjs %" _label="Max objects"
-      low="3" high="35" default="8"/>            
-   </vgroup>
-   <vgroup>
-    <number id="minhinc" type="spinbutton" arg="-minhinc %" _label="Min height"
-      low="1" high="31" default="2"/>
+  <boolean id="describe" _label="Print Cambridge juggling pattern descriptions" arg-unset="-no-describe"/>
+  <string id="pattern" _label="Juggle this pattern" arg="-pattern %" />
 
-    <number id="maxhinc" type="spinbutton" arg="-maxhinc %" _label="Max height"
-      low="1" high="31" default="6"/>            
-   </vgroup>
-   <vgroup>
-    <boolean id="wire"   _label="Wireframe" arg-set="-wireframe"/>
-    <boolean id="showfps" _label="Show frame rate" arg-set="-fps"/>
-   </vgroup>
-  </hgroup>
+  <boolean id="showfps" _label="Show frame rate" arg-set="-fps"/>
 
   <_description>
-3D simulation of a juggler performing with balls, clubs and rings.  
+Draws a 3D juggling stick-man.
 
 http://en.wikipedia.org/wiki/Siteswap
 
-Written by Brian Apps; 2005.
+Written by Tim Auckland and Jamie Zawinski; 2002.
   </_description>
 </screensaver>
index 0cd83fa759519ce3247a1120b207ea4d7affd4cc..5f9ae718e47e865a146810441c0822654bd3fc5a 100644 (file)
 
   <command arg="-root"/>
 
+  <hgroup>
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
-          low="0" high="100000" default="20000"
+          low="0" high="100000" default="10000"
           convert="invert"/>
+  <boolean id="showfps" _label="Show frame rate" arg-set="-fps"/>
+  </hgroup>
 
-  <number id="descent" type="slider" arg="-speed %"
-          _label="Duration" _low-label="Short" _high-label="Long"
-          low="2" high="500" default="150"
-          convert="invert"/>
+  <hgroup>
+    <select id="kleinbottle">
+      <option id="random"   _label="Random"/>
+      <option id="figure-8" _label="Figure 8" arg-set="-klein-bottle figure-8"/>
+      <option id="lawson"   _label="Lawson"   arg-set="-klein-bottle lawson"/>
+    </select>
 
-  <boolean id="random" _label="Use randomized surfaces and primitives" arg-unset="-no-random"/>
-  <boolean id="wander"  _label="Wander" arg-set="-wander"/>
-  <boolean id="spin"    _label="Spin" arg-unset="-no-spin"/>
-  <boolean id="showfps" _label="Show frame rate" arg-set="-fps"/>
+    <select id="view-mode">
+      <option id="walk"      _label="Random"/>
+      <option id="walk"      _label="Walk"          arg-set="-view-mode walk"/>
+      <option id="turn"      _label="Turn"          arg-set="-view-mode turn"/>
+      <option id="walk-turn" _label="Walk and turn" arg-set="-view-mode walk-turn"/>
+    </select>
+
+    <boolean id="orientation-marks" _label="Show orientation marks"
+              arg-set="-orientation-marks"/>
+  </hgroup>
+
+  <hgroup>
+    <select id="display-mode">
+      <option id="random"      _label="Random"/>
+      <option id="wire"        _label="Wireframe mesh"      arg-set="-mode wireframe"/>
+      <option id="surface"     _label="Solid surface"       arg-set="-mode surface"/>
+      <option id="transparent" _label="Transparent surface" arg-set="-mode transparent"/>
+    </select>
+
+    <select id="appearance">
+      <option id="random" _label="Random"/>
+      <option id="solid"  _label="Solid object"       arg-set="-appearance solid"/>
+      <option id="bands"  _label="See-through bands"  arg-set="-appearance bands"/>
+    </select>
+  </hgroup>
+
+  <hgroup>
+    <select id="colors">
+      <option id="random"   _label="Random"/>
+      <option id="twosided" _label="Two-sided"       arg-set="-colors two-sided"/>
+      <option id="rainbow"  _label="Rainbow colors"  arg-set="-colors rainbow"/>
+      <option id="depth"    _label="4d depth colors" arg-set="-colors depth"/>
+    </select>
+
+    <select id="projection3d">
+      <option id="random"          _label="Random"/>
+      <option id="perspective-3d"  _label="Perspective 3D"  arg-set="-projection-3d perspective"/>
+      <option id="orthographic-3d" _label="Orthographic 3D" arg-set="-projection-3d orthographic"/>
+    </select>
+
+    <select id="projection4d">
+      <option id="random"          _label="Random"/>
+      <option id="perspective-4d"  _label="Perspective 4D"  arg-set="-projection-4d perspective"/>
+      <option id="orthographic-4d" _label="Orthographic 4D" arg-set="-projection-4d orthographic"/>
+    </select>
+  </hgroup>
+
+  <hgroup>
+    <vgroup>
+      <number id="speed-wx" type="slider" arg="-speed-wx %"
+              _label="WX rotation speed"
+              _low-label="-4.0" _high-label="4.0"
+              low="-4.0" high="4.0" default="1.1"/>
+
+      <number id="speed-wy" type="slider" arg="-speed-wy %"
+              _label="WY rotation speed"
+              _low-label="-4.0" _high-label="4.0"
+              low="-4.0" high="4.0" default="1.3"/>
+
+      <number id="speed-wz" type="slider" arg="-speed-wz %"
+              _label="WZ rotation speed"
+              _low-label="-4.0" _high-label="4.0"
+              low="-4.0" high="4.0" default="1.5"/>
+
+    <number id="walk-direction" type="slider" arg="-walk-direction %"
+            _label="Walking direction"
+            _low-label="-180.0" _high-label="180.0"
+            low="-180.0" high="180.0" default="7.0"/>
+    </vgroup>
+
+    <vgroup>
+      <number id="speed-xy" type="slider" arg="-speed-xy %"
+              _label="XY rotation speed"
+              _low-label="-4.0" _high-label="4.0"
+              low="-4.0" high="4.0" default="1.7"/>
+
+      <number id="speed-xz" type="slider" arg="-speed-xz %"
+              _label="XZ rotation speed"
+              _low-label="-4.0" _high-label="4.0"
+              low="-4.0" high="4.0" default="1.9"/>
+
+      <number id="speed-yz" type="slider" arg="-speed-yz %"
+              _label="YZ rotation speed"
+              _low-label="-4.0" _high-label="4.0"
+              low="-4.0" high="4.0" default="2.1"/>
+
+    <number id="walk-speed" type="slider" arg="-walk-speed %"
+            _label="Walking speed"
+            _low-label="1.0" _high-label="100.0"
+            low="1.0" high="100.0" default="20.0"/>
+    </vgroup>
+  </hgroup>
 
   <_description>
-This draws a visualization of a Klein bottle or some other interesting
-parametric surfaces.
+This shows a 4D Klein bottle.  You can walk on the Klein bottle or
+rotate it in 4D or walk on it while it rotates in 4D.  Inspired by
+Thomas Banchoff's book "Beyond the Third Dimension: Geometry, Computer
+Graphics, and Higher Dimensions", Scientific American Library, 1990.
 
 http://en.wikipedia.org/wiki/Klein_bottle
 
-Written by Andrey Mirtchovski; 2003.
+Written by Carsten Steger; 2008.
   </_description>
 </screensaver>
index 53e0e68f817ec5076ce5a4f7683f366f22bf7563..7ea18c7a1d399ff49de40cf34346af2264cabf2c 100644 (file)
@@ -43,9 +43,8 @@
   </hgroup>
 
   <_description>
-This draws rippling interference patterns like splashing water.
-With the -water option, it manipulates your desktop image to look
-like something is dripping into it.
+This draws rippling interference patterns like splashing water,
+overlayed on the desktop or an image.
 
 Written by Tom Hammersley; 1999.
   </_description>
diff --git a/hacks/config/rubikblocks.xml b/hacks/config/rubikblocks.xml
new file mode 100644 (file)
index 0000000..141acb7
--- /dev/null
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<screensaver name="rubikblocks" _label="RubikBlocks">
+
+  <command arg="-root"/>
+
+  <hgroup>
+   <vgroup>
+
+    <number id="speed" type="slider" arg="-delay %"
+      _label="Frame rate" _low-label="Low" _high-label="High"
+      low="0" high="100000" default="20000" convert="invert"/>
+
+    <number id="cubesize" type="slider" arg="-cubesize %"
+      _label="Cube size" _low-label="Small" _high-label="Large"
+      low="0.4" high="2.0" default="1.0"/>  
+
+    <number id="rotspeed" type="slider" arg="-rotspeed %"
+      _label="Rotation" _low-label="Slow" _high-label="Fast"
+      low="1.0" high="10.0" default="3.0"/>
+
+    <select id="start">
+     <option id="cube"    _label="Start as cube"/>
+     <option id="shuffle" _label="Start as random shape" arg-set="-randomize"/>
+    </select>
+
+   </vgroup>
+   <vgroup>
+
+    <number id="spinspeed" type="slider" arg="-spinspeed %"
+      _label="Spin" _low-label="Slow" _high-label="Fast"
+      low="0.01" high="4.0" default="0.1"/>
+
+    <number id="wanderspeed" type="slider" arg="-wanderspeed %"
+      _label="Wander" _low-label="Slow" _high-label="Fast"
+      low="0.001" high="0.1" default="0.005"/>
+
+    <number id="wait" type="slider" arg="-wait %"
+      _label="Linger" _low-label="Short" _high-label="Long"
+      low="10.0" high="100.0" default="40.0"/>
+
+    <hgroup>
+     <boolean id="spin"    _label="Spin"     arg-unset="-no-spin"/>
+     <boolean id="wander"  _label="Wander"   arg-unset="-no-wander"/>
+     <boolean id="tex"     _label="Outlines" arg-unset="-no-texture"/>
+    </hgroup>
+    <hgroup>
+     <boolean id="wire"    _label="Wireframe"      arg-set="-wireframe"/>
+     <boolean id="showfps" _label="Show frame rate" arg-set="-fps"/>
+    </hgroup>
+
+   </vgroup>
+  </hgroup>
+
+  <_description>
+Animates the Rubik's Mirror Blocks puzzle.
+See also the "Rubik", "Cube21", and "GLSnake" screen savers.
+
+http://en.wikipedia.org/wiki/Combination_puzzles#Irregular_Cuboids
+
+Written by Vasek Potocek; 2009.
+  </_description>
+</screensaver>
diff --git a/hacks/config/surfaces.xml b/hacks/config/surfaces.xml
new file mode 100644 (file)
index 0000000..f62385d
--- /dev/null
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<screensaver name="surfaces" _label="Surfaces">
+
+  <command arg="-root"/>
+
+  <number id="delay" type="slider" arg="-delay %"
+          _label="Frame rate" _low-label="Low" _high-label="High"
+          low="0" high="100000" default="20000"
+          convert="invert"/>
+
+  <number id="descent" type="slider" arg="-speed %"
+          _label="Duration" _low-label="Short" _high-label="Long"
+          low="2" high="2000" default="300"
+          convert="invert"/>
+
+  <hgroup>
+   <select id="surface">
+    <option id="random"    _label="Random Surface"/>
+    <option id="dini"      _label="Dini's Surface"      arg-set="-surface dini"/>
+    <option id="enneper"   _label="Enneper's Surface"   arg-set="-surface enneper"/>
+    <option id="kuen"      _label="Kuen Surface"        arg-set="-surface kuen"/>
+    <option id="moebius"   _label="Moebius Strip"       arg-set="-surface moebius"/>
+    <option id="seashell"  _label="Seashell"            arg-set="-surface seashell"/>
+    <option id="swallow"   _label="Swallowtail"         arg-set="-surface swallowtail"/>
+    <option id="bohemian"  _label="Bohemian Dome"       arg-set="-surface bohemian"/>
+    <option id="whitney"   _label="Whitney Umbrella"    arg-set="-surface whitney"/>
+    <option id="pluecker"  _label="Pluecker's Conoid"   arg-set="-surface pluecker"/>
+    <option id="henneberg" _label="Henneberg's Surface" arg-set="-surface henneberg"/>
+    <option id="catalan"   _label="Catalan's Surface"   arg-set="-surface catalan"/>
+    <option id="corkscrew" _label="Corkscrew Surface"   arg-set="-surface corkscrew"/>
+   </select>
+
+   <select id="mode">
+     <option id="random"    _label="Random Display Mode"/>
+     <option id="points"    _label="Points"     arg-set="-mode points"/>
+     <option id="lines"     _label="Lines"      arg-set="-mode lines"/>
+     <option id="line_loop" _label="Line Loops" arg-set="-mode line-loops"/>
+   </select>
+  </hgroup>
+
+  <hgroup>
+   <boolean id="wander"  _label="Wander" arg-set="-wander"/>
+   <boolean id="spin"    _label="Spin" arg-unset="-no-spin"/>
+   <boolean id="showfps" _label="Show frame rate" arg-set="-fps"/>
+  </hgroup>
+
+  <_description>
+This draws a visualization of several interesting parametric surfaces.
+
+http://mathworld.wolfram.com/DinisSurface.html
+http://en.wikipedia.org/wiki/Enneper_surface
+http://mathworld.wolfram.com/EnnepersMinimalSurface.html
+http://mathworld.wolfram.com/KuenSurface.html
+http://en.wikipedia.org/wiki/Moebius_strip
+http://mathworld.wolfram.com/Seashell.html
+http://mathworld.wolfram.com/SwallowtailCatastrophe.html
+http://mathworld.wolfram.com/BohemianDome.html
+http://en.wikipedia.org/wiki/Whitney_umbrella
+http://mathworld.wolfram.com/PlueckersConoid.html
+http://mathworld.wolfram.com/HennebergsMinimalSurface.html
+http://mathworld.wolfram.com/CatalansSurface.html
+http://mathworld.wolfram.com/CorkscrewSurface.html
+
+Written by Andrey Mirtchovski and Carsten Steger; 2003.
+  </_description>
+</screensaver>
index a1f2d7a13443a10b6a238bdccc12828031636800..032b3bd75e5def0e5fb0b3c738f7e30677b4232e 100644 (file)
@@ -1,6 +1,6 @@
 .TH XScreenSaver 1 "" "X Version 11"
 .SH NAME
-Eruption.
+Eruption \- eruption of pieces of hot volcanic rock
 .SH SYNOPSIS
 .B Eruption
 [\-display \fIhost:display.screen\fP]
index 2e1ba3f715a2f4125c5564c85ece9d2b4fc3a744..2aa0174377756afeaea6754ada674ff93a8b4a44 100644 (file)
@@ -219,7 +219,6 @@ fps_draw (fps_state *st)
   if (st->clear_p)
     {
       int w, h;
-      int lh = st->font->ascent + st->font->descent;
       w = string_width (st->font, string, &h);
       XFillRectangle (st->dpy, st->window, st->erase_gc,
                       x - st->font->descent,
diff --git a/hacks/glx/._grab-ximage.c b/hacks/glx/._grab-ximage.c
new file mode 100644 (file)
index 0000000..b83172e
Binary files /dev/null and b/hacks/glx/._grab-ximage.c differ
diff --git a/hacks/glx/._rubikblocks.man b/hacks/glx/._rubikblocks.man
new file mode 100644 (file)
index 0000000..7061479
Binary files /dev/null and b/hacks/glx/._rubikblocks.man differ
index 3ea3bdc1e0a21e21fdce53ea0f624e68b904da82..23dde73b467fe7416bd9d3be3731290af53c8a53 100644 (file)
@@ -109,7 +109,7 @@ SRCS                = xscreensaver-gl-helper.c normals.c glxfonts.c fps-gl.c \
                  glschool_gl.c glschool_alg.c glcells.c voronoi.c \
                  moebiusgears.c lockward.c cubicgrid.c hypnowheel.c \
                  skytentacles.c teapot.c sonar.c sonar-sim.c sonar-icmp.c \
-                 jigsaw.c photopile.c
+                 jigsaw.c photopile.c rubikblocks.c surfaces.c
 
 OBJS           = xscreensaver-gl-helper.o normals.o glxfonts.o fps-gl.o \
                  atlantis.o b_draw.o b_lockglue.o b_sphere.o bubble3d.o \
@@ -145,7 +145,7 @@ OBJS                = xscreensaver-gl-helper.o normals.o glxfonts.o fps-gl.o \
                  glschool_gl.o glschool_alg.o glcells.o voronoi.o \
                  moebiusgears.o lockward.o cubicgrid.o hypnowheel.o \
                  skytentacles.o teapot.o sonar.o sonar-sim.o sonar-icmp.o \
-                 jigsaw.o photopile.o
+                 jigsaw.o photopile.o rubikblocks.o surfaces.o
 
 GL_EXES                = cage gears moebius pipes sproingies stairs superquadrics \
                  morph3d rubik atlantis lament bubble3d glplanet pulsar \
@@ -159,7 +159,8 @@ GL_EXES             = cage gears moebius pipes sproingies stairs superquadrics \
                  antinspect providence pinion boing carousel fliptext \
                  antmaze tangram crackberg glhanoi cube21 timetunnel \
                  juggler3d topblock glschool glcells voronoi moebiusgears \
-                 lockward cubicgrid hypnowheel skytentacles jigsaw photopile
+                 lockward cubicgrid hypnowheel skytentacles jigsaw photopile \
+                 rubikblocks surfaces
 GLE_EXES       = extrusion
 SUID_EXES      = sonar
 GL_UTIL_EXES   = xscreensaver-gl-helper
@@ -169,8 +170,8 @@ XSHM_OBJS   = $(UTILS_BIN)/xshm.o
 GRAB_OBJS      = $(UTILS_BIN)/grabclient.o grab-ximage.o $(XSHM_OBJS)
 EXES           = @GL_UTIL_EXES@ $(HACK_EXES)
 
-RETIRED_EXES   = glforestfire
-RETIRED_GL_EXES        = @RETIRED_GL_EXES@
+RETIRED_EXES   = @RETIRED_GL_EXES@
+RETIRED_GL_EXES        = glforestfire
 
 HACK_OBJS      = $(HACK_BIN)/screenhack.o $(HACK_BIN)/fps.o \
                  xlockmore-gl.o xlock-gl-utils.o glxfonts.o fps-gl.o \
@@ -208,7 +209,7 @@ GL_MEN              = atlantis.man boxed.man bubble3d.man cage.man circuit.man \
                  juggler3d.man topblock.man glschool.man glcells.man \
                  voronoi.man moebiusgears.man lockward.man cubicgrid.man \
                  hypnowheel.man skytentacles.man sonar.man jigsaw.man \
-                 photopile.man
+                 photopile.man rubikblocks.man surfaces.man
 MEN            = @GL_MEN@
 RETIRED_MEN    = glforestfire.man
 EXTRAS         = README Makefile.in dxf2gl.pl molecules.sh starwars.txt
@@ -327,7 +328,7 @@ install-xml:
 
 # the hacks, in $HACKDIR
 uninstall-program::
-       @exes="$(HACK_EXES)" ;                                          \
+       @exes="$(HACK_EXES) $(RETIRED_EXES)" ;                          \
         idir="$(install_prefix)$(HACKDIR)" ;                           \
         for program in $$exes; do                                      \
           echo rm -f $$idir/$$program ;                                \
@@ -344,7 +345,7 @@ uninstall-program::
        done
 
 uninstall-man:
-       @men="$(MEN)" ;                                                 \
+       @men="$(MEN) $(RETIRED_MEN)" ;                                  \
        for man in $$men; do                                            \
          instname=`echo $$man | sed 's/\.man$$/\.$(mansuffix)/'` ;     \
          echo rm -f $(install_prefix)$(manNdir)/$$instname* ;          \
@@ -353,13 +354,13 @@ uninstall-man:
 
 uninstall-xml:
        @dest=$(install_prefix)$(HACK_CONF_DIR) ;                       \
-        for file in $(EXES) $(SCRIPTS) ; do                            \
+        for file in $(EXES) $(RETIRED_EXES) $(SCRIPTS) ; do            \
             echo rm -f $$dest/$$file.xml ;                             \
                  rm -f $$dest/$$file.xml ;                             \
        done
 
 clean:
-       -rm -f *.o a.out core $(EXES) molecules.h
+       -rm -f *.o a.out core $(EXES) $(RETIRED_EXES) molecules.h
 
 distclean: clean
        -rm -f Makefile TAGS *~ "#"*
@@ -631,6 +632,9 @@ jigglypuff: jigglypuff.o    xpm-ximage.o $(HACK_TRACK_OBJS)
 klein:         klein.o         $(HACK_TRACK_OBJS)
        $(CC_HACK) -o $@ $@.o   $(HACK_TRACK_OBJS) $(HACK_LIBS)
 
+surfaces:      surfaces.o      $(HACK_TRACK_OBJS)
+       $(CC_HACK) -o $@ $@.o   $(HACK_TRACK_OBJS) $(HACK_LIBS)
+
 hypertorus:    hypertorus.o    $(HACK_TRACK_OBJS)
        $(CC_HACK) -o $@ $@.o   $(HACK_TRACK_OBJS) $(HACK_LIBS)
 
@@ -726,8 +730,9 @@ TIMETUNNEL_OBJS = xpm-ximage.o  $(HACK_TRACK_OBJS)
 timetunnel:    timetunnel.o    $(TIMETUNNEL_OBJS)
        $(CC_HACK) -o $@ $@.o   $(TIMETUNNEL_OBJS) $(XPM_LIBS)
 
-juggler3d:     juggler3d.o     $(HACK_TRACK_OBJS)
-       $(CC_HACK) -o $@ $@.o   $(HACK_TRACK_OBJS) $(HACK_LIBS)
+JUGG_OBJS=sphere.o tube.o $(HACK_TRACK_OBJS)
+juggler3d:     juggler3d.o     $(JUGG_OBJS)
+       $(CC_HACK) -o $@ $@.o   $(JUGG_OBJS) $(HACK_LIBS)
 
 dnalogo:       dnalogo.o      tube.o normals.o $(HACK_TRACK_OBJS)
        $(CC_HACK) -o $@ $@.o  tube.o normals.o $(HACK_TRACK_OBJS) $(HACK_LIBS)
@@ -769,1585 +774,10 @@ jigsaw:         jigsaw.o        $(JIGSAW_OBJS)
 photopile:     photopile.o     texfont.o $(HACK_GRAB_OBJS)
        $(CC_HACK) -o $@ $@.o   texfont.o $(HACK_GRAB_OBJS) $(HACK_LIBS)
 
+rubikblocks:   rubikblocks.o   $(HACK_TRACK_OBJS)
+       $(CC_HACK) -o $@ $@.o   $(HACK_TRACK_OBJS) $(HACK_LIBS)
+
 ##############################################################################
 #
 # DO NOT DELETE: updated by make distdepend
 
-antinspect.o: ../../config.h
-antinspect.o: $(HACK_SRC)/fps.h
-antinspect.o: $(srcdir)/gltrackball.h
-antinspect.o: $(HACK_SRC)/screenhackI.h
-antinspect.o: $(UTILS_SRC)/colors.h
-antinspect.o: $(UTILS_SRC)/grabscreen.h
-antinspect.o: $(UTILS_SRC)/hsv.h
-antinspect.o: $(UTILS_SRC)/resources.h
-antinspect.o: $(UTILS_SRC)/usleep.h
-antinspect.o: $(UTILS_SRC)/visual.h
-antinspect.o: $(UTILS_SRC)/xshm.h
-antinspect.o: $(UTILS_SRC)/yarandom.h
-antinspect.o: $(HACK_SRC)/xlockmoreI.h
-antinspect.o: $(HACK_SRC)/xlockmore.h
-antmaze.o: $(srcdir)/ants.h
-antmaze.o: ../../config.h
-antmaze.o: $(HACK_SRC)/fps.h
-antmaze.o: $(srcdir)/gltrackball.h
-antmaze.o: $(srcdir)/rotator.h
-antmaze.o: $(HACK_SRC)/screenhackI.h
-antmaze.o: $(UTILS_SRC)/colors.h
-antmaze.o: $(UTILS_SRC)/grabscreen.h
-antmaze.o: $(UTILS_SRC)/hsv.h
-antmaze.o: $(UTILS_SRC)/resources.h
-antmaze.o: $(UTILS_SRC)/usleep.h
-antmaze.o: $(UTILS_SRC)/visual.h
-antmaze.o: $(UTILS_SRC)/xshm.h
-antmaze.o: $(UTILS_SRC)/yarandom.h
-antmaze.o: $(HACK_SRC)/xlockmoreI.h
-antmaze.o: $(HACK_SRC)/xlockmore.h
-antspotlight.o: $(srcdir)/ants.h
-antspotlight.o: ../../config.h
-antspotlight.o: $(HACK_SRC)/fps.h
-antspotlight.o: $(srcdir)/gltrackball.h
-antspotlight.o: $(srcdir)/grab-ximage.h
-antspotlight.o: $(srcdir)/rotator.h
-antspotlight.o: $(HACK_SRC)/screenhackI.h
-antspotlight.o: $(UTILS_SRC)/colors.h
-antspotlight.o: $(UTILS_SRC)/grabscreen.h
-antspotlight.o: $(UTILS_SRC)/hsv.h
-antspotlight.o: $(UTILS_SRC)/resources.h
-antspotlight.o: $(UTILS_SRC)/usleep.h
-antspotlight.o: $(UTILS_SRC)/visual.h
-antspotlight.o: $(UTILS_SRC)/xshm.h
-antspotlight.o: $(UTILS_SRC)/yarandom.h
-antspotlight.o: $(HACK_SRC)/xlockmoreI.h
-antspotlight.o: $(HACK_SRC)/xlockmore.h
-atlantis.o: $(srcdir)/atlantis.h
-atlantis.o: ../../config.h
-atlantis.o: $(HACK_SRC)/fps.h
-atlantis.o: $(HACK_SRC)/images/sea-texture.xpm
-atlantis.o: $(HACK_SRC)/screenhackI.h
-atlantis.o: $(UTILS_SRC)/colors.h
-atlantis.o: $(UTILS_SRC)/grabscreen.h
-atlantis.o: $(UTILS_SRC)/hsv.h
-atlantis.o: $(UTILS_SRC)/resources.h
-atlantis.o: $(UTILS_SRC)/usleep.h
-atlantis.o: $(UTILS_SRC)/visual.h
-atlantis.o: $(UTILS_SRC)/xshm.h
-atlantis.o: $(UTILS_SRC)/yarandom.h
-atlantis.o: $(HACK_SRC)/xlockmoreI.h
-atlantis.o: $(HACK_SRC)/xlockmore.h
-atlantis.o: $(srcdir)/xpm-ximage.h
-atunnel.o: ../../config.h
-atunnel.o: $(HACK_SRC)/fps.h
-atunnel.o: $(HACK_SRC)/images/tunnel0.xpm
-atunnel.o: $(HACK_SRC)/images/tunnel1.xpm
-atunnel.o: $(HACK_SRC)/images/tunnel2.xpm
-atunnel.o: $(HACK_SRC)/images/tunnel3.xpm
-atunnel.o: $(HACK_SRC)/images/tunnel4.xpm
-atunnel.o: $(HACK_SRC)/images/tunnel5.xpm
-atunnel.o: $(HACK_SRC)/screenhackI.h
-atunnel.o: $(srcdir)/tunnel_draw.h
-atunnel.o: $(UTILS_SRC)/colors.h
-atunnel.o: $(UTILS_SRC)/grabscreen.h
-atunnel.o: $(UTILS_SRC)/hsv.h
-atunnel.o: $(UTILS_SRC)/resources.h
-atunnel.o: $(UTILS_SRC)/usleep.h
-atunnel.o: $(UTILS_SRC)/visual.h
-atunnel.o: $(UTILS_SRC)/xshm.h
-atunnel.o: $(UTILS_SRC)/yarandom.h
-atunnel.o: $(HACK_SRC)/xlockmoreI.h
-atunnel.o: $(HACK_SRC)/xlockmore.h
-atunnel.o: $(srcdir)/xpm-ximage.h
-b_draw.o: $(srcdir)/bubble3d.h
-b_draw.o: ../../config.h
-b_draw.o: $(HACK_SRC)/fps.h
-b_draw.o: $(HACK_SRC)/screenhackI.h
-b_draw.o: $(UTILS_SRC)/colors.h
-b_draw.o: $(UTILS_SRC)/grabscreen.h
-b_draw.o: $(UTILS_SRC)/hsv.h
-b_draw.o: $(UTILS_SRC)/resources.h
-b_draw.o: $(UTILS_SRC)/usleep.h
-b_draw.o: $(UTILS_SRC)/visual.h
-b_draw.o: $(UTILS_SRC)/xshm.h
-b_draw.o: $(UTILS_SRC)/yarandom.h
-b_draw.o: $(HACK_SRC)/xlockmoreI.h
-blinkbox.o: ../../config.h
-blinkbox.o: $(HACK_SRC)/fps.h
-blinkbox.o: $(HACK_SRC)/screenhackI.h
-blinkbox.o: $(srcdir)/sphere.h
-blinkbox.o: $(UTILS_SRC)/colors.h
-blinkbox.o: $(UTILS_SRC)/grabscreen.h
-blinkbox.o: $(UTILS_SRC)/hsv.h
-blinkbox.o: $(UTILS_SRC)/resources.h
-blinkbox.o: $(UTILS_SRC)/usleep.h
-blinkbox.o: $(UTILS_SRC)/visual.h
-blinkbox.o: $(UTILS_SRC)/xshm.h
-blinkbox.o: $(UTILS_SRC)/yarandom.h
-blinkbox.o: $(HACK_SRC)/xlockmoreI.h
-blinkbox.o: $(HACK_SRC)/xlockmore.h
-b_lockglue.o: $(srcdir)/bubble3d.h
-b_lockglue.o: ../../config.h
-b_lockglue.o: $(HACK_SRC)/fps.h
-b_lockglue.o: $(HACK_SRC)/screenhackI.h
-b_lockglue.o: $(UTILS_SRC)/colors.h
-b_lockglue.o: $(UTILS_SRC)/grabscreen.h
-b_lockglue.o: $(UTILS_SRC)/hsv.h
-b_lockglue.o: $(UTILS_SRC)/resources.h
-b_lockglue.o: $(UTILS_SRC)/usleep.h
-b_lockglue.o: $(UTILS_SRC)/visual.h
-b_lockglue.o: $(UTILS_SRC)/xshm.h
-b_lockglue.o: $(UTILS_SRC)/yarandom.h
-b_lockglue.o: $(HACK_SRC)/xlockmoreI.h
-b_lockglue.o: $(HACK_SRC)/xlockmore.h
-blocktube.o: ../../config.h
-blocktube.o: $(HACK_SRC)/fps.h
-blocktube.o: $(HACK_SRC)/images/blocktube.xpm
-blocktube.o: $(HACK_SRC)/screenhackI.h
-blocktube.o: $(UTILS_SRC)/colors.h
-blocktube.o: $(UTILS_SRC)/grabscreen.h
-blocktube.o: $(UTILS_SRC)/hsv.h
-blocktube.o: $(UTILS_SRC)/resources.h
-blocktube.o: $(UTILS_SRC)/usleep.h
-blocktube.o: $(UTILS_SRC)/visual.h
-blocktube.o: $(UTILS_SRC)/xshm.h
-blocktube.o: $(UTILS_SRC)/yarandom.h
-blocktube.o: $(HACK_SRC)/xlockmoreI.h
-blocktube.o: $(HACK_SRC)/xlockmore.h
-blocktube.o: $(srcdir)/xpm-ximage.h
-boing.o: ../../config.h
-boing.o: $(HACK_SRC)/fps.h
-boing.o: $(srcdir)/gltrackball.h
-boing.o: $(HACK_SRC)/screenhackI.h
-boing.o: $(UTILS_SRC)/colors.h
-boing.o: $(UTILS_SRC)/grabscreen.h
-boing.o: $(UTILS_SRC)/hsv.h
-boing.o: $(UTILS_SRC)/resources.h
-boing.o: $(UTILS_SRC)/usleep.h
-boing.o: $(UTILS_SRC)/visual.h
-boing.o: $(UTILS_SRC)/xshm.h
-boing.o: $(UTILS_SRC)/yarandom.h
-boing.o: $(HACK_SRC)/xlockmoreI.h
-boing.o: $(HACK_SRC)/xlockmore.h
-bouncingcow.o: ../../config.h
-bouncingcow.o: $(HACK_SRC)/fps.h
-bouncingcow.o: $(srcdir)/gllist.h
-bouncingcow.o: $(srcdir)/gltrackball.h
-bouncingcow.o: $(srcdir)/rotator.h
-bouncingcow.o: $(HACK_SRC)/screenhackI.h
-bouncingcow.o: $(UTILS_SRC)/colors.h
-bouncingcow.o: $(UTILS_SRC)/grabscreen.h
-bouncingcow.o: $(UTILS_SRC)/hsv.h
-bouncingcow.o: $(UTILS_SRC)/resources.h
-bouncingcow.o: $(UTILS_SRC)/usleep.h
-bouncingcow.o: $(UTILS_SRC)/visual.h
-bouncingcow.o: $(UTILS_SRC)/xshm.h
-bouncingcow.o: $(UTILS_SRC)/yarandom.h
-bouncingcow.o: $(HACK_SRC)/xlockmoreI.h
-bouncingcow.o: $(HACK_SRC)/xlockmore.h
-bouncingcow.o: $(srcdir)/xpm-ximage.h
-boxed.o: $(srcdir)/boxed.h
-boxed.o: ../../config.h
-boxed.o: $(HACK_SRC)/fps.h
-boxed.o: $(HACK_SRC)/screenhackI.h
-boxed.o: $(UTILS_SRC)/colors.h
-boxed.o: $(UTILS_SRC)/grabscreen.h
-boxed.o: $(UTILS_SRC)/hsv.h
-boxed.o: $(UTILS_SRC)/resources.h
-boxed.o: $(UTILS_SRC)/usleep.h
-boxed.o: $(UTILS_SRC)/visual.h
-boxed.o: $(UTILS_SRC)/xshm.h
-boxed.o: $(UTILS_SRC)/yarandom.h
-boxed.o: $(HACK_SRC)/xlockmoreI.h
-boxed.o: $(HACK_SRC)/xlockmore.h
-b_sphere.o: $(srcdir)/bubble3d.h
-b_sphere.o: ../../config.h
-b_sphere.o: $(HACK_SRC)/fps.h
-b_sphere.o: $(HACK_SRC)/screenhackI.h
-b_sphere.o: $(UTILS_SRC)/colors.h
-b_sphere.o: $(UTILS_SRC)/grabscreen.h
-b_sphere.o: $(UTILS_SRC)/hsv.h
-b_sphere.o: $(UTILS_SRC)/resources.h
-b_sphere.o: $(UTILS_SRC)/usleep.h
-b_sphere.o: $(UTILS_SRC)/visual.h
-b_sphere.o: $(UTILS_SRC)/xshm.h
-b_sphere.o: $(UTILS_SRC)/yarandom.h
-b_sphere.o: $(HACK_SRC)/xlockmoreI.h
-bubble3d.o: $(srcdir)/bubble3d.h
-bubble3d.o: ../../config.h
-bubble3d.o: $(HACK_SRC)/fps.h
-bubble3d.o: $(HACK_SRC)/screenhackI.h
-bubble3d.o: $(UTILS_SRC)/colors.h
-bubble3d.o: $(UTILS_SRC)/grabscreen.h
-bubble3d.o: $(UTILS_SRC)/hsv.h
-bubble3d.o: $(UTILS_SRC)/resources.h
-bubble3d.o: $(UTILS_SRC)/usleep.h
-bubble3d.o: $(UTILS_SRC)/visual.h
-bubble3d.o: $(UTILS_SRC)/xshm.h
-bubble3d.o: $(UTILS_SRC)/yarandom.h
-bubble3d.o: $(HACK_SRC)/xlockmoreI.h
-buildlwo.o: $(srcdir)/buildlwo.h
-cage.o: ../../config.h
-cage.o: $(srcdir)/e_textures.h
-cage.o: $(HACK_SRC)/fps.h
-cage.o: $(HACK_SRC)/screenhackI.h
-cage.o: $(UTILS_SRC)/colors.h
-cage.o: $(UTILS_SRC)/grabscreen.h
-cage.o: $(UTILS_SRC)/hsv.h
-cage.o: $(UTILS_SRC)/resources.h
-cage.o: $(UTILS_SRC)/usleep.h
-cage.o: $(UTILS_SRC)/visual.h
-cage.o: $(UTILS_SRC)/xshm.h
-cage.o: $(UTILS_SRC)/yarandom.h
-cage.o: $(HACK_SRC)/xlockmoreI.h
-cage.o: $(HACK_SRC)/xlockmore.h
-carousel.o: ../../config.h
-carousel.o: $(HACK_SRC)/fps.h
-carousel.o: $(srcdir)/gltrackball.h
-carousel.o: $(srcdir)/grab-ximage.h
-carousel.o: $(srcdir)/rotator.h
-carousel.o: $(HACK_SRC)/screenhackI.h
-carousel.o: $(srcdir)/texfont.h
-carousel.o: $(UTILS_SRC)/colors.h
-carousel.o: $(UTILS_SRC)/grabscreen.h
-carousel.o: $(UTILS_SRC)/hsv.h
-carousel.o: $(UTILS_SRC)/resources.h
-carousel.o: $(UTILS_SRC)/usleep.h
-carousel.o: $(UTILS_SRC)/visual.h
-carousel.o: $(UTILS_SRC)/xshm.h
-carousel.o: $(UTILS_SRC)/yarandom.h
-carousel.o: $(HACK_SRC)/xlockmoreI.h
-carousel.o: $(HACK_SRC)/xlockmore.h
-chessmodels.o: $(srcdir)/chessmodels.h
-circuit.o: ../../config.h
-circuit.o: $(srcdir)/font-ximage.h
-circuit.o: $(HACK_SRC)/fps.h
-circuit.o: $(HACK_SRC)/screenhackI.h
-circuit.o: $(UTILS_SRC)/colors.h
-circuit.o: $(UTILS_SRC)/grabscreen.h
-circuit.o: $(UTILS_SRC)/hsv.h
-circuit.o: $(UTILS_SRC)/resources.h
-circuit.o: $(UTILS_SRC)/usleep.h
-circuit.o: $(UTILS_SRC)/visual.h
-circuit.o: $(UTILS_SRC)/xshm.h
-circuit.o: $(UTILS_SRC)/yarandom.h
-circuit.o: $(HACK_SRC)/xlockmoreI.h
-circuit.o: $(HACK_SRC)/xlockmore.h
-cow_face.o: $(srcdir)/gllist.h
-cow_hide.o: $(srcdir)/gllist.h
-cow_hoofs.o: $(srcdir)/gllist.h
-cow_horns.o: $(srcdir)/gllist.h
-cow_tail.o: $(srcdir)/gllist.h
-cow_udder.o: $(srcdir)/gllist.h
-crackberg.o: ../../config.h
-crackberg.o: $(HACK_SRC)/fps.h
-crackberg.o: $(HACK_SRC)/screenhackI.h
-crackberg.o: $(UTILS_SRC)/colors.h
-crackberg.o: $(UTILS_SRC)/grabscreen.h
-crackberg.o: $(UTILS_SRC)/hsv.h
-crackberg.o: $(UTILS_SRC)/resources.h
-crackberg.o: $(UTILS_SRC)/usleep.h
-crackberg.o: $(UTILS_SRC)/visual.h
-crackberg.o: $(UTILS_SRC)/xshm.h
-crackberg.o: $(UTILS_SRC)/yarandom.h
-crackberg.o: $(HACK_SRC)/xlockmoreI.h
-crackberg.o: $(HACK_SRC)/xlockmore.h
-cube21.o: ../../config.h
-cube21.o: $(HACK_SRC)/fps.h
-cube21.o: $(HACK_SRC)/screenhackI.h
-cube21.o: $(UTILS_SRC)/colors.h
-cube21.o: $(UTILS_SRC)/grabscreen.h
-cube21.o: $(UTILS_SRC)/hsv.h
-cube21.o: $(UTILS_SRC)/resources.h
-cube21.o: $(UTILS_SRC)/usleep.h
-cube21.o: $(UTILS_SRC)/visual.h
-cube21.o: $(UTILS_SRC)/xshm.h
-cube21.o: $(UTILS_SRC)/yarandom.h
-cube21.o: $(HACK_SRC)/xlockmoreI.h
-cube21.o: $(HACK_SRC)/xlockmore.h
-cubenetic.o: ../../config.h
-cubenetic.o: $(HACK_SRC)/fps.h
-cubenetic.o: $(srcdir)/gltrackball.h
-cubenetic.o: $(srcdir)/rotator.h
-cubenetic.o: $(HACK_SRC)/screenhackI.h
-cubenetic.o: $(UTILS_SRC)/colors.h
-cubenetic.o: $(UTILS_SRC)/grabscreen.h
-cubenetic.o: $(UTILS_SRC)/hsv.h
-cubenetic.o: $(UTILS_SRC)/resources.h
-cubenetic.o: $(UTILS_SRC)/usleep.h
-cubenetic.o: $(UTILS_SRC)/visual.h
-cubenetic.o: $(UTILS_SRC)/xshm.h
-cubenetic.o: $(UTILS_SRC)/yarandom.h
-cubenetic.o: $(HACK_SRC)/xlockmoreI.h
-cubenetic.o: $(HACK_SRC)/xlockmore.h
-cubestorm.o: ../../config.h
-cubestorm.o: $(HACK_SRC)/fps.h
-cubestorm.o: $(srcdir)/gltrackball.h
-cubestorm.o: $(srcdir)/rotator.h
-cubestorm.o: $(HACK_SRC)/screenhackI.h
-cubestorm.o: $(UTILS_SRC)/colors.h
-cubestorm.o: $(UTILS_SRC)/grabscreen.h
-cubestorm.o: $(UTILS_SRC)/hsv.h
-cubestorm.o: $(UTILS_SRC)/resources.h
-cubestorm.o: $(UTILS_SRC)/usleep.h
-cubestorm.o: $(UTILS_SRC)/visual.h
-cubestorm.o: $(UTILS_SRC)/xshm.h
-cubestorm.o: $(UTILS_SRC)/yarandom.h
-cubestorm.o: $(HACK_SRC)/xlockmoreI.h
-cubestorm.o: $(HACK_SRC)/xlockmore.h
-cubicgrid.o: ../../config.h
-cubicgrid.o: $(HACK_SRC)/fps.h
-cubicgrid.o: $(srcdir)/gltrackball.h
-cubicgrid.o: $(srcdir)/rotator.h
-cubicgrid.o: $(HACK_SRC)/screenhackI.h
-cubicgrid.o: $(UTILS_SRC)/colors.h
-cubicgrid.o: $(UTILS_SRC)/grabscreen.h
-cubicgrid.o: $(UTILS_SRC)/hsv.h
-cubicgrid.o: $(UTILS_SRC)/resources.h
-cubicgrid.o: $(UTILS_SRC)/usleep.h
-cubicgrid.o: $(UTILS_SRC)/visual.h
-cubicgrid.o: $(UTILS_SRC)/xshm.h
-cubicgrid.o: $(UTILS_SRC)/yarandom.h
-cubicgrid.o: $(HACK_SRC)/xlockmoreI.h
-cubicgrid.o: $(HACK_SRC)/xlockmore.h
-dangerball.o: ../../config.h
-dangerball.o: $(HACK_SRC)/fps.h
-dangerball.o: $(srcdir)/gltrackball.h
-dangerball.o: $(srcdir)/rotator.h
-dangerball.o: $(HACK_SRC)/screenhackI.h
-dangerball.o: $(srcdir)/sphere.h
-dangerball.o: $(srcdir)/tube.h
-dangerball.o: $(UTILS_SRC)/colors.h
-dangerball.o: $(UTILS_SRC)/grabscreen.h
-dangerball.o: $(UTILS_SRC)/hsv.h
-dangerball.o: $(UTILS_SRC)/resources.h
-dangerball.o: $(UTILS_SRC)/usleep.h
-dangerball.o: $(UTILS_SRC)/visual.h
-dangerball.o: $(UTILS_SRC)/xshm.h
-dangerball.o: $(UTILS_SRC)/yarandom.h
-dangerball.o: $(HACK_SRC)/xlockmoreI.h
-dangerball.o: $(HACK_SRC)/xlockmore.h
-dnalogo.o: ../../config.h
-dnalogo.o: $(HACK_SRC)/fps.h
-dnalogo.o: $(srcdir)/gltrackball.h
-dnalogo.o: $(srcdir)/normals.h
-dnalogo.o: $(srcdir)/rotator.h
-dnalogo.o: $(HACK_SRC)/screenhackI.h
-dnalogo.o: $(srcdir)/tube.h
-dnalogo.o: $(UTILS_SRC)/colors.h
-dnalogo.o: $(UTILS_SRC)/grabscreen.h
-dnalogo.o: $(UTILS_SRC)/hsv.h
-dnalogo.o: $(UTILS_SRC)/resources.h
-dnalogo.o: $(UTILS_SRC)/usleep.h
-dnalogo.o: $(UTILS_SRC)/visual.h
-dnalogo.o: $(UTILS_SRC)/xshm.h
-dnalogo.o: $(UTILS_SRC)/yarandom.h
-dnalogo.o: $(HACK_SRC)/xlockmoreI.h
-dnalogo.o: $(HACK_SRC)/xlockmore.h
-dolphin.o: $(srcdir)/atlantis.h
-dolphin.o: ../../config.h
-dolphin.o: $(HACK_SRC)/fps.h
-dolphin.o: $(HACK_SRC)/screenhackI.h
-dolphin.o: $(UTILS_SRC)/colors.h
-dolphin.o: $(UTILS_SRC)/grabscreen.h
-dolphin.o: $(UTILS_SRC)/hsv.h
-dolphin.o: $(UTILS_SRC)/resources.h
-dolphin.o: $(UTILS_SRC)/usleep.h
-dolphin.o: $(UTILS_SRC)/visual.h
-dolphin.o: $(UTILS_SRC)/yarandom.h
-endgame.o: $(srcdir)/chessgames.h
-endgame.o: $(srcdir)/chessmodels.h
-endgame.o: ../../config.h
-endgame.o: $(HACK_SRC)/fps.h
-endgame.o: $(srcdir)/gltrackball.h
-endgame.o: $(HACK_SRC)/screenhackI.h
-endgame.o: $(UTILS_SRC)/colors.h
-endgame.o: $(UTILS_SRC)/grabscreen.h
-endgame.o: $(UTILS_SRC)/hsv.h
-endgame.o: $(UTILS_SRC)/resources.h
-endgame.o: $(UTILS_SRC)/usleep.h
-endgame.o: $(UTILS_SRC)/visual.h
-endgame.o: $(UTILS_SRC)/xshm.h
-endgame.o: $(UTILS_SRC)/yarandom.h
-endgame.o: $(HACK_SRC)/xlockmoreI.h
-endgame.o: $(HACK_SRC)/xlockmore.h
-engine.o: ../../config.h
-engine.o: $(HACK_SRC)/fps.h
-engine.o: $(srcdir)/gltrackball.h
-engine.o: $(srcdir)/glxfonts.h
-engine.o: $(srcdir)/rotator.h
-engine.o: $(HACK_SRC)/screenhackI.h
-engine.o: $(UTILS_SRC)/colors.h
-engine.o: $(UTILS_SRC)/grabscreen.h
-engine.o: $(UTILS_SRC)/hsv.h
-engine.o: $(UTILS_SRC)/resources.h
-engine.o: $(UTILS_SRC)/usleep.h
-engine.o: $(UTILS_SRC)/visual.h
-engine.o: $(UTILS_SRC)/xshm.h
-engine.o: $(UTILS_SRC)/yarandom.h
-engine.o: $(HACK_SRC)/xlockmoreI.h
-engine.o: $(HACK_SRC)/xlockmore.h
-extrusion-helix2.o: ../../config.h
-extrusion-helix2.o: $(srcdir)/extrusion.h
-extrusion-helix3.o: ../../config.h
-extrusion-helix3.o: $(srcdir)/extrusion.h
-extrusion-helix4.o: ../../config.h
-extrusion-helix4.o: $(srcdir)/extrusion.h
-extrusion-joinoffset.o: ../../config.h
-extrusion-joinoffset.o: $(srcdir)/extrusion.h
-extrusion.o: ../../config.h
-extrusion.o: $(srcdir)/extrusion.h
-extrusion.o: $(HACK_SRC)/fps.h
-extrusion.o: $(srcdir)/gltrackball.h
-extrusion.o: $(srcdir)/rotator.h
-extrusion.o: $(HACK_SRC)/screenhackI.h
-extrusion.o: $(UTILS_SRC)/colors.h
-extrusion.o: $(UTILS_SRC)/grabscreen.h
-extrusion.o: $(UTILS_SRC)/hsv.h
-extrusion.o: $(UTILS_SRC)/resources.h
-extrusion.o: $(UTILS_SRC)/usleep.h
-extrusion.o: $(UTILS_SRC)/visual.h
-extrusion.o: $(UTILS_SRC)/xshm.h
-extrusion.o: $(UTILS_SRC)/yarandom.h
-extrusion.o: $(HACK_SRC)/xlockmoreI.h
-extrusion.o: $(HACK_SRC)/xlockmore.h
-extrusion.o: $(srcdir)/xpm-ximage.h
-extrusion-screw.o: ../../config.h
-extrusion-screw.o: $(srcdir)/extrusion.h
-extrusion-taper.o: ../../config.h
-extrusion-taper.o: $(srcdir)/extrusion.h
-extrusion-twistoid.o: ../../config.h
-extrusion-twistoid.o: $(srcdir)/extrusion.h
-flipflop.o: ../../config.h
-flipflop.o: $(HACK_SRC)/fps.h
-flipflop.o: $(srcdir)/gltrackball.h
-flipflop.o: $(srcdir)/grab-ximage.h
-flipflop.o: $(HACK_SRC)/screenhackI.h
-flipflop.o: $(UTILS_SRC)/colors.h
-flipflop.o: $(UTILS_SRC)/grabscreen.h
-flipflop.o: $(UTILS_SRC)/hsv.h
-flipflop.o: $(UTILS_SRC)/resources.h
-flipflop.o: $(UTILS_SRC)/usleep.h
-flipflop.o: $(UTILS_SRC)/visual.h
-flipflop.o: $(UTILS_SRC)/xshm.h
-flipflop.o: $(UTILS_SRC)/yarandom.h
-flipflop.o: $(HACK_SRC)/xlockmoreI.h
-flipflop.o: $(HACK_SRC)/xlockmore.h
-flipscreen3d.o: ../../config.h
-flipscreen3d.o: $(HACK_SRC)/fps.h
-flipscreen3d.o: $(srcdir)/gltrackball.h
-flipscreen3d.o: $(srcdir)/grab-ximage.h
-flipscreen3d.o: $(HACK_SRC)/screenhackI.h
-flipscreen3d.o: $(UTILS_SRC)/colors.h
-flipscreen3d.o: $(UTILS_SRC)/grabscreen.h
-flipscreen3d.o: $(UTILS_SRC)/hsv.h
-flipscreen3d.o: $(UTILS_SRC)/resources.h
-flipscreen3d.o: $(UTILS_SRC)/usleep.h
-flipscreen3d.o: $(UTILS_SRC)/visual.h
-flipscreen3d.o: $(UTILS_SRC)/xshm.h
-flipscreen3d.o: $(UTILS_SRC)/yarandom.h
-flipscreen3d.o: $(HACK_SRC)/xlockmoreI.h
-flipscreen3d.o: $(HACK_SRC)/xlockmore.h
-fliptext.o: ../../config.h
-fliptext.o: $(HACK_SRC)/fps.h
-fliptext.o: $(HACK_SRC)/screenhackI.h
-fliptext.o: $(srcdir)/texfont.h
-fliptext.o: $(UTILS_SRC)/colors.h
-fliptext.o: $(UTILS_SRC)/grabscreen.h
-fliptext.o: $(UTILS_SRC)/hsv.h
-fliptext.o: $(UTILS_SRC)/resources.h
-fliptext.o: $(UTILS_SRC)/usleep.h
-fliptext.o: $(UTILS_SRC)/visual.h
-fliptext.o: $(UTILS_SRC)/xshm.h
-fliptext.o: $(UTILS_SRC)/yarandom.h
-fliptext.o: $(HACK_SRC)/xlockmoreI.h
-fliptext.o: $(HACK_SRC)/xlockmore.h
-flurry.o: ../../config.h
-flurry.o: $(srcdir)/flurry.h
-flurry.o: $(HACK_SRC)/fps.h
-flurry.o: $(srcdir)/gltrackball.h
-flurry.o: $(srcdir)/rotator.h
-flurry.o: $(HACK_SRC)/screenhackI.h
-flurry.o: $(UTILS_SRC)/colors.h
-flurry.o: $(UTILS_SRC)/grabscreen.h
-flurry.o: $(UTILS_SRC)/hsv.h
-flurry.o: $(UTILS_SRC)/resources.h
-flurry.o: $(UTILS_SRC)/usleep.h
-flurry.o: $(UTILS_SRC)/visual.h
-flurry.o: $(UTILS_SRC)/xshm.h
-flurry.o: $(UTILS_SRC)/yarandom.h
-flurry.o: $(HACK_SRC)/xlockmoreI.h
-flurry.o: $(HACK_SRC)/xlockmore.h
-flurry-smoke.o: ../../config.h
-flurry-smoke.o: $(srcdir)/flurry.h
-flurry-smoke.o: $(srcdir)/gltrackball.h
-flurry-smoke.o: $(srcdir)/rotator.h
-flurry-smoke.o: $(UTILS_SRC)/yarandom.h
-flurry-spark.o: ../../config.h
-flurry-spark.o: $(srcdir)/flurry.h
-flurry-spark.o: $(srcdir)/gltrackball.h
-flurry-spark.o: $(srcdir)/rotator.h
-flurry-spark.o: $(UTILS_SRC)/yarandom.h
-flurry-star.o: ../../config.h
-flurry-star.o: $(srcdir)/flurry.h
-flurry-star.o: $(srcdir)/gltrackball.h
-flurry-star.o: $(srcdir)/rotator.h
-flurry-star.o: $(UTILS_SRC)/yarandom.h
-flurry-texture.o: ../../config.h
-flurry-texture.o: $(srcdir)/flurry.h
-flurry-texture.o: $(srcdir)/gltrackball.h
-flurry-texture.o: $(srcdir)/rotator.h
-flurry-texture.o: $(UTILS_SRC)/yarandom.h
-flyingtoasters.o: ../../config.h
-flyingtoasters.o: $(HACK_SRC)/fps.h
-flyingtoasters.o: $(srcdir)/gllist.h
-flyingtoasters.o: $(srcdir)/gltrackball.h
-flyingtoasters.o: $(HACK_SRC)/images/chromesphere.xpm
-flyingtoasters.o: $(HACK_SRC)/images/toast.xpm
-flyingtoasters.o: $(HACK_SRC)/screenhackI.h
-flyingtoasters.o: $(UTILS_SRC)/colors.h
-flyingtoasters.o: $(UTILS_SRC)/grabscreen.h
-flyingtoasters.o: $(UTILS_SRC)/hsv.h
-flyingtoasters.o: $(UTILS_SRC)/resources.h
-flyingtoasters.o: $(UTILS_SRC)/usleep.h
-flyingtoasters.o: $(UTILS_SRC)/visual.h
-flyingtoasters.o: $(UTILS_SRC)/xshm.h
-flyingtoasters.o: $(UTILS_SRC)/yarandom.h
-flyingtoasters.o: $(HACK_SRC)/xlockmoreI.h
-flyingtoasters.o: $(HACK_SRC)/xlockmore.h
-flyingtoasters.o: $(srcdir)/xpm-ximage.h
-font-ximage.o: ../../config.h
-font-ximage.o: $(srcdir)/font-ximage.h
-fps-gl.o: ../../config.h
-fps-gl.o: $(HACK_SRC)/fpsI.h
-fps-gl.o: $(HACK_SRC)/fps.h
-fps-gl.o: $(srcdir)/glxfonts.h
-fps-gl.o: $(HACK_SRC)/screenhackI.h
-fps-gl.o: $(UTILS_SRC)/colors.h
-fps-gl.o: $(UTILS_SRC)/grabscreen.h
-fps-gl.o: $(UTILS_SRC)/hsv.h
-fps-gl.o: $(UTILS_SRC)/resources.h
-fps-gl.o: $(UTILS_SRC)/usleep.h
-fps-gl.o: $(UTILS_SRC)/visual.h
-fps-gl.o: $(UTILS_SRC)/xshm.h
-fps-gl.o: $(UTILS_SRC)/yarandom.h
-fps-gl.o: $(HACK_SRC)/xlockmoreI.h
-gears.o: ../../config.h
-gears.o: $(HACK_SRC)/fps.h
-gears.o: $(srcdir)/gltrackball.h
-gears.o: $(srcdir)/involute.h
-gears.o: $(srcdir)/normals.h
-gears.o: $(srcdir)/rotator.h
-gears.o: $(HACK_SRC)/screenhackI.h
-gears.o: $(srcdir)/tube.h
-gears.o: $(UTILS_SRC)/colors.h
-gears.o: $(UTILS_SRC)/grabscreen.h
-gears.o: $(UTILS_SRC)/hsv.h
-gears.o: $(UTILS_SRC)/resources.h
-gears.o: $(UTILS_SRC)/usleep.h
-gears.o: $(UTILS_SRC)/visual.h
-gears.o: $(UTILS_SRC)/xshm.h
-gears.o: $(UTILS_SRC)/yarandom.h
-gears.o: $(HACK_SRC)/xlockmoreI.h
-gears.o: $(HACK_SRC)/xlockmore.h
-gflux.o: ../../config.h
-gflux.o: $(HACK_SRC)/fps.h
-gflux.o: $(srcdir)/gltrackball.h
-gflux.o: $(srcdir)/grab-ximage.h
-gflux.o: $(HACK_SRC)/screenhackI.h
-gflux.o: $(UTILS_SRC)/colors.h
-gflux.o: $(UTILS_SRC)/grabscreen.h
-gflux.o: $(UTILS_SRC)/hsv.h
-gflux.o: $(UTILS_SRC)/resources.h
-gflux.o: $(UTILS_SRC)/usleep.h
-gflux.o: $(UTILS_SRC)/visual.h
-gflux.o: $(UTILS_SRC)/xshm.h
-gflux.o: $(UTILS_SRC)/yarandom.h
-gflux.o: $(HACK_SRC)/xlockmoreI.h
-gflux.o: $(HACK_SRC)/xlockmore.h
-glblur.o: ../../config.h
-glblur.o: $(HACK_SRC)/fps.h
-glblur.o: $(srcdir)/gltrackball.h
-glblur.o: $(srcdir)/rotator.h
-glblur.o: $(HACK_SRC)/screenhackI.h
-glblur.o: $(UTILS_SRC)/colors.h
-glblur.o: $(UTILS_SRC)/grabscreen.h
-glblur.o: $(UTILS_SRC)/hsv.h
-glblur.o: $(UTILS_SRC)/resources.h
-glblur.o: $(UTILS_SRC)/usleep.h
-glblur.o: $(UTILS_SRC)/visual.h
-glblur.o: $(UTILS_SRC)/xshm.h
-glblur.o: $(UTILS_SRC)/yarandom.h
-glblur.o: $(HACK_SRC)/xlockmoreI.h
-glblur.o: $(HACK_SRC)/xlockmore.h
-glcells.o: ../../config.h
-glcells.o: $(HACK_SRC)/fps.h
-glcells.o: $(HACK_SRC)/screenhackI.h
-glcells.o: $(UTILS_SRC)/colors.h
-glcells.o: $(UTILS_SRC)/grabscreen.h
-glcells.o: $(UTILS_SRC)/hsv.h
-glcells.o: $(UTILS_SRC)/resources.h
-glcells.o: $(UTILS_SRC)/usleep.h
-glcells.o: $(UTILS_SRC)/visual.h
-glcells.o: $(UTILS_SRC)/xshm.h
-glcells.o: $(UTILS_SRC)/yarandom.h
-glcells.o: $(HACK_SRC)/xlockmoreI.h
-glcells.o: $(HACK_SRC)/xlockmore.h
-gleidescope.o: ../../config.h
-gleidescope.o: $(HACK_SRC)/fps.h
-gleidescope.o: $(srcdir)/grab-ximage.h
-gleidescope.o: $(HACK_SRC)/screenhackI.h
-gleidescope.o: $(UTILS_SRC)/colors.h
-gleidescope.o: $(UTILS_SRC)/grabscreen.h
-gleidescope.o: $(UTILS_SRC)/hsv.h
-gleidescope.o: $(UTILS_SRC)/resources.h
-gleidescope.o: $(UTILS_SRC)/usleep.h
-gleidescope.o: $(UTILS_SRC)/visual.h
-gleidescope.o: $(UTILS_SRC)/xshm.h
-gleidescope.o: $(UTILS_SRC)/yarandom.h
-gleidescope.o: $(HACK_SRC)/xlockmoreI.h
-gleidescope.o: $(HACK_SRC)/xlockmore.h
-gleidescope.o: $(srcdir)/xpm-ximage.h
-glforestfire.o: ../../config.h
-glforestfire.o: $(HACK_SRC)/fps.h
-glforestfire.o: $(srcdir)/gltrackball.h
-glforestfire.o: $(HACK_SRC)/images/ground.xpm
-glforestfire.o: $(HACK_SRC)/images/tree.xpm
-glforestfire.o: $(HACK_SRC)/screenhackI.h
-glforestfire.o: $(UTILS_SRC)/colors.h
-glforestfire.o: $(UTILS_SRC)/grabscreen.h
-glforestfire.o: $(UTILS_SRC)/hsv.h
-glforestfire.o: $(UTILS_SRC)/resources.h
-glforestfire.o: $(UTILS_SRC)/usleep.h
-glforestfire.o: $(UTILS_SRC)/visual.h
-glforestfire.o: $(UTILS_SRC)/xshm.h
-glforestfire.o: $(UTILS_SRC)/yarandom.h
-glforestfire.o: $(HACK_SRC)/xlockmoreI.h
-glforestfire.o: $(HACK_SRC)/xlockmore.h
-glforestfire.o: $(srcdir)/xpm-ximage.h
-glhanoi.o: ../../config.h
-glhanoi.o: $(HACK_SRC)/fps.h
-glhanoi.o: $(srcdir)/rotator.h
-glhanoi.o: $(HACK_SRC)/screenhackI.h
-glhanoi.o: $(UTILS_SRC)/colors.h
-glhanoi.o: $(UTILS_SRC)/grabscreen.h
-glhanoi.o: $(UTILS_SRC)/hsv.h
-glhanoi.o: $(UTILS_SRC)/resources.h
-glhanoi.o: $(UTILS_SRC)/usleep.h
-glhanoi.o: $(UTILS_SRC)/visual.h
-glhanoi.o: $(UTILS_SRC)/xshm.h
-glhanoi.o: $(UTILS_SRC)/yarandom.h
-glhanoi.o: $(HACK_SRC)/xlockmoreI.h
-glhanoi.o: $(HACK_SRC)/xlockmore.h
-glknots.o: ../../config.h
-glknots.o: $(HACK_SRC)/fps.h
-glknots.o: $(srcdir)/gltrackball.h
-glknots.o: $(srcdir)/rotator.h
-glknots.o: $(HACK_SRC)/screenhackI.h
-glknots.o: $(srcdir)/tube.h
-glknots.o: $(UTILS_SRC)/colors.h
-glknots.o: $(UTILS_SRC)/grabscreen.h
-glknots.o: $(UTILS_SRC)/hsv.h
-glknots.o: $(UTILS_SRC)/resources.h
-glknots.o: $(UTILS_SRC)/usleep.h
-glknots.o: $(UTILS_SRC)/visual.h
-glknots.o: $(UTILS_SRC)/xshm.h
-glknots.o: $(UTILS_SRC)/yarandom.h
-glknots.o: $(HACK_SRC)/xlockmoreI.h
-glknots.o: $(HACK_SRC)/xlockmore.h
-gllist.o: $(srcdir)/gllist.h
-glmatrix.o: ../../config.h
-glmatrix.o: $(HACK_SRC)/fps.h
-glmatrix.o: $(srcdir)/gllist.h
-glmatrix.o: $(HACK_SRC)/images/matrix3.xpm
-glmatrix.o: $(HACK_SRC)/screenhackI.h
-glmatrix.o: $(UTILS_SRC)/colors.h
-glmatrix.o: $(UTILS_SRC)/grabscreen.h
-glmatrix.o: $(UTILS_SRC)/hsv.h
-glmatrix.o: $(UTILS_SRC)/resources.h
-glmatrix.o: $(UTILS_SRC)/usleep.h
-glmatrix.o: $(UTILS_SRC)/visual.h
-glmatrix.o: $(UTILS_SRC)/xshm.h
-glmatrix.o: $(UTILS_SRC)/yarandom.h
-glmatrix.o: $(HACK_SRC)/xlockmoreI.h
-glmatrix.o: $(HACK_SRC)/xlockmore.h
-glmatrix.o: $(srcdir)/xpm-ximage.h
-glplanet.o: ../../config.h
-glplanet.o: $(HACK_SRC)/fps.h
-glplanet.o: $(srcdir)/gltrackball.h
-glplanet.o: $(HACK_SRC)/images/earth.xpm
-glplanet.o: $(srcdir)/rotator.h
-glplanet.o: $(HACK_SRC)/screenhackI.h
-glplanet.o: $(srcdir)/sphere.h
-glplanet.o: $(UTILS_SRC)/colors.h
-glplanet.o: $(UTILS_SRC)/grabscreen.h
-glplanet.o: $(UTILS_SRC)/hsv.h
-glplanet.o: $(UTILS_SRC)/resources.h
-glplanet.o: $(UTILS_SRC)/usleep.h
-glplanet.o: $(UTILS_SRC)/visual.h
-glplanet.o: $(UTILS_SRC)/xshm.h
-glplanet.o: $(UTILS_SRC)/yarandom.h
-glplanet.o: $(HACK_SRC)/xlockmoreI.h
-glplanet.o: $(HACK_SRC)/xlockmore.h
-glplanet.o: $(srcdir)/xpm-ximage.h
-glschool_alg.o: ../../config.h
-glschool_alg.o: $(srcdir)/glschool_alg.h
-glschool_alg.o: $(UTILS_SRC)/yarandom.h
-glschool_gl.o: $(srcdir)/glschool_alg.h
-glschool_gl.o: $(srcdir)/glschool_gl.h
-glschool_gl.o: $(srcdir)/sphere.h
-glschool_gl.o: $(srcdir)/tube.h
-glschool.o: ../../config.h
-glschool.o: $(HACK_SRC)/fps.h
-glschool.o: $(srcdir)/glschool_alg.h
-glschool.o: $(srcdir)/glschool_gl.h
-glschool.o: $(srcdir)/glschool.h
-glschool.o: $(HACK_SRC)/screenhackI.h
-glschool.o: $(UTILS_SRC)/colors.h
-glschool.o: $(UTILS_SRC)/grabscreen.h
-glschool.o: $(UTILS_SRC)/hsv.h
-glschool.o: $(UTILS_SRC)/resources.h
-glschool.o: $(UTILS_SRC)/usleep.h
-glschool.o: $(UTILS_SRC)/visual.h
-glschool.o: $(UTILS_SRC)/xshm.h
-glschool.o: $(UTILS_SRC)/yarandom.h
-glschool.o: $(HACK_SRC)/xlockmoreI.h
-glschool.o: $(HACK_SRC)/xlockmore.h
-glslideshow.o: ../../config.h
-glslideshow.o: $(HACK_SRC)/fps.h
-glslideshow.o: $(srcdir)/glxfonts.h
-glslideshow.o: $(srcdir)/grab-ximage.h
-glslideshow.o: $(HACK_SRC)/screenhackI.h
-glslideshow.o: $(UTILS_SRC)/colors.h
-glslideshow.o: $(UTILS_SRC)/grabscreen.h
-glslideshow.o: $(UTILS_SRC)/hsv.h
-glslideshow.o: $(UTILS_SRC)/resources.h
-glslideshow.o: $(UTILS_SRC)/usleep.h
-glslideshow.o: $(UTILS_SRC)/visual.h
-glslideshow.o: $(UTILS_SRC)/xshm.h
-glslideshow.o: $(UTILS_SRC)/yarandom.h
-glslideshow.o: $(HACK_SRC)/xlockmoreI.h
-glslideshow.o: $(HACK_SRC)/xlockmore.h
-glsnake.o: ../../config.h
-glsnake.o: $(HACK_SRC)/fps.h
-glsnake.o: $(srcdir)/glxfonts.h
-glsnake.o: $(HACK_SRC)/screenhackI.h
-glsnake.o: $(UTILS_SRC)/colors.h
-glsnake.o: $(UTILS_SRC)/grabscreen.h
-glsnake.o: $(UTILS_SRC)/hsv.h
-glsnake.o: $(UTILS_SRC)/resources.h
-glsnake.o: $(UTILS_SRC)/usleep.h
-glsnake.o: $(UTILS_SRC)/visual.h
-glsnake.o: $(UTILS_SRC)/xshm.h
-glsnake.o: $(UTILS_SRC)/yarandom.h
-glsnake.o: $(HACK_SRC)/xlockmoreI.h
-glsnake.o: $(HACK_SRC)/xlockmore.h
-gltext.o: ../../config.h
-gltext.o: $(HACK_SRC)/fps.h
-gltext.o: $(srcdir)/gltrackball.h
-gltext.o: $(srcdir)/glut_roman.h
-gltext.o: $(srcdir)/glutstroke.h
-gltext.o: $(srcdir)/rotator.h
-gltext.o: $(HACK_SRC)/screenhackI.h
-gltext.o: $(srcdir)/tube.h
-gltext.o: $(UTILS_SRC)/colors.h
-gltext.o: $(UTILS_SRC)/grabscreen.h
-gltext.o: $(UTILS_SRC)/hsv.h
-gltext.o: $(UTILS_SRC)/resources.h
-gltext.o: $(UTILS_SRC)/usleep.h
-gltext.o: $(UTILS_SRC)/visual.h
-gltext.o: $(UTILS_SRC)/xshm.h
-gltext.o: $(UTILS_SRC)/yarandom.h
-gltext.o: $(HACK_SRC)/xlockmoreI.h
-gltext.o: $(HACK_SRC)/xlockmore.h
-gltrackball.o: ../../config.h
-gltrackball.o: $(srcdir)/gltrackball.h
-gltrackball.o: $(srcdir)/trackball.h
-glut_stroke.o: ../../config.h
-glut_stroke.o: $(srcdir)/glutstroke.h
-glut_swidth.o: ../../config.h
-glut_swidth.o: $(srcdir)/glutstroke.h
-glxfonts.o: ../../config.h
-glxfonts.o: $(srcdir)/glxfonts.h
-glxfonts.o: $(UTILS_SRC)/resources.h
-grab-ximage.o: ../../config.h
-grab-ximage.o: $(srcdir)/grab-ximage.h
-grab-ximage.o: $(UTILS_SRC)/grabscreen.h
-grab-ximage.o: $(UTILS_SRC)/resources.h
-grab-ximage.o: $(UTILS_SRC)/visual.h
-grab-ximage.o: $(UTILS_SRC)/xshm.h
-hypertorus.o: ../../config.h
-hypertorus.o: $(HACK_SRC)/fps.h
-hypertorus.o: $(srcdir)/gltrackball.h
-hypertorus.o: $(HACK_SRC)/screenhackI.h
-hypertorus.o: $(UTILS_SRC)/colors.h
-hypertorus.o: $(UTILS_SRC)/grabscreen.h
-hypertorus.o: $(UTILS_SRC)/hsv.h
-hypertorus.o: $(UTILS_SRC)/resources.h
-hypertorus.o: $(UTILS_SRC)/usleep.h
-hypertorus.o: $(UTILS_SRC)/visual.h
-hypertorus.o: $(UTILS_SRC)/xshm.h
-hypertorus.o: $(UTILS_SRC)/yarandom.h
-hypertorus.o: $(HACK_SRC)/xlockmoreI.h
-hypertorus.o: $(HACK_SRC)/xlockmore.h
-hypnowheel.o: ../../config.h
-hypnowheel.o: $(HACK_SRC)/fps.h
-hypnowheel.o: $(srcdir)/rotator.h
-hypnowheel.o: $(HACK_SRC)/screenhackI.h
-hypnowheel.o: $(UTILS_SRC)/colors.h
-hypnowheel.o: $(UTILS_SRC)/grabscreen.h
-hypnowheel.o: $(UTILS_SRC)/hsv.h
-hypnowheel.o: $(UTILS_SRC)/resources.h
-hypnowheel.o: $(UTILS_SRC)/usleep.h
-hypnowheel.o: $(UTILS_SRC)/visual.h
-hypnowheel.o: $(UTILS_SRC)/xshm.h
-hypnowheel.o: $(UTILS_SRC)/yarandom.h
-hypnowheel.o: $(HACK_SRC)/xlockmoreI.h
-hypnowheel.o: $(HACK_SRC)/xlockmore.h
-involute.o: ../../config.h
-involute.o: $(HACK_SRC)/fps.h
-involute.o: $(srcdir)/involute.h
-involute.o: $(srcdir)/normals.h
-involute.o: $(HACK_SRC)/screenhackI.h
-involute.o: $(UTILS_SRC)/colors.h
-involute.o: $(UTILS_SRC)/grabscreen.h
-involute.o: $(UTILS_SRC)/hsv.h
-involute.o: $(UTILS_SRC)/resources.h
-involute.o: $(UTILS_SRC)/usleep.h
-involute.o: $(UTILS_SRC)/visual.h
-involute.o: $(UTILS_SRC)/yarandom.h
-jigglypuff.o: ../../config.h
-jigglypuff.o: $(HACK_SRC)/fps.h
-jigglypuff.o: $(srcdir)/gltrackball.h
-jigglypuff.o: $(HACK_SRC)/images/jigglymap.xpm
-jigglypuff.o: $(HACK_SRC)/screenhackI.h
-jigglypuff.o: $(UTILS_SRC)/colors.h
-jigglypuff.o: $(UTILS_SRC)/grabscreen.h
-jigglypuff.o: $(UTILS_SRC)/hsv.h
-jigglypuff.o: $(UTILS_SRC)/resources.h
-jigglypuff.o: $(UTILS_SRC)/usleep.h
-jigglypuff.o: $(UTILS_SRC)/visual.h
-jigglypuff.o: $(UTILS_SRC)/xshm.h
-jigglypuff.o: $(UTILS_SRC)/yarandom.h
-jigglypuff.o: $(HACK_SRC)/xlockmoreI.h
-jigglypuff.o: $(HACK_SRC)/xlockmore.h
-jigglypuff.o: $(srcdir)/xpm-ximage.h
-jigsaw.o: ../../config.h
-jigsaw.o: $(HACK_SRC)/fps.h
-jigsaw.o: $(srcdir)/gltrackball.h
-jigsaw.o: $(srcdir)/grab-ximage.h
-jigsaw.o: $(srcdir)/normals.h
-jigsaw.o: $(srcdir)/rotator.h
-jigsaw.o: $(HACK_SRC)/screenhackI.h
-jigsaw.o: $(UTILS_SRC)/colors.h
-jigsaw.o: $(UTILS_SRC)/grabscreen.h
-jigsaw.o: $(UTILS_SRC)/hsv.h
-jigsaw.o: $(UTILS_SRC)/resources.h
-jigsaw.o: $(UTILS_SRC)/spline.h
-jigsaw.o: $(UTILS_SRC)/usleep.h
-jigsaw.o: $(UTILS_SRC)/visual.h
-jigsaw.o: $(UTILS_SRC)/xshm.h
-jigsaw.o: $(UTILS_SRC)/yarandom.h
-jigsaw.o: $(HACK_SRC)/xlockmoreI.h
-jigsaw.o: $(HACK_SRC)/xlockmore.h
-juggler3d.o: ../../config.h
-juggler3d.o: $(HACK_SRC)/fps.h
-juggler3d.o: $(srcdir)/gltrackball.h
-juggler3d.o: $(HACK_SRC)/screenhackI.h
-juggler3d.o: $(UTILS_SRC)/colors.h
-juggler3d.o: $(UTILS_SRC)/grabscreen.h
-juggler3d.o: $(UTILS_SRC)/hsv.h
-juggler3d.o: $(UTILS_SRC)/resources.h
-juggler3d.o: $(UTILS_SRC)/usleep.h
-juggler3d.o: $(UTILS_SRC)/visual.h
-juggler3d.o: $(UTILS_SRC)/xshm.h
-juggler3d.o: $(UTILS_SRC)/yarandom.h
-juggler3d.o: $(HACK_SRC)/xlockmoreI.h
-juggler3d.o: $(HACK_SRC)/xlockmore.h
-klein.o: ../../config.h
-klein.o: $(HACK_SRC)/fps.h
-klein.o: $(srcdir)/gltrackball.h
-klein.o: $(srcdir)/rotator.h
-klein.o: $(HACK_SRC)/screenhackI.h
-klein.o: $(UTILS_SRC)/colors.h
-klein.o: $(UTILS_SRC)/grabscreen.h
-klein.o: $(UTILS_SRC)/hsv.h
-klein.o: $(UTILS_SRC)/resources.h
-klein.o: $(UTILS_SRC)/usleep.h
-klein.o: $(UTILS_SRC)/visual.h
-klein.o: $(UTILS_SRC)/xshm.h
-klein.o: $(UTILS_SRC)/yarandom.h
-klein.o: $(HACK_SRC)/xlockmoreI.h
-klein.o: $(HACK_SRC)/xlockmore.h
-lament.o: ../../config.h
-lament.o: $(HACK_SRC)/fps.h
-lament.o: $(srcdir)/gltrackball.h
-lament.o: $(HACK_SRC)/images/lament.xpm
-lament.o: $(srcdir)/normals.h
-lament.o: $(srcdir)/rotator.h
-lament.o: $(HACK_SRC)/screenhackI.h
-lament.o: $(UTILS_SRC)/colors.h
-lament.o: $(UTILS_SRC)/grabscreen.h
-lament.o: $(UTILS_SRC)/hsv.h
-lament.o: $(UTILS_SRC)/resources.h
-lament.o: $(UTILS_SRC)/usleep.h
-lament.o: $(UTILS_SRC)/visual.h
-lament.o: $(UTILS_SRC)/xshm.h
-lament.o: $(UTILS_SRC)/yarandom.h
-lament.o: $(HACK_SRC)/xlockmoreI.h
-lament.o: $(HACK_SRC)/xlockmore.h
-lament.o: $(srcdir)/xpm-ximage.h
-lavalite.o: ../../config.h
-lavalite.o: $(HACK_SRC)/fps.h
-lavalite.o: $(srcdir)/gltrackball.h
-lavalite.o: $(srcdir)/marching.h
-lavalite.o: $(srcdir)/rotator.h
-lavalite.o: $(HACK_SRC)/screenhackI.h
-lavalite.o: $(UTILS_SRC)/colors.h
-lavalite.o: $(UTILS_SRC)/grabscreen.h
-lavalite.o: $(UTILS_SRC)/hsv.h
-lavalite.o: $(UTILS_SRC)/resources.h
-lavalite.o: $(UTILS_SRC)/usleep.h
-lavalite.o: $(UTILS_SRC)/visual.h
-lavalite.o: $(UTILS_SRC)/xshm.h
-lavalite.o: $(UTILS_SRC)/yarandom.h
-lavalite.o: $(HACK_SRC)/xlockmoreI.h
-lavalite.o: $(HACK_SRC)/xlockmore.h
-lavalite.o: $(srcdir)/xpm-ximage.h
-lockward.o: ../../config.h
-lockward.o: $(HACK_SRC)/fps.h
-lockward.o: $(HACK_SRC)/screenhackI.h
-lockward.o: $(UTILS_SRC)/colors.h
-lockward.o: $(UTILS_SRC)/grabscreen.h
-lockward.o: $(UTILS_SRC)/hsv.h
-lockward.o: $(UTILS_SRC)/resources.h
-lockward.o: $(UTILS_SRC)/usleep.h
-lockward.o: $(UTILS_SRC)/visual.h
-lockward.o: $(UTILS_SRC)/xshm.h
-lockward.o: $(UTILS_SRC)/yarandom.h
-lockward.o: $(HACK_SRC)/xlockmoreI.h
-lockward.o: $(HACK_SRC)/xlockmore.h
-marching.o: ../../config.h
-marching.o: $(srcdir)/marching.h
-marching.o: $(srcdir)/normals.h
-menger.o: ../../config.h
-menger.o: $(HACK_SRC)/fps.h
-menger.o: $(srcdir)/gltrackball.h
-menger.o: $(srcdir)/rotator.h
-menger.o: $(HACK_SRC)/screenhackI.h
-menger.o: $(UTILS_SRC)/colors.h
-menger.o: $(UTILS_SRC)/grabscreen.h
-menger.o: $(UTILS_SRC)/hsv.h
-menger.o: $(UTILS_SRC)/resources.h
-menger.o: $(UTILS_SRC)/usleep.h
-menger.o: $(UTILS_SRC)/visual.h
-menger.o: $(UTILS_SRC)/xshm.h
-menger.o: $(UTILS_SRC)/yarandom.h
-menger.o: $(HACK_SRC)/xlockmoreI.h
-menger.o: $(HACK_SRC)/xlockmore.h
-mirrorblob.o: ../../config.h
-mirrorblob.o: $(HACK_SRC)/fps.h
-mirrorblob.o: $(srcdir)/gltrackball.h
-mirrorblob.o: $(srcdir)/grab-ximage.h
-mirrorblob.o: $(HACK_SRC)/screenhackI.h
-mirrorblob.o: $(UTILS_SRC)/colors.h
-mirrorblob.o: $(UTILS_SRC)/grabscreen.h
-mirrorblob.o: $(UTILS_SRC)/hsv.h
-mirrorblob.o: $(UTILS_SRC)/resources.h
-mirrorblob.o: $(UTILS_SRC)/usleep.h
-mirrorblob.o: $(UTILS_SRC)/visual.h
-mirrorblob.o: $(UTILS_SRC)/xshm.h
-mirrorblob.o: $(UTILS_SRC)/yarandom.h
-mirrorblob.o: $(HACK_SRC)/xlockmoreI.h
-mirrorblob.o: $(HACK_SRC)/xlockmore.h
-moebiusgears.o: ../../config.h
-moebiusgears.o: $(HACK_SRC)/fps.h
-moebiusgears.o: $(srcdir)/gltrackball.h
-moebiusgears.o: $(srcdir)/involute.h
-moebiusgears.o: $(srcdir)/normals.h
-moebiusgears.o: $(srcdir)/rotator.h
-moebiusgears.o: $(HACK_SRC)/screenhackI.h
-moebiusgears.o: $(UTILS_SRC)/colors.h
-moebiusgears.o: $(UTILS_SRC)/grabscreen.h
-moebiusgears.o: $(UTILS_SRC)/hsv.h
-moebiusgears.o: $(UTILS_SRC)/resources.h
-moebiusgears.o: $(UTILS_SRC)/usleep.h
-moebiusgears.o: $(UTILS_SRC)/visual.h
-moebiusgears.o: $(UTILS_SRC)/xshm.h
-moebiusgears.o: $(UTILS_SRC)/yarandom.h
-moebiusgears.o: $(HACK_SRC)/xlockmoreI.h
-moebiusgears.o: $(HACK_SRC)/xlockmore.h
-moebius.o: ../../config.h
-moebius.o: $(srcdir)/e_textures.h
-moebius.o: $(HACK_SRC)/fps.h
-moebius.o: $(srcdir)/gltrackball.h
-moebius.o: $(srcdir)/rotator.h
-moebius.o: $(HACK_SRC)/screenhackI.h
-moebius.o: $(UTILS_SRC)/colors.h
-moebius.o: $(UTILS_SRC)/grabscreen.h
-moebius.o: $(UTILS_SRC)/hsv.h
-moebius.o: $(UTILS_SRC)/resources.h
-moebius.o: $(UTILS_SRC)/usleep.h
-moebius.o: $(UTILS_SRC)/visual.h
-moebius.o: $(UTILS_SRC)/xshm.h
-moebius.o: $(UTILS_SRC)/yarandom.h
-moebius.o: $(HACK_SRC)/xlockmoreI.h
-moebius.o: $(HACK_SRC)/xlockmore.h
-molecule.o: ../../config.h
-molecule.o: $(HACK_SRC)/fps.h
-molecule.o: $(srcdir)/gltrackball.h
-molecule.o: $(srcdir)/glxfonts.h
-molecule.o: molecules.h
-molecule.o: $(srcdir)/rotator.h
-molecule.o: $(HACK_SRC)/screenhackI.h
-molecule.o: $(srcdir)/sphere.h
-molecule.o: $(srcdir)/tube.h
-molecule.o: $(UTILS_SRC)/colors.h
-molecule.o: $(UTILS_SRC)/grabscreen.h
-molecule.o: $(UTILS_SRC)/hsv.h
-molecule.o: $(UTILS_SRC)/resources.h
-molecule.o: $(UTILS_SRC)/usleep.h
-molecule.o: $(UTILS_SRC)/visual.h
-molecule.o: $(UTILS_SRC)/xshm.h
-molecule.o: $(UTILS_SRC)/yarandom.h
-molecule.o: $(HACK_SRC)/xlockmoreI.h
-molecule.o: $(HACK_SRC)/xlockmore.h
-morph3d.o: ../../config.h
-morph3d.o: $(HACK_SRC)/fps.h
-morph3d.o: $(HACK_SRC)/screenhackI.h
-morph3d.o: $(UTILS_SRC)/colors.h
-morph3d.o: $(UTILS_SRC)/grabscreen.h
-morph3d.o: $(UTILS_SRC)/hsv.h
-morph3d.o: $(UTILS_SRC)/resources.h
-morph3d.o: $(UTILS_SRC)/usleep.h
-morph3d.o: $(UTILS_SRC)/visual.h
-morph3d.o: $(UTILS_SRC)/xshm.h
-morph3d.o: $(UTILS_SRC)/yarandom.h
-morph3d.o: $(HACK_SRC)/xlockmoreI.h
-morph3d.o: $(HACK_SRC)/xlockmore.h
-noof.o: ../../config.h
-noof.o: $(HACK_SRC)/fps.h
-noof.o: $(HACK_SRC)/screenhackI.h
-noof.o: $(UTILS_SRC)/colors.h
-noof.o: $(UTILS_SRC)/grabscreen.h
-noof.o: $(UTILS_SRC)/hsv.h
-noof.o: $(UTILS_SRC)/resources.h
-noof.o: $(UTILS_SRC)/usleep.h
-noof.o: $(UTILS_SRC)/visual.h
-noof.o: $(UTILS_SRC)/xshm.h
-noof.o: $(UTILS_SRC)/yarandom.h
-noof.o: $(HACK_SRC)/xlockmoreI.h
-noof.o: $(HACK_SRC)/xlockmore.h
-normals.o: ../../config.h
-normals.o: $(srcdir)/normals.h
-photopile.o: ../../config.h
-photopile.o: $(HACK_SRC)/fps.h
-photopile.o: $(srcdir)/grab-ximage.h
-photopile.o: $(HACK_SRC)/screenhackI.h
-photopile.o: $(srcdir)/texfont.h
-photopile.o: $(UTILS_SRC)/colors.h
-photopile.o: $(UTILS_SRC)/grabscreen.h
-photopile.o: $(UTILS_SRC)/hsv.h
-photopile.o: $(UTILS_SRC)/resources.h
-photopile.o: $(UTILS_SRC)/usleep.h
-photopile.o: $(UTILS_SRC)/visual.h
-photopile.o: $(UTILS_SRC)/xshm.h
-photopile.o: $(UTILS_SRC)/yarandom.h
-photopile.o: $(HACK_SRC)/xlockmoreI.h
-photopile.o: $(HACK_SRC)/xlockmore.h
-pinion.o: ../../config.h
-pinion.o: $(HACK_SRC)/fps.h
-pinion.o: $(srcdir)/gltrackball.h
-pinion.o: $(srcdir)/glxfonts.h
-pinion.o: $(srcdir)/involute.h
-pinion.o: $(srcdir)/normals.h
-pinion.o: $(HACK_SRC)/screenhackI.h
-pinion.o: $(UTILS_SRC)/colors.h
-pinion.o: $(UTILS_SRC)/grabscreen.h
-pinion.o: $(UTILS_SRC)/hsv.h
-pinion.o: $(UTILS_SRC)/resources.h
-pinion.o: $(UTILS_SRC)/usleep.h
-pinion.o: $(UTILS_SRC)/visual.h
-pinion.o: $(UTILS_SRC)/xshm.h
-pinion.o: $(UTILS_SRC)/yarandom.h
-pinion.o: $(HACK_SRC)/xlockmoreI.h
-pinion.o: $(HACK_SRC)/xlockmore.h
-pipeobjs.o: $(srcdir)/buildlwo.h
-pipes.o: $(srcdir)/buildlwo.h
-pipes.o: ../../config.h
-pipes.o: $(HACK_SRC)/fps.h
-pipes.o: $(HACK_SRC)/screenhackI.h
-pipes.o: $(srcdir)/teapot.h
-pipes.o: $(UTILS_SRC)/colors.h
-pipes.o: $(UTILS_SRC)/grabscreen.h
-pipes.o: $(UTILS_SRC)/hsv.h
-pipes.o: $(UTILS_SRC)/resources.h
-pipes.o: $(UTILS_SRC)/usleep.h
-pipes.o: $(UTILS_SRC)/visual.h
-pipes.o: $(UTILS_SRC)/xshm.h
-pipes.o: $(UTILS_SRC)/yarandom.h
-pipes.o: $(HACK_SRC)/xlockmoreI.h
-pipes.o: $(HACK_SRC)/xlockmore.h
-polyhedra-gl.o: ../../config.h
-polyhedra-gl.o: $(HACK_SRC)/fps.h
-polyhedra-gl.o: $(srcdir)/gltrackball.h
-polyhedra-gl.o: $(srcdir)/glxfonts.h
-polyhedra-gl.o: $(srcdir)/normals.h
-polyhedra-gl.o: $(srcdir)/polyhedra.h
-polyhedra-gl.o: $(srcdir)/rotator.h
-polyhedra-gl.o: $(HACK_SRC)/screenhackI.h
-polyhedra-gl.o: $(srcdir)/teapot.h
-polyhedra-gl.o: $(UTILS_SRC)/colors.h
-polyhedra-gl.o: $(UTILS_SRC)/grabscreen.h
-polyhedra-gl.o: $(UTILS_SRC)/hsv.h
-polyhedra-gl.o: $(UTILS_SRC)/resources.h
-polyhedra-gl.o: $(UTILS_SRC)/usleep.h
-polyhedra-gl.o: $(UTILS_SRC)/visual.h
-polyhedra-gl.o: $(UTILS_SRC)/xshm.h
-polyhedra-gl.o: $(UTILS_SRC)/yarandom.h
-polyhedra-gl.o: $(HACK_SRC)/xlockmoreI.h
-polyhedra-gl.o: $(HACK_SRC)/xlockmore.h
-polyhedra.o: ../../config.h
-polyhedra.o: $(srcdir)/polyhedra.h
-polytopes.o: ../../config.h
-polytopes.o: $(HACK_SRC)/fps.h
-polytopes.o: $(srcdir)/gltrackball.h
-polytopes.o: $(HACK_SRC)/screenhackI.h
-polytopes.o: $(UTILS_SRC)/colors.h
-polytopes.o: $(UTILS_SRC)/grabscreen.h
-polytopes.o: $(UTILS_SRC)/hsv.h
-polytopes.o: $(UTILS_SRC)/resources.h
-polytopes.o: $(UTILS_SRC)/usleep.h
-polytopes.o: $(UTILS_SRC)/visual.h
-polytopes.o: $(UTILS_SRC)/xshm.h
-polytopes.o: $(UTILS_SRC)/yarandom.h
-polytopes.o: $(HACK_SRC)/xlockmoreI.h
-polytopes.o: $(HACK_SRC)/xlockmore.h
-providence.o: ../../config.h
-providence.o: $(HACK_SRC)/fps.h
-providence.o: $(srcdir)/gltrackball.h
-providence.o: $(HACK_SRC)/screenhackI.h
-providence.o: $(UTILS_SRC)/colors.h
-providence.o: $(UTILS_SRC)/grabscreen.h
-providence.o: $(UTILS_SRC)/hsv.h
-providence.o: $(UTILS_SRC)/resources.h
-providence.o: $(UTILS_SRC)/usleep.h
-providence.o: $(UTILS_SRC)/visual.h
-providence.o: $(UTILS_SRC)/xshm.h
-providence.o: $(UTILS_SRC)/yarandom.h
-providence.o: $(HACK_SRC)/xlockmoreI.h
-providence.o: $(HACK_SRC)/xlockmore.h
-pulsar.o: ../../config.h
-pulsar.o: $(HACK_SRC)/fps.h
-pulsar.o: $(HACK_SRC)/screenhackI.h
-pulsar.o: $(UTILS_SRC)/colors.h
-pulsar.o: $(UTILS_SRC)/grabscreen.h
-pulsar.o: $(UTILS_SRC)/hsv.h
-pulsar.o: $(UTILS_SRC)/resources.h
-pulsar.o: $(UTILS_SRC)/usleep.h
-pulsar.o: $(UTILS_SRC)/visual.h
-pulsar.o: $(UTILS_SRC)/xshm.h
-pulsar.o: $(UTILS_SRC)/yarandom.h
-pulsar.o: $(HACK_SRC)/xlockmoreI.h
-pulsar.o: $(HACK_SRC)/xlockmore.h
-pulsar.o: $(srcdir)/xpm-ximage.h
-queens.o: ../../config.h
-queens.o: $(HACK_SRC)/fps.h
-queens.o: $(srcdir)/gltrackball.h
-queens.o: $(HACK_SRC)/screenhackI.h
-queens.o: $(UTILS_SRC)/colors.h
-queens.o: $(UTILS_SRC)/grabscreen.h
-queens.o: $(UTILS_SRC)/hsv.h
-queens.o: $(UTILS_SRC)/resources.h
-queens.o: $(UTILS_SRC)/usleep.h
-queens.o: $(UTILS_SRC)/visual.h
-queens.o: $(UTILS_SRC)/xshm.h
-queens.o: $(UTILS_SRC)/yarandom.h
-queens.o: $(HACK_SRC)/xlockmoreI.h
-queens.o: $(HACK_SRC)/xlockmore.h
-rotator.o: ../../config.h
-rotator.o: $(srcdir)/rotator.h
-rotator.o: $(UTILS_SRC)/yarandom.h
-rubik.o: ../../config.h
-rubik.o: $(HACK_SRC)/fps.h
-rubik.o: $(HACK_SRC)/screenhackI.h
-rubik.o: $(UTILS_SRC)/colors.h
-rubik.o: $(UTILS_SRC)/grabscreen.h
-rubik.o: $(UTILS_SRC)/hsv.h
-rubik.o: $(UTILS_SRC)/resources.h
-rubik.o: $(UTILS_SRC)/usleep.h
-rubik.o: $(UTILS_SRC)/visual.h
-rubik.o: $(UTILS_SRC)/xshm.h
-rubik.o: $(UTILS_SRC)/yarandom.h
-rubik.o: $(HACK_SRC)/xlockmoreI.h
-rubik.o: $(HACK_SRC)/xlockmore.h
-s1_1.o: $(srcdir)/gllist.h
-s1_2.o: $(srcdir)/gllist.h
-s1_3.o: $(srcdir)/gllist.h
-s1_4.o: $(srcdir)/gllist.h
-s1_5.o: $(srcdir)/gllist.h
-s1_6.o: $(srcdir)/gllist.h
-s1_b.o: $(srcdir)/gllist.h
-sballs.o: ../../config.h
-sballs.o: $(HACK_SRC)/fps.h
-sballs.o: $(srcdir)/gltrackball.h
-sballs.o: $(HACK_SRC)/images/sball-bg.xpm
-sballs.o: $(HACK_SRC)/images/sball.xpm
-sballs.o: $(HACK_SRC)/screenhackI.h
-sballs.o: $(UTILS_SRC)/colors.h
-sballs.o: $(UTILS_SRC)/grabscreen.h
-sballs.o: $(UTILS_SRC)/hsv.h
-sballs.o: $(UTILS_SRC)/resources.h
-sballs.o: $(UTILS_SRC)/usleep.h
-sballs.o: $(UTILS_SRC)/visual.h
-sballs.o: $(UTILS_SRC)/xshm.h
-sballs.o: $(UTILS_SRC)/yarandom.h
-sballs.o: $(HACK_SRC)/xlockmoreI.h
-sballs.o: $(HACK_SRC)/xlockmore.h
-sballs.o: $(srcdir)/xpm-ximage.h
-shark.o: $(srcdir)/atlantis.h
-shark.o: ../../config.h
-shark.o: $(HACK_SRC)/fps.h
-shark.o: $(HACK_SRC)/screenhackI.h
-shark.o: $(UTILS_SRC)/colors.h
-shark.o: $(UTILS_SRC)/grabscreen.h
-shark.o: $(UTILS_SRC)/hsv.h
-shark.o: $(UTILS_SRC)/resources.h
-shark.o: $(UTILS_SRC)/usleep.h
-shark.o: $(UTILS_SRC)/visual.h
-shark.o: $(UTILS_SRC)/yarandom.h
-sierpinski3d.o: ../../config.h
-sierpinski3d.o: $(HACK_SRC)/fps.h
-sierpinski3d.o: $(srcdir)/gltrackball.h
-sierpinski3d.o: $(srcdir)/rotator.h
-sierpinski3d.o: $(HACK_SRC)/screenhackI.h
-sierpinski3d.o: $(UTILS_SRC)/colors.h
-sierpinski3d.o: $(UTILS_SRC)/grabscreen.h
-sierpinski3d.o: $(UTILS_SRC)/hsv.h
-sierpinski3d.o: $(UTILS_SRC)/resources.h
-sierpinski3d.o: $(UTILS_SRC)/usleep.h
-sierpinski3d.o: $(UTILS_SRC)/visual.h
-sierpinski3d.o: $(UTILS_SRC)/xshm.h
-sierpinski3d.o: $(UTILS_SRC)/yarandom.h
-sierpinski3d.o: $(HACK_SRC)/xlockmoreI.h
-sierpinski3d.o: $(HACK_SRC)/xlockmore.h
-skytentacles.o: ../../config.h
-skytentacles.o: $(HACK_SRC)/fps.h
-skytentacles.o: $(srcdir)/gltrackball.h
-skytentacles.o: $(HACK_SRC)/images/scales.xpm
-skytentacles.o: $(srcdir)/normals.h
-skytentacles.o: $(srcdir)/rotator.h
-skytentacles.o: $(HACK_SRC)/screenhackI.h
-skytentacles.o: $(UTILS_SRC)/colors.h
-skytentacles.o: $(UTILS_SRC)/grabscreen.h
-skytentacles.o: $(UTILS_SRC)/hsv.h
-skytentacles.o: $(UTILS_SRC)/resources.h
-skytentacles.o: $(UTILS_SRC)/usleep.h
-skytentacles.o: $(UTILS_SRC)/visual.h
-skytentacles.o: $(UTILS_SRC)/xshm.h
-skytentacles.o: $(UTILS_SRC)/yarandom.h
-skytentacles.o: $(HACK_SRC)/xlockmoreI.h
-skytentacles.o: $(HACK_SRC)/xlockmore.h
-skytentacles.o: $(srcdir)/xpm-ximage.h
-sonar-icmp.o: ../../config.h
-sonar-icmp.o: $(HACK_SRC)/fps.h
-sonar-icmp.o: $(HACK_SRC)/screenhackI.h
-sonar-icmp.o: $(srcdir)/sonar.h
-sonar-icmp.o: $(UTILS_SRC)/colors.h
-sonar-icmp.o: $(UTILS_SRC)/grabscreen.h
-sonar-icmp.o: $(UTILS_SRC)/hsv.h
-sonar-icmp.o: $(UTILS_SRC)/resources.h
-sonar-icmp.o: $(UTILS_SRC)/usleep.h
-sonar-icmp.o: $(UTILS_SRC)/version.h
-sonar-icmp.o: $(UTILS_SRC)/visual.h
-sonar-icmp.o: $(UTILS_SRC)/yarandom.h
-sonar.o: ../../config.h
-sonar.o: $(HACK_SRC)/fps.h
-sonar.o: $(srcdir)/gltrackball.h
-sonar.o: $(srcdir)/rotator.h
-sonar.o: $(HACK_SRC)/screenhackI.h
-sonar.o: $(srcdir)/sonar.h
-sonar.o: $(srcdir)/texfont.h
-sonar.o: $(UTILS_SRC)/colors.h
-sonar.o: $(UTILS_SRC)/grabscreen.h
-sonar.o: $(UTILS_SRC)/hsv.h
-sonar.o: $(UTILS_SRC)/resources.h
-sonar.o: $(UTILS_SRC)/usleep.h
-sonar.o: $(UTILS_SRC)/visual.h
-sonar.o: $(UTILS_SRC)/xshm.h
-sonar.o: $(UTILS_SRC)/yarandom.h
-sonar.o: $(HACK_SRC)/xlockmoreI.h
-sonar.o: $(HACK_SRC)/xlockmore.h
-sonar-sim.o: ../../config.h
-sonar-sim.o: $(HACK_SRC)/fps.h
-sonar-sim.o: $(HACK_SRC)/screenhackI.h
-sonar-sim.o: $(srcdir)/sonar.h
-sonar-sim.o: $(UTILS_SRC)/colors.h
-sonar-sim.o: $(UTILS_SRC)/grabscreen.h
-sonar-sim.o: $(UTILS_SRC)/hsv.h
-sonar-sim.o: $(UTILS_SRC)/resources.h
-sonar-sim.o: $(UTILS_SRC)/usleep.h
-sonar-sim.o: $(UTILS_SRC)/visual.h
-sonar-sim.o: $(UTILS_SRC)/yarandom.h
-spheremonics.o: ../../config.h
-spheremonics.o: $(HACK_SRC)/fps.h
-spheremonics.o: $(srcdir)/gltrackball.h
-spheremonics.o: $(srcdir)/glxfonts.h
-spheremonics.o: $(srcdir)/normals.h
-spheremonics.o: $(srcdir)/rotator.h
-spheremonics.o: $(HACK_SRC)/screenhackI.h
-spheremonics.o: $(UTILS_SRC)/colors.h
-spheremonics.o: $(UTILS_SRC)/grabscreen.h
-spheremonics.o: $(UTILS_SRC)/hsv.h
-spheremonics.o: $(UTILS_SRC)/resources.h
-spheremonics.o: $(UTILS_SRC)/usleep.h
-spheremonics.o: $(UTILS_SRC)/visual.h
-spheremonics.o: $(UTILS_SRC)/xshm.h
-spheremonics.o: $(UTILS_SRC)/yarandom.h
-spheremonics.o: $(HACK_SRC)/xlockmoreI.h
-spheremonics.o: $(HACK_SRC)/xlockmore.h
-sphere.o: ../../config.h
-sphere.o: $(srcdir)/sphere.h
-sproingies.o: ../../config.h
-sproingies.o: $(HACK_SRC)/fps.h
-sproingies.o: $(srcdir)/gllist.h
-sproingies.o: $(HACK_SRC)/screenhackI.h
-sproingies.o: $(srcdir)/sproingies.h
-sproingies.o: $(UTILS_SRC)/colors.h
-sproingies.o: $(UTILS_SRC)/grabscreen.h
-sproingies.o: $(UTILS_SRC)/hsv.h
-sproingies.o: $(UTILS_SRC)/resources.h
-sproingies.o: $(UTILS_SRC)/usleep.h
-sproingies.o: $(UTILS_SRC)/visual.h
-sproingies.o: $(UTILS_SRC)/xshm.h
-sproingies.o: $(UTILS_SRC)/yarandom.h
-sproingies.o: $(HACK_SRC)/xlockmoreI.h
-sproingiewrap.o: ../../config.h
-sproingiewrap.o: $(HACK_SRC)/fps.h
-sproingiewrap.o: $(HACK_SRC)/screenhackI.h
-sproingiewrap.o: $(srcdir)/sproingies.h
-sproingiewrap.o: $(UTILS_SRC)/colors.h
-sproingiewrap.o: $(UTILS_SRC)/grabscreen.h
-sproingiewrap.o: $(UTILS_SRC)/hsv.h
-sproingiewrap.o: $(UTILS_SRC)/resources.h
-sproingiewrap.o: $(UTILS_SRC)/usleep.h
-sproingiewrap.o: $(UTILS_SRC)/visual.h
-sproingiewrap.o: $(UTILS_SRC)/xshm.h
-sproingiewrap.o: $(UTILS_SRC)/yarandom.h
-sproingiewrap.o: $(HACK_SRC)/xlockmoreI.h
-sproingiewrap.o: $(HACK_SRC)/xlockmore.h
-stairs.o: ../../config.h
-stairs.o: $(srcdir)/e_textures.h
-stairs.o: $(HACK_SRC)/fps.h
-stairs.o: $(srcdir)/gltrackball.h
-stairs.o: $(HACK_SRC)/screenhackI.h
-stairs.o: $(srcdir)/sphere.h
-stairs.o: $(UTILS_SRC)/colors.h
-stairs.o: $(UTILS_SRC)/grabscreen.h
-stairs.o: $(UTILS_SRC)/hsv.h
-stairs.o: $(UTILS_SRC)/resources.h
-stairs.o: $(UTILS_SRC)/usleep.h
-stairs.o: $(UTILS_SRC)/visual.h
-stairs.o: $(UTILS_SRC)/xshm.h
-stairs.o: $(UTILS_SRC)/yarandom.h
-stairs.o: $(HACK_SRC)/xlockmoreI.h
-stairs.o: $(HACK_SRC)/xlockmore.h
-starwars.o: ../../config.h
-starwars.o: $(HACK_SRC)/fps.h
-starwars.o: $(srcdir)/glut_roman.h
-starwars.o: $(srcdir)/glutstroke.h
-starwars.o: $(HACK_SRC)/screenhackI.h
-starwars.o: $(srcdir)/texfont.h
-starwars.o: $(UTILS_SRC)/colors.h
-starwars.o: $(UTILS_SRC)/grabscreen.h
-starwars.o: $(UTILS_SRC)/hsv.h
-starwars.o: $(UTILS_SRC)/resources.h
-starwars.o: $(UTILS_SRC)/usleep.h
-starwars.o: $(UTILS_SRC)/visual.h
-starwars.o: $(UTILS_SRC)/xshm.h
-starwars.o: $(UTILS_SRC)/yarandom.h
-starwars.o: $(HACK_SRC)/xlockmoreI.h
-starwars.o: $(HACK_SRC)/xlockmore.h
-stonerview-move.o: ../../config.h
-stonerview-move.o: $(srcdir)/stonerview.h
-stonerview-move.o: $(srcdir)/stonerview-move.h
-stonerview-move.o: $(srcdir)/stonerview-osc.h
-stonerview-move.o: $(UTILS_SRC)/yarandom.h
-stonerview.o: ../../config.h
-stonerview.o: $(HACK_SRC)/fps.h
-stonerview.o: $(srcdir)/gltrackball.h
-stonerview.o: $(HACK_SRC)/screenhackI.h
-stonerview.o: $(srcdir)/stonerview.h
-stonerview.o: $(srcdir)/stonerview-move.h
-stonerview.o: $(srcdir)/stonerview-osc.h
-stonerview.o: $(UTILS_SRC)/colors.h
-stonerview.o: $(UTILS_SRC)/grabscreen.h
-stonerview.o: $(UTILS_SRC)/hsv.h
-stonerview.o: $(UTILS_SRC)/resources.h
-stonerview.o: $(UTILS_SRC)/usleep.h
-stonerview.o: $(UTILS_SRC)/visual.h
-stonerview.o: $(UTILS_SRC)/xshm.h
-stonerview.o: $(UTILS_SRC)/yarandom.h
-stonerview.o: $(HACK_SRC)/xlockmoreI.h
-stonerview.o: $(HACK_SRC)/xlockmore.h
-stonerview-osc.o: ../../config.h
-stonerview-osc.o: $(srcdir)/stonerview.h
-stonerview-osc.o: $(srcdir)/stonerview-move.h
-stonerview-osc.o: $(srcdir)/stonerview-osc.h
-stonerview-osc.o: $(UTILS_SRC)/yarandom.h
-stonerview-view.o: ../../config.h
-stonerview-view.o: $(srcdir)/stonerview.h
-stonerview-view.o: $(srcdir)/stonerview-move.h
-stonerview-view.o: $(srcdir)/stonerview-osc.h
-superquadrics.o: ../../config.h
-superquadrics.o: $(HACK_SRC)/fps.h
-superquadrics.o: $(HACK_SRC)/screenhackI.h
-superquadrics.o: $(UTILS_SRC)/colors.h
-superquadrics.o: $(UTILS_SRC)/grabscreen.h
-superquadrics.o: $(UTILS_SRC)/hsv.h
-superquadrics.o: $(UTILS_SRC)/resources.h
-superquadrics.o: $(UTILS_SRC)/usleep.h
-superquadrics.o: $(UTILS_SRC)/visual.h
-superquadrics.o: $(UTILS_SRC)/xshm.h
-superquadrics.o: $(UTILS_SRC)/yarandom.h
-superquadrics.o: $(HACK_SRC)/xlockmoreI.h
-superquadrics.o: $(HACK_SRC)/xlockmore.h
-swim.o: $(srcdir)/atlantis.h
-swim.o: ../../config.h
-swim.o: $(HACK_SRC)/fps.h
-swim.o: $(HACK_SRC)/screenhackI.h
-swim.o: $(UTILS_SRC)/colors.h
-swim.o: $(UTILS_SRC)/grabscreen.h
-swim.o: $(UTILS_SRC)/hsv.h
-swim.o: $(UTILS_SRC)/resources.h
-swim.o: $(UTILS_SRC)/usleep.h
-swim.o: $(UTILS_SRC)/visual.h
-swim.o: $(UTILS_SRC)/xshm.h
-swim.o: $(UTILS_SRC)/yarandom.h
-swim.o: $(HACK_SRC)/xlockmoreI.h
-tangram.o: ../../config.h
-tangram.o: $(HACK_SRC)/fps.h
-tangram.o: $(srcdir)/glxfonts.h
-tangram.o: $(HACK_SRC)/screenhackI.h
-tangram.o: $(srcdir)/tangram_shapes.h
-tangram.o: $(UTILS_SRC)/colors.h
-tangram.o: $(UTILS_SRC)/grabscreen.h
-tangram.o: $(UTILS_SRC)/hsv.h
-tangram.o: $(UTILS_SRC)/resources.h
-tangram.o: $(UTILS_SRC)/usleep.h
-tangram.o: $(UTILS_SRC)/visual.h
-tangram.o: $(UTILS_SRC)/xshm.h
-tangram.o: $(UTILS_SRC)/yarandom.h
-tangram.o: $(HACK_SRC)/xlockmoreI.h
-tangram.o: $(HACK_SRC)/xlockmore.h
-tangram_shapes.o: $(srcdir)/tangram_shapes.h
-teapot.o: ../../config.h
-teapot.o: $(srcdir)/teapot.h
-texfont.o: ../../config.h
-texfont.o: $(srcdir)/texfont.h
-texfont.o: $(UTILS_SRC)/resources.h
-timetunnel.o: ../../config.h
-timetunnel.o: $(HACK_SRC)/fps.h
-timetunnel.o: $(srcdir)/gltrackball.h
-timetunnel.o: $(HACK_SRC)/images/timetunnel0.xpm
-timetunnel.o: $(HACK_SRC)/images/timetunnel1.xpm
-timetunnel.o: $(HACK_SRC)/images/timetunnel2.xpm
-timetunnel.o: $(HACK_SRC)/images/tunnelstar.xpm
-timetunnel.o: $(srcdir)/rotator.h
-timetunnel.o: $(HACK_SRC)/screenhackI.h
-timetunnel.o: $(UTILS_SRC)/colors.h
-timetunnel.o: $(UTILS_SRC)/grabscreen.h
-timetunnel.o: $(UTILS_SRC)/hsv.h
-timetunnel.o: $(UTILS_SRC)/images/logo-180.xpm
-timetunnel.o: $(UTILS_SRC)/resources.h
-timetunnel.o: $(UTILS_SRC)/usleep.h
-timetunnel.o: $(UTILS_SRC)/visual.h
-timetunnel.o: $(UTILS_SRC)/xshm.h
-timetunnel.o: $(UTILS_SRC)/yarandom.h
-timetunnel.o: $(HACK_SRC)/xlockmoreI.h
-timetunnel.o: $(HACK_SRC)/xlockmore.h
-timetunnel.o: $(srcdir)/xpm-ximage.h
-toast2.o: $(srcdir)/gllist.h
-toaster_base.o: $(srcdir)/gllist.h
-toaster_handle2.o: $(srcdir)/gllist.h
-toaster_handle.o: $(srcdir)/gllist.h
-toaster_jet.o: $(srcdir)/gllist.h
-toaster_knob.o: $(srcdir)/gllist.h
-toaster.o: $(srcdir)/gllist.h
-toaster_slots.o: $(srcdir)/gllist.h
-toaster_wing.o: $(srcdir)/gllist.h
-toast.o: $(srcdir)/gllist.h
-topblock.o: ../../config.h
-topblock.o: $(HACK_SRC)/fps.h
-topblock.o: $(srcdir)/gltrackball.h
-topblock.o: $(HACK_SRC)/screenhackI.h
-topblock.o: $(srcdir)/sphere.h
-topblock.o: $(srcdir)/topblock.h
-topblock.o: $(UTILS_SRC)/colors.h
-topblock.o: $(UTILS_SRC)/grabscreen.h
-topblock.o: $(UTILS_SRC)/hsv.h
-topblock.o: $(UTILS_SRC)/resources.h
-topblock.o: $(UTILS_SRC)/usleep.h
-topblock.o: $(UTILS_SRC)/visual.h
-topblock.o: $(UTILS_SRC)/xshm.h
-topblock.o: $(UTILS_SRC)/yarandom.h
-topblock.o: $(HACK_SRC)/xlockmoreI.h
-topblock.o: $(HACK_SRC)/xlockmore.h
-trackball.o: ../../config.h
-trackball.o: $(srcdir)/trackball.h
-tube.o: ../../config.h
-tube.o: $(srcdir)/tube.h
-tunnel_draw.o: ../../config.h
-tunnel_draw.o: $(HACK_SRC)/fps.h
-tunnel_draw.o: $(HACK_SRC)/screenhackI.h
-tunnel_draw.o: $(srcdir)/tunnel_draw.h
-tunnel_draw.o: $(UTILS_SRC)/colors.h
-tunnel_draw.o: $(UTILS_SRC)/grabscreen.h
-tunnel_draw.o: $(UTILS_SRC)/hsv.h
-tunnel_draw.o: $(UTILS_SRC)/resources.h
-tunnel_draw.o: $(UTILS_SRC)/usleep.h
-tunnel_draw.o: $(UTILS_SRC)/visual.h
-tunnel_draw.o: $(UTILS_SRC)/xshm.h
-tunnel_draw.o: $(UTILS_SRC)/yarandom.h
-tunnel_draw.o: $(HACK_SRC)/xlockmoreI.h
-voronoi.o: ../../config.h
-voronoi.o: $(HACK_SRC)/fps.h
-voronoi.o: $(HACK_SRC)/screenhackI.h
-voronoi.o: $(UTILS_SRC)/colors.h
-voronoi.o: $(UTILS_SRC)/grabscreen.h
-voronoi.o: $(UTILS_SRC)/hsv.h
-voronoi.o: $(UTILS_SRC)/resources.h
-voronoi.o: $(UTILS_SRC)/usleep.h
-voronoi.o: $(UTILS_SRC)/visual.h
-voronoi.o: $(UTILS_SRC)/xshm.h
-voronoi.o: $(UTILS_SRC)/yarandom.h
-voronoi.o: $(HACK_SRC)/xlockmoreI.h
-voronoi.o: $(HACK_SRC)/xlockmore.h
-whale.o: $(srcdir)/atlantis.h
-whale.o: ../../config.h
-whale.o: $(HACK_SRC)/fps.h
-whale.o: $(HACK_SRC)/screenhackI.h
-whale.o: $(UTILS_SRC)/colors.h
-whale.o: $(UTILS_SRC)/grabscreen.h
-whale.o: $(UTILS_SRC)/hsv.h
-whale.o: $(UTILS_SRC)/resources.h
-whale.o: $(UTILS_SRC)/usleep.h
-whale.o: $(UTILS_SRC)/visual.h
-whale.o: $(UTILS_SRC)/yarandom.h
-xlock-gl-utils.o: ../../config.h
-xlock-gl-utils.o: $(HACK_SRC)/fps.h
-xlock-gl-utils.o: $(srcdir)/glxfonts.h
-xlock-gl-utils.o: $(HACK_SRC)/screenhackI.h
-xlock-gl-utils.o: $(UTILS_SRC)/colors.h
-xlock-gl-utils.o: $(UTILS_SRC)/grabscreen.h
-xlock-gl-utils.o: $(UTILS_SRC)/hsv.h
-xlock-gl-utils.o: $(UTILS_SRC)/resources.h
-xlock-gl-utils.o: $(UTILS_SRC)/usleep.h
-xlock-gl-utils.o: $(UTILS_SRC)/visual.h
-xlock-gl-utils.o: $(UTILS_SRC)/xshm.h
-xlock-gl-utils.o: $(UTILS_SRC)/yarandom.h
-xlock-gl-utils.o: $(HACK_SRC)/xlockmoreI.h
-xpm-ximage.o: ../../config.h
-xpm-ximage.o: $(srcdir)/xpm-ximage.h
-xscreensaver-gl-helper.o: ../../config.h
-xscreensaver-gl-helper.o: $(UTILS_SRC)/utils.h
-xscreensaver-gl-helper.o: $(UTILS_SRC)/visual.h
-
index de7d55e741b262ab40b0d2a2791bff964512f659..b2c6e4bc960f7910a8afd4f4a8f26bdc2a729b61 100644 (file)
@@ -386,8 +386,6 @@ init_ball (ModeInfo *mi)
     bp->des_amt = bp->bscale.wh / MAX_COUNT;
   }
 
-  bp->glx_context = init_GL(mi);
-
   reshape_ball(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
   bp->ballList = glGenLists(1);
   glNewList(bp->ballList, GL_COMPILE);
index 31f45d33dd7113391139a43cb62d7966df4486a6..0dc2a3f8080cc162451e1097602793969d242759 100644 (file)
@@ -1,6 +1,6 @@
 .TH XScreenSaver 1 "" "X Version 11"
 .SH NAME
-blinkbox 
+blinkbox \- shows a ball inside a box.
 .SH SYNOPSIS
 .B blinkbox
 [\-display \fIhost:display.screen\fP]
index 1379b4cf9f36b02735a6574950071d73f470b681..2ca13a127e88718a5d7ab080d5110cee1abc3805 100644 (file)
@@ -57,7 +57,7 @@
 #define DEF_RANDOMIZE   "True"
 #define DEF_SPINSPEED   "1.0"
 #define DEF_ROTSPEED    "3.0"
-#define DEF_WANDERSPEED "1.0"
+#define DEF_WANDERSPEED "0.02"
 #define DEF_WAIT        "40.0"
 #define DEF_CUBESIZE    "0.7"
 #define DEF_COLORMODE   "six"
index 38c0adebb624559c6445834de82712b87f6c2349..ba9cc9219d0569c9c7aac1a204a2c7f0dc7462ce 100644 (file)
@@ -68,16 +68,20 @@ typedef struct _flurry_info_t flurry_info_t;
 
 typedef union {
     float              f[4];
+#if 0
 #if __VEC__
     vector float       v;
 #endif
+#endif /* 0 */
 } floatToVector;
 
 typedef union {
     unsigned int       i[4];
+#if 0
 #if __VEC__
     vector unsigned int        v;
 #endif
+#endif /* 0 */
 } intToVector;
 
 typedef struct SmokeParticleV  
@@ -110,6 +114,7 @@ typedef struct SmokeV
 void InitSmoke(SmokeV *s);
 
 void UpdateSmoke_ScalarBase(global_info_t *global, flurry_info_t *flurry, SmokeV *s);
+#if 0
 #ifdef __ppc__
 void UpdateSmoke_ScalarFrsqrte(global_info_t *global, flurry_info_t *flurry, SmokeV *s);
 #endif
@@ -117,6 +122,7 @@ void UpdateSmoke_ScalarFrsqrte(global_info_t *global, flurry_info_t *flurry, Smo
 void UpdateSmoke_VectorBase(global_info_t *global, flurry_info_t *flurry, SmokeV *s);
 void UpdateSmoke_VectorUnrolled(global_info_t *global, flurry_info_t *flurry, SmokeV *s);
 #endif
+#endif /* 0 */
 
 void DrawSmoke_Scalar(global_info_t *global, flurry_info_t *flurry, SmokeV *s, float);
 void DrawSmoke_Vector(global_info_t *global, flurry_info_t *flurry, SmokeV *s, float);
@@ -171,6 +177,7 @@ static inline float FastDistance2D(float x, float y)
        return(x+y-(mn*0.5f)-(mn*0.25f)+(mn*0.0625f));
 }
 
+#if 0
 #ifdef __VEC__
 
 static vector float FastDistance2DV(vector float x, vector float y) {
@@ -185,6 +192,7 @@ static vector float FastDistance2DV(vector float x, vector float y) {
 }
 
 #endif
+#endif /* 0 */
 
 #define RandFlt(min, max) ((min) + frand((max) - (min)))
 
@@ -196,6 +204,7 @@ void MakeTexture(void);
 
 #define OPT_MODE_SCALAR_BASE           0x0
 
+#if 0
 #ifdef __ppc__
 #define OPT_MODE_SCALAR_FRSQRTE                0x1
 #endif
@@ -204,6 +213,7 @@ void MakeTexture(void);
 #define OPT_MODE_VECTOR_SIMPLE         0x2
 #define OPT_MODE_VECTOR_UNROLLED       0x3
 #endif
+#endif /* 0 */
 
 typedef enum _ColorModes
 {
index 59032aab8d1e66537c96f1ba1597961c49c70685..7680d878e8aa41fb2495d523db4edd6c91dda288 100644 (file)
@@ -1,4 +1,4 @@
-/* fps, Copyright (c) 2001-2008 Jamie Zawinski <jwz@jwz.org>
+/* fps, Copyright (c) 2001-2009 Jamie Zawinski <jwz@jwz.org>
  * Draw a frames-per-second display (Xlib and OpenGL).
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
@@ -44,24 +44,9 @@ xlockmore_gl_fps_init (fps_state *st)
   st->font_dlist = glGenLists ((GLuint) last+1);
   check_gl_error ("glGenLists");
 
-# ifndef HAVE_COCOA
-
-  glXUseXFont (f->fid, first, last-first+1, st->font_dlist + first);
-  check_gl_error ("glXUseXFont");
-
-# else  /* HAVE_COCOA */
-  {
-    AGLContext ctx = aglGetCurrentContext();
-    int afid, face, size;
-    afid = jwxyz_font_info (f->fid, &size, &face);
-
-    if (! aglUseFont (ctx, afid, face, size, 
-                      first, last-first+1, st->font_dlist + first)) {
-      check_gl_error ("aglUseFont");
-      abort();
-    }
-  }
-# endif  /* HAVE_COCOA */
+  xscreensaver_glXUseXFont (st->dpy, f->fid,
+                            first, last-first+1, st->font_dlist + first);
+  check_gl_error ("xscreensaver_glXUseXFont");
 }
 
 
index 6ac0d1bcfad120a64e622316f47f17f441729872..9f1df0ed2fae61a5940f1472fe88160fbde594b9 100644 (file)
@@ -1,5 +1,5 @@
 /* -*- Mode: C; tab-width: 4 -*- */
-/* glhanoi, Copyright (c) 2005 Dave Atkinson <dave.atkinson@uwe.ac.uk>
+/* glhanoi, Copyright (c) 2005, 2009 Dave Atkinson <da@davea.org.uk>
  * except noise function code Copyright (c) 2002 Ken Perlin
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
@@ -146,8 +146,7 @@ typedef struct {
        int drag_x;
        int drag_y;
        int noise_initted;
-
-        int p[512];
+       int p[512];
 
 } glhcfg;
 
@@ -275,10 +274,18 @@ static void moveSetup(glhcfg *glhanoi, Disk * disk)
        int dst = glhanoi->dst;
        GLfloat theta;
        GLfloat sintheta, costheta;
+       double absx;
 
-       if(glhanoi->state != FINISHED && random() % 6 == 0) {
-               disk->rotAngle =
-                       -180.0 * (2 - 2 * random() % 2) * (random() % 3 + 1);
+       if(glhanoi->state != FINISHED) {
+               double xxx = -180.0 * (dst - src >= 0 ? 1.0 : -1.0);
+               if(random() % 6 == 0) {
+                       disk->rotAngle = xxx * (2 - 2 * random() % 2) * (random() % 3 + 1);
+               } else {
+                       disk->rotAngle = xxx;
+               }
+               if(random() % 4 == 0) {
+                       disk->rotAngle = -disk->rotAngle;
+               }
        } else {
                disk->rotAngle = -180.0;
        }
@@ -292,16 +299,12 @@ static void moveSetup(glhcfg *glhanoi, Disk * disk)
        disk->xmin = glhanoi->poleOffset * (src - 1);
        disk->xmax = glhanoi->poleOffset * (dst - 1);
        disk->ymin = glhanoi->poleHeight;
-       ymax =
-               glhanoi->poleHeight + fabs(disk->xmax -
-                                                                  disk->xmin) * (glhanoi->state ==
-                                                                                                 FINISHED ? 1.0 +
-                                                                                                 (double)(glhanoi->
-                                                                                                                  numberOfDisks -
-                                                                                                                  disk->id) /
-                                                                                                 (double)glhanoi->
-                                                                                                 numberOfDisks : 1.0);
 
+       absx = fabs(disk->xmax - disk->xmin);
+       ymax = glhanoi->poleHeight + absx;
+       if(glhanoi->state == FINISHED) {
+               ymax += absx * (double)(glhanoi->numberOfDisks - disk->id);
+       }
        h = ymax - disk->ymin;
        theta = atan((disk->xmin - disk->xmax) * A(disk->xmin, disk->xmax, h));
        if(theta < 0.0)
@@ -359,7 +362,7 @@ static void parafunc(GLdouble t, Disk * d)
        d->position[1] = d->ymin + (d->usintheta - 0.5 * g * t) * t;
 
        d->rotation[1] =
-               d->rotAngle * (d->position[0] - d->xmin) / (d->xmax - d->xmin);
+       d->rotAngle * (d->position[0] - d->xmin) / (d->xmax - d->xmin);
 }
 
 static void downfunc(GLdouble t, Disk * d)
@@ -944,15 +947,19 @@ static double improved_noise(glhcfg *glhanoi, double x, double y, double z)
        x -= floor(x);                          /* FIND RELATIVE X,Y,Z */
        y -= floor(y);                          /* OF POINT IN CUBE. */
        z -= floor(z);
-       u = fade(x),                            /* COMPUTE FADE CURVES */
-               v = fade(y),                    /* FOR EACH OF X,Y,Z. */
-               w = fade(z);
-       A = glhanoi->p[X] + Y, AA = glhanoi->p[A] + Z, AB = glhanoi->p[A + 1] + Z,      /* HASH COORDINATES OF */
-               B = glhanoi->p[X + 1] + Y, BA = glhanoi->p[B] + Z, BB = glhanoi->p[B + 1] + Z;  /* THE 8 CUBE CORNERS, */
-       return lerp(w, lerp(v, lerp(u, grad(glhanoi->p[AA], x, y, z),   /* AND ADD */
-                                                               grad(glhanoi->p[BA], x - 1, y, z)),     /* BLENDED */
-                                               lerp(u, grad(glhanoi->p[AB], x, y - 1, z),      /* RESULTS */
-                                                        grad(glhanoi->p[BB], x - 1, y - 1, z))),       /* FROM 8 CORNERS */
+       u  = fade(x),                           /* COMPUTE FADE CURVES */
+       v  = fade(y),                           /* FOR EACH OF X,Y,Z. */
+       w  = fade(z);
+       A  = glhanoi->p[X] + Y;
+       AA = glhanoi->p[A] + Z;
+       AB = glhanoi->p[A + 1] + Z,     /* HASH COORDINATES OF */
+       B  = glhanoi->p[X + 1] + Y;
+       BA = glhanoi->p[B] + Z;
+       BB = glhanoi->p[B + 1] + Z;     /* THE 8 CUBE CORNERS, */
+       return lerp(w, lerp(v, lerp(u, grad(glhanoi->p[AA], x, y, z),/* AND ADD */
+                                                               grad(glhanoi->p[BA], x - 1, y, z)),/* BLENDED */
+                                               lerp(u, grad(glhanoi->p[AB], x, y - 1, z),/* RESULTS */
+                                                        grad(glhanoi->p[BB], x - 1, y - 1, z))),/* FROM 8 CORNERS */
                                lerp(v, lerp(u, grad(glhanoi->p[AA + 1], x, y, z - 1), grad(glhanoi->p[BA + 1], x - 1, y, z - 1)),      /* OF CUBE */
                                         lerp(u, grad(glhanoi->p[AB + 1], x, y - 1, z - 1),
                                                  grad(glhanoi->p[BB + 1], x - 1, y - 1, z - 1))));
@@ -1003,16 +1010,25 @@ static GLubyte *makeTexture(glhcfg *glhanoi, int x_size, int y_size, int z_size,
        return textureData;
 }
 
-static tex_col_t makeMarbleColours(void)
+static void freeTexCols(tex_col_t*p)
+{
+       free(p->colours);
+       free(p);
+}
+
+static tex_col_t *makeMarbleColours(void)
 {
-       tex_col_t marbleColours;
+       tex_col_t *marbleColours;
        int ncols = 2;
 
-       marbleColours.colours = calloc(sizeof(GLuint), ncols);
-       marbleColours.ncols = ncols;
+       marbleColours = malloc(sizeof(tex_col_t));
+       if(marbleColours == NULL) return NULL;
+       marbleColours->colours = calloc(sizeof(GLuint), ncols);
+       if(marbleColours->colours == NULL) return NULL;
+       marbleColours->ncols = ncols;
 
-       marbleColours.colours[0] = 0x3f3f3f3f;
-       marbleColours.colours[1] = 0xffffffff;
+       marbleColours->colours[0] = 0x3f3f3f3f;
+       marbleColours->colours[1] = 0xffffffff;
 
        return marbleColours;
 }
@@ -1079,14 +1095,16 @@ static void setTexture(glhcfg *glhanoi, int n)
 static int makeTextures(glhcfg *glhanoi)
 {
        GLubyte *marbleTexture;
-       tex_col_t marbleColours;
+       tex_col_t *marbleColours;
 
        glGenTextures(N_TEXTURES, glhanoi->textureNames);
 
-       marbleColours = makeMarbleColours();
+       if((marbleColours = makeMarbleColours()) == NULL) {
+               return 1;
+       }
        if((marbleTexture =
                makeTexture(glhanoi, MARBLE_TEXTURE_SIZE, MARBLE_TEXTURE_SIZE, 1,
-                                       makeMarbleTexture, &marbleColours)) == NULL) {
+                                       makeMarbleTexture, marbleColours)) == NULL) {
                return 1;
        }
 
@@ -1099,6 +1117,7 @@ static int makeTextures(glhcfg *glhanoi)
                                 MARBLE_TEXTURE_SIZE, MARBLE_TEXTURE_SIZE, 0,
                                 GL_RGBA, GL_UNSIGNED_BYTE, marbleTexture);
        free(marbleTexture);
+       freeTexCols(marbleColours);
 
        return 0;
 }
@@ -1173,7 +1192,6 @@ static void initTowers(glhcfg *glhanoi)
                                     glhanoi->baseHeight);
        glEndList();
 
-
        if((glhanoi->poleList = glGenLists(1)) == 0) {
                fprintf(stderr, "can't allocate memory for towers display list\n");
                exit(EXIT_FAILURE);
@@ -1332,10 +1350,10 @@ ENTRYPOINT void init_glhanoi(ModeInfo * mi)
     if (glhanoi->numberOfDisks <= 1)
       glhanoi->numberOfDisks = 3 + (int) BELLRAND(9);
 
-    /* magicnumber is a bitfield, so we can't have more than 31 discs
-       on a system with 4-byte ints. */
-    if (glhanoi->numberOfDisks >= 8 * sizeof(int))
-      glhanoi->numberOfDisks = (8 * sizeof(int)) - 1;
+       /* magicnumber is a bitfield, so we can't have more than 31 discs
+          on a system with 4-byte ints. */
+       if (glhanoi->numberOfDisks >= 8 * sizeof(int))
+               glhanoi->numberOfDisks = (8 * sizeof(int)) - 1;
 
        glhanoi->maxDiskIdx = glhanoi->numberOfDisks - 1;
        glhanoi->wire = MI_IS_WIREFRAME(mi);
@@ -1385,7 +1403,7 @@ ENTRYPOINT void init_glhanoi(ModeInfo * mi)
 
 ENTRYPOINT void draw_glhanoi(ModeInfo * mi)
 {
-        glhcfg *glhanoi = &glhanoi_cfg[MI_SCREEN(mi)];
+       glhcfg *glhanoi = &glhanoi_cfg[MI_SCREEN(mi)];
        Display *dpy = MI_DISPLAY(mi);
        Window window = MI_WINDOW(mi);
 
index 55ee7f515f3cfa0eb5277328f81da6919c39777b..9197af975b2f69ecb4ab8e4e8fb7f0395ff615d1 100644 (file)
@@ -1,4 +1,4 @@
-/* glxfonts, Copyright (c) 2001-2008 Jamie Zawinski <jwz@jwz.org>
+/* glxfonts, Copyright (c) 2001-2009 Jamie Zawinski <jwz@jwz.org>
  * Loads X11 fonts for use with OpenGL.
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
@@ -46,6 +46,221 @@ extern char *progname;
                */
 
 
+/* Mostly lifted from the Mesa implementation of glXUseXFont(), since
+   Mac OS 10.6 no longer supports aglUseFont() which was their analog
+   of that.  This code could be in libjwxyz instead, but we might as
+   well use the same text-drawing code on both X11 and Cocoa.
+ */
+static void
+fill_bitmap (Display *dpy, Window win, GC gc,
+            unsigned int width, unsigned int height,
+            int x0, int y0, char c, GLubyte *bitmap)
+{
+  XImage *image;
+  int x, y;
+  Pixmap pixmap;
+
+  pixmap = XCreatePixmap (dpy, win, 8*width, height, 1);
+  XSetForeground(dpy, gc, 0);
+  XFillRectangle (dpy, pixmap, gc, 0, 0, 8*width, height);
+  XSetForeground(dpy, gc, 1);
+  XDrawString (dpy, pixmap, gc, x0, y0, &c, 1);
+
+  image = XGetImage (dpy, pixmap, 0, 0, 8*width, height, 1, XYPixmap);
+
+  /* Fill the bitmap (X11 and OpenGL are upside down wrt each other).  */
+  for (y = 0; y < height; y++)
+    for (x = 0; x < 8*width; x++)
+      if (XGetPixel (image, x, y))
+       bitmap[width*(height - y - 1) + x/8] |= (1 << (7 - (x % 8)));
+  
+  XFreePixmap (dpy, pixmap);
+  XDestroyImage (image);
+}
+
+
+#if 0
+static void
+dump_bitmap (unsigned int width, unsigned int height, GLubyte *bitmap)
+{
+  int x, y;
+
+  printf ("    ");
+  for (x = 0; x < 8*width; x++)
+    printf ("%o", 7 - (x % 8));
+  putchar ('\n');
+  for (y = 0; y < height; y++)
+    {
+      printf ("%3o:", y);
+      for (x = 0; x < 8*width; x++)
+        putchar ((bitmap[width*(height - y - 1) + x/8] & (1 << (7 - (x % 8))))
+                ? '#' : '.');
+      printf ("   ");
+      for (x = 0; x < width; x++)
+       printf ("0x%02x, ", bitmap[width*(height - y - 1) + x]);
+      putchar ('\n');
+    }
+}
+#endif
+
+
+void
+xscreensaver_glXUseXFont (Display *dpy, Font font, 
+                          int first, int count, int listbase)
+{
+  Window win = RootWindowOfScreen (DefaultScreenOfDisplay (dpy));
+  Pixmap pixmap;
+  GC gc;
+  XGCValues values;
+  unsigned long valuemask;
+
+  XFontStruct *fs;
+
+  GLint swapbytes, lsbfirst, rowlength;
+  GLint skiprows, skippixels, alignment;
+
+  unsigned int max_width, max_height, max_bm_width, max_bm_height;
+  GLubyte *bm;
+
+  int i;
+
+  fs = XQueryFont (dpy, font);  
+  if (!fs)
+    {
+      /*gl_error (CC->gl_ctx, GL_INVALID_VALUE,
+               "Couldn't get font structure information");*/
+      abort();
+      return;
+    }
+
+  /* Allocate a bitmap that can fit all characters.  */
+  max_width = fs->max_bounds.rbearing - fs->min_bounds.lbearing;
+  max_height = fs->max_bounds.ascent + fs->max_bounds.descent;
+  max_bm_width = (max_width + 7) / 8;
+  max_bm_height = max_height;
+
+  bm = (GLubyte *) malloc ((max_bm_width * max_bm_height) * sizeof (GLubyte));
+  if (!bm)
+    {
+      /*gl_error (CC->gl_ctx, GL_OUT_OF_MEMORY,
+               "Couldn't allocate bitmap in glXUseXFont()");*/
+      abort();
+      return;
+    }
+
+  /* Save the current packing mode for bitmaps.  */
+  glGetIntegerv        (GL_UNPACK_SWAP_BYTES, &swapbytes);
+  glGetIntegerv        (GL_UNPACK_LSB_FIRST, &lsbfirst);
+  glGetIntegerv        (GL_UNPACK_ROW_LENGTH, &rowlength);
+  glGetIntegerv        (GL_UNPACK_SKIP_ROWS, &skiprows);
+  glGetIntegerv        (GL_UNPACK_SKIP_PIXELS, &skippixels);
+  glGetIntegerv        (GL_UNPACK_ALIGNMENT, &alignment);
+
+  /* Enforce a standard packing mode which is compatible with
+     fill_bitmap() from above.  This is actually the default mode,
+     except for the (non)alignment.  */
+  glPixelStorei        (GL_UNPACK_SWAP_BYTES, GL_FALSE);
+  glPixelStorei        (GL_UNPACK_LSB_FIRST, GL_FALSE);
+  glPixelStorei        (GL_UNPACK_ROW_LENGTH, 0);
+  glPixelStorei        (GL_UNPACK_SKIP_ROWS, 0);
+  glPixelStorei        (GL_UNPACK_SKIP_PIXELS, 0);
+  glPixelStorei        (GL_UNPACK_ALIGNMENT, 1);
+
+  pixmap = XCreatePixmap (dpy, win, 10, 10, 1);
+  values.foreground = 0;
+  values.background = 1;
+  values.font = fs->fid;
+  valuemask = GCForeground | GCBackground | GCFont;
+  gc = XCreateGC (dpy, pixmap, valuemask, &values);
+  XFreePixmap (dpy, pixmap);
+
+# ifdef HAVE_COCOA
+  /* Anti-aliasing of fonts looks like crap with 1-bit bitmaps.
+     It would be nice if we were using full-depth bitmaps, so
+     that the text showed up anti-aliased on screen, but
+     glBitmap() doesn't work that way. */
+  jwxyz_XSetAntiAliasing (dpy, gc, False);
+# endif
+
+  for (i = 0; i < count; i++)
+    {
+      unsigned int width, height, bm_width, bm_height;
+      GLfloat x0, y0, dx, dy;
+      XCharStruct *ch;
+      int x, y;
+      int c = first + i;
+      int list = listbase + i;
+
+      if (fs->per_char
+         && (c >= fs->min_char_or_byte2) && (c <= fs->max_char_or_byte2))
+       ch = &fs->per_char[c-fs->min_char_or_byte2];
+      else
+       ch = &fs->max_bounds;
+
+      /* I'm not entirely clear on why this is necessary on OSX, but
+         without it, the characters are clipped.  And it does not hurt
+         under real X11.  -- jwz. */
+      ch->lbearing--;
+      ch->ascent++;
+
+      /* glBitmap()'s parameters:
+         "Bitmap parameters xorig, yorig, width, and height are
+         computed from font metrics as descent-1, -lbearing,
+         rbearing-lbearing, and ascent+descent, respectively. 
+         xmove is taken from the glyph's width metric, and 
+         ymove is set to zero. Finally, the glyph's image is 
+         converted to the appropriate format for glBitmap."
+      */
+      width = ch->rbearing - ch->lbearing;
+      height = ch->ascent + ch->descent;
+      x0 = - ch->lbearing;
+      y0 = ch->descent - 1;
+      dx = ch->width;
+      dy = 0;
+
+      /* X11's starting point.  */
+      x = - ch->lbearing;
+      y = ch->ascent;
+      
+      /* Round the width to a multiple of eight.  We will use this also
+        for the pixmap for capturing the X11 font.  This is slightly
+        inefficient, but it makes the OpenGL part real easy.  */
+      bm_width = (width + 7) / 8;
+      bm_height = height;
+
+      glNewList (list, GL_COMPILE);
+        if ((c >= fs->min_char_or_byte2) && (c <= fs->max_char_or_byte2)
+           && (bm_width > 0) && (bm_height > 0))
+         {
+           memset (bm, '\0', bm_width * bm_height);
+           fill_bitmap (dpy, win, gc, bm_width, bm_height, x, y, c, bm);
+           glBitmap (width, height, x0, y0, dx, dy, bm);
+#if 0
+            printf ("width/height = %d/%d\n", width, height);
+            printf ("bm_width/bm_height = %d/%d\n", bm_width, bm_height);
+            dump_bitmap (bm_width, bm_height, bm);
+#endif
+         }
+       else
+         glBitmap (0, 0, 0.0, 0.0, dx, dy, NULL);
+      glEndList ();
+    }
+
+  free (bm);
+  XFreeFontInfo( NULL, fs, 0 );
+  XFreeGC (dpy, gc);
+
+  /* Restore saved packing modes.  */    
+  glPixelStorei(GL_UNPACK_SWAP_BYTES, swapbytes);
+  glPixelStorei(GL_UNPACK_LSB_FIRST, lsbfirst);
+  glPixelStorei(GL_UNPACK_ROW_LENGTH, rowlength);
+  glPixelStorei(GL_UNPACK_SKIP_ROWS, skiprows);
+  glPixelStorei(GL_UNPACK_SKIP_PIXELS, skippixels);
+  glPixelStorei(GL_UNPACK_ALIGNMENT, alignment);
+}
+
+
+
 /* Loads the font named by the X resource "res".
    Returns an XFontStruct.
    Also converts the font to a set of GL lists and returns the first list.
@@ -95,39 +310,15 @@ load_font (Display *dpy, char *res, XFontStruct **font_ret, GLuint *dlist_ret)
   last = f->max_char_or_byte2;
   
 
-# ifndef HAVE_COCOA /* Xlib version */
-
   if (dlist_ret)
     {
       clear_gl_error ();
       *dlist_ret = glGenLists ((GLuint) last+1);
       check_gl_error ("glGenLists");
-      glXUseXFont(id, first, last-first+1, *dlist_ret + first);
-      check_gl_error ("glXUseXFont");
-    }
-
-# else  /* HAVE_COCOA */
-
-  {
-    int afid, face, size;
-    afid = jwxyz_font_info (id, &size, &face);
-
-    if (dlist_ret)
-      {
-        clear_gl_error ();
-        *dlist_ret = glGenLists ((GLuint) last+1);
-        check_gl_error ("glGenLists");
-
-        AGLContext ctx = aglGetCurrentContext();
-        if (! aglUseFont (ctx, afid, face, size, 
-                          first, last-first+1, *dlist_ret + first)) {
-          check_gl_error ("aglUseFont");
-          abort();
-      }
+      xscreensaver_glXUseXFont(dpy, id, first, last-first+1,
+                               *dlist_ret + first);
+      check_gl_error ("xscreensaver_glXUseXFont");
     }
-  }
-
-# endif  /* HAVE_COCOA */
 
   if (font_ret)
     *font_ret = f;
index 75107909af1666e2cd65225988095e273aa66f6a..1bffc54837cfb758e7af1dda5561dc9f2dd462b1 100644 (file)
@@ -1,4 +1,4 @@
-/* glxfonts, Copyright (c) 2001-2008 Jamie Zawinski <jwz@jwz.org>
+/* glxfonts, Copyright (c) 2001-2009 Jamie Zawinski <jwz@jwz.org>
  * Loads X11 fonts for use with OpenGL.
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
@@ -9,12 +9,18 @@
  * software for any purpose.  It is provided "as is" without express or 
  * implied warranty.
  *
- * Compute normal vectors for arbitrary triangles.
+ * Loads X11 fonts for use with OpenGL.
  */
 
 #ifndef __GLXFONTS_H__
 #define __GLXFONTS_H__
 
+/* This is basically the same as glXUseXFont().
+   We have our own version of it for portability.
+ */
+extern void xscreensaver_glXUseXFont (Display *dpy, Font font, 
+                                      int first, int count, int listbase);
+
 /* Loads the font named by the X resource "res".
    Returns an XFontStruct.
    Also converts the font to a set of GL lists and returns the first list.
index 9fca3c811eccff0e2f1fddabeae93e9f52c6a3a2..653fe4ba9a322ce33d1ee884ee3e4479e9e61c3d 100644 (file)
@@ -141,7 +141,6 @@ convert_ximage_to_rgba32 (Screen *screen, XImage *image)
   unsigned int srpos=0, sgpos=0, sbpos=0;
   unsigned int srmsk=0, sgmsk=0, sbmsk=0;
   unsigned int srsiz=0, sgsiz=0, sbsiz=0;
-  int i;
   XColor *colors = 0;
   unsigned char spread_map[3][256];
 
@@ -193,6 +192,7 @@ convert_ximage_to_rgba32 (Screen *screen, XImage *image)
 
   if (colors == 0)  /* truecolor */
     {
+      int i;
       for (i = 0; i < 256; i++)
         {
           spread_map[0][i] = spread_bits (i, srsiz);
index cdf6187a502c4db9c68de40b4cf9457d19a136e8..5697ed263af32c44e98aed77dde5e2e6320627c5 100644 (file)
-/* Juggler3D, Copyright (c) 2005-2008 Brian Apps <brian@jugglesaver.co.uk>
+/* juggle, Copyright (c) 1996-2009 Tim Auckland <tda10.geo@yahoo.com>
+ * and Jamie Zawinski <jwz@jwz.org>
  *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that copyright
- * notice and this permission notice appear in supporting documentation.  No
- * representations are made about the suitability of this software for any
- * purpose.  It is provided "as is" without express or implied warranty. */
-
-#undef countof
-#define countof(x) (sizeof((x))/sizeof((*x)))
-
-#define DEFAULTS    \
-    "*delay: 20000\n*showFPS: False\n*wireframe: False\n"
-
-# define refresh_juggler3d 0
-# define release_juggler3d 0
-#include "xlockmore.h"
-#include "gltrackball.h"
-
-#ifdef USE_GL /* whole file */
-
-/* A selection of macros to make functions from math.h return single precision
- * numbers.  Arguably it's better to work at a higher precision and cast it
- * back but littering the code with casts makes it less readable -- without
- * the casts you can get tons of warnings from the compiler (particularily
- * MSVC which enables loss of precision warnings by default) */
-#define cosf(a) (float)(cos((a)))
-#define sinf(a) (float)(sin((a)))
-#define tanf(a) (float)(tan((a)))
-#define sqrtf(a) (float)(sqrt((a)))
-#define powf(a, b) (float)(pow((a), (b)))
-
-#undef max
-#undef min
+ * 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.
+ *
+ * NOTE: this program was originally called "juggle" and was 2D Xlib.
+ *       There was another program called "juggler3d" that was OpenGL.
+ *       In 2009, jwz converted "juggle" to OpenGL and renamed
+ *       "juggle" to "juggler3d".  The old "juggler3d" hack is gone.
+ *
+ * Revision History
+ * 09-Aug-2009: jwz: converted from Xlib to OpenGL.
+ * 13-Dec-2004: [TDA] Use -cycles and -count in a rational manner.
+ *              Add -rings, -bballs.  Add -describe.  Finally made
+ *              live pattern updates possible.  Add refill_juggle(),
+ *              change_juggle() and reshape_juggle().  Make
+ *              init_juggle() non-destructive.  Reorder erase/draw
+ *              operations.  Update xscreensaver xml and manpage.
+ * 15-Nov-2004: [TDA] Fix all memory leaks.
+ * 12-Nov-2004: [TDA] Add -torches and another new trail
+ *              implementation, so that different objects can have
+ *              different length trails.
+ * 11-Nov-2004: [TDA] Clap when all the balls are in the air.
+ * 10-Nov-2004: [TDA] Display pattern name converted to hight
+ *              notation.
+ * 31-Oct-2004: [TDA] Add -clubs and new trail implementation.
+ * 02-Sep-2003: Non-real time to see what is happening without a
+ *              strobe effect for slow machines.
+ * 01-Nov-2000: Allocation checks
+ * 1996: Written
+ */
 
-#define max(a, b) ((a) > (b) ? (a) : (b))
-#define min(a, b) ((a) < (b) ? (a) : (b))
+/*-
+ * TODO
+ * Implement the anonymously promised -uni option.
+ */
 
 
-/******************************************************************************
+/*
+ * Notes on Adam Chalcraft Juggling Notation (used by permission)
+ * a-> Adam's notation  s-> Site swap (Cambridge) notation
  *
- * The code is broadly split into the following parts:
+ * To define a map from a-notation to s-notation ("site-swap"), both
+ * of which look like doubly infinite sequences of natural numbers. In
+ * s-notation, there is a restriction on what is allowed, namely for
+ * the sequence s_n, the associated function f(n)=n+s_n must be a
+ * bijection. In a-notation, there is no restriction.
  *
- *  - Engine.  The process of determining the position of the juggler and 
- *        objects being juggled at an arbitrary point in time.  This is
- *        independent from any drawing code.
- *  - Sites.  The process of creating a random site swap pattern or parsing
- *        a Juggle Saver compatible siteswap for use by the engine.  For an
- *        introduction to juggling site swaps check out
- *         http://www.jugglingdb.com/
- *  - Rendering.  OpenGL drawing code that animates the juggler.
- *  - XScreenSaver.  Interface code to get thing working as a GLX hack.
- *  
- *****************************************************************************/
-
-
-/*****************************************************************************
+ * To go from a-notation to s-notation, you start by mapping each a_n
+ * to a permutation of N, the natural numbers.
  *
- * Data structures
+ * 0 -> the identity
+ * 1 -> (10) [i.e. f(1)=0, f(0)=1]
+ * 2 -> (210) [i.e. f(2)=1, f(1)=0, f(0)=2]
+ * 3 -> (3210) [i.e. f(3)=2, f(2)=1, f(1)=0, f(0)=3]
+ * etc.
  *
- *****************************************************************************/
-
-/* POS is used to represent the position of a hand when it catches or throws
- * an object; as well as the orientation of the object.  The rotation and
- * elevation are specified in degrees.  These angles are not normalised so that
- * it is possible to specify how the object spins and rotates as it is thrown
- * from the 'From' position to the 'To' position.
- * 
- * Because this is the position of the hand some translation is required with
- * rings and clubs to get the centre of rotation position. */
-
-typedef struct
-{
-    float x;
-    float y;
-    float z;
-    float Rot;
-    float Elev;
-} POS;
-
-
-/* An array of THROW_INFOs are configured with each entry corresponding to the
- * position in the site swap (In fact we double up odd length patterns to ensure
- * there is left/right symmetry).  It allows us to quickly determine where an
- * object and the hands are at a given time.  The information is specified in
- * terms of throws, and positions where throws aren't present (0's and 2's) are
- * simply ignored.
- * 
- * TotalTime - The count of beats before this object is thrown again.  Typically
- *    this is the same as the weight of the throw but where an object is held it
- *    is longer.  e.g. the first throw of the site 64242.7. will be 10, 6 for
- *    throw and 4 (two 2's) for the carry.
- * TimeInAir - The weight of the throw.
- * PrevThrow - zero based index into array of THROW_INFOs of the previous throw.
- *     e.g. for the throw '8' in the site 345678..... the PrevThrow is 1
- *    (i.e. the 4)
- * FromPos, FromVelocity, ToPos, ToVelocity - The position and speeds at the
- *    start and end of the throw.  These are used to generate a spline while
- *    carrying an object and while moving the hand from a throw to a catch.
- * NextForHand - Number of beats before the hand that throws this object will
- *    throw another object.  This is always going to be at least 2.  When there
- *    are gaps in the pattern (0's) or holds (2's) NextForHand increases. */
-
-typedef struct
-{
-    int TotalTime;
-    int TimeInAir;
-    int PrevThrow;
-
-    POS FromPos;
-    POS FromVelocity;
-    POS ToPos;
-    POS ToVelocity;
-
-    int NextForHand;
-} THROW_INFO;
-
-
-/* OBJECT_POSITION works with the array of THROW_INFOs to allow us to determine
- * exactly where an object or hand is.
+ * Then for each n, you look at how long 0 takes to get back to 0
+ * again and you call this t_n. If a_n=0, for example, then since the
+ * identity leaves 0 alone, it gets back to 0 in 1 step, so t_n=1. If
+ * a_n=1, then f(0)=1. Now any further a_n=0 leave 1 alone, but the
+ * next a_n>0 sends 1 back to 0. Hence t_n is 2 + the number of 0's
+ * following the 1. Finally, set s_n = t_n - 1.
  *
- * TimeOffset - The total number of beats expired when the object was thrown.
- * ThrowIndex - The zero based index into the THROW_INFO array for the current
- *     throw.
- * ObjectType - One of the OBJECT_XX defines.
- * TotalTwist - Only relevant for OBJECT_BALL, this is the total amount the ball
- *     has twisted while in the air.  When segmented balls are drawn you see a 
- *     spinning effect similar to what happens when you juggle beanbags.  */
-
-#define OBJECT_DEFAULT 0
-#define OBJECT_BALL 1
-#define OBJECT_CLUB 2
-#define OBJECT_RING 3
-
-typedef struct
-{
-    int TimeOffset;
-    int ThrowIndex;
-    float TotalTwist;
-    int ObjectType;
-} OBJECT_POSITION;
-
-
-/* PATTERN_INFO is the main structure that holds the information about a 
- * juggling pattern. 
+ * To give some examples, it helps to have a notation for cyclic
+ * sequences. By (123), for example, I mean ...123123123123... . Now
+ * under the a-notation -> s-notation mapping we have some familiar
+ * examples:
  *
- * pThrowInfo is an array of ThrowLen elements that describes each throw in the
- *     pattern.
- * pObjectInfo gives the current position of all objects at a given instant.
- *     These values are updated as the pattern is animated.
- * LeftHand and RightHand describe the current positions of each of the 
- *     juggler's hands.
- * MaxWeight is the maximum weight of the all throws in pThrowInfo.
- * Height and Alpha are parameters that describe how objects fall under the
- *     influence of gravity.  See SetHeightAndAlpha() for the gory details. */
-
-typedef struct
-{
-    THROW_INFO* pThrowInfo;
-    int ThrowLen;
-    
-    OBJECT_POSITION* pObjectInfo;
-    int Objects;
-
-    OBJECT_POSITION LeftHand;
-    OBJECT_POSITION RightHand;
-    
-    int MaxWeight;
-
-    float Height;
-    float Alpha;
-} PATTERN_INFO;
-
-
-/* EXT_SITE_INFO is used to initialise a PATTERN_INFO object using a Juggle
- * Saver compatible site swap.  These contain additional information about the
- * type of object thrown, the positions of throw and catch etc. */
-
-#define HAS_FROM_POS 1
-#define HAS_TO_POS 2
-#define HAS_SNATCH 4
-#define HAS_SPINS 8
-
-typedef struct
-{
-    unsigned Flags;
-    int Weight;
-    int ObjectType;
-    POS FromPos;
-    POS ToPos;
-    float SnatchX;
-    float SnatchY;
-    int Spins;
-} EXT_SITE_INFO;
-
-
-/* RENDER_STATE is used to co-ordinate the OpenGL rendering of the juggler and
- * objects:
- * pPattern - The pattern to be juggled
- * CameraElev - The elevation angle (in degrees) that the camera is looking
- *    along.  0 is horizontal and a +ve angle is looking down.  This value
- *    should be between -90 and +90.
- * AspectRatio - Window width to height ratio.
- * DLStart - The number for the first display list created, any others directly
- *    follow this.
- * Time - Animation time (in beats)
- * TranslateAngle - Cumulative translation (in degrees) for the juggling figure.
- * SpinAngle- Cumulative spin (in degrees) for the juggling figure.
- */
-
-typedef struct
-{
-    PATTERN_INFO* pPattern;
-    float CameraElev;
-    float AspectRatio;
-    int DLStart;
-    
-    float Time;
-    float TranslateAngle;
-    float SpinAngle;
-    
-    trackball_state *trackball;
-    Bool button_down_p;
-
-} RENDER_STATE;
-
-
-/*****************************************************************************
+ * (0)->(0), (1)->(1), (2)->(2) etc.
+ * (21)->(31), (31)->(51), (41)->(71) etc.
+ * (10)->(20), (20)->(40), (30)->(60) etc.
+ * (331)->(441), (312)->(612), (303)->(504), (321)->(531)
+ * (43)->(53), (434)->(534), (433)->(633)
+ * (552)->(672)
+ *
+ * In general, the number of balls is the *average* of the s-notation,
+ * and the *maximum* of the a-notation. Another theorem is that the
+ * minimum values in the a-notation and the s-notation and equal, and
+ * preserved in the same positions.
+ *
+ * The usefulness of a-notation is the fact that there are no
+ * restrictions on what is allowed. This makes random juggle
+ * generation much easier. It also makes enumeration very
+ * easy. Another handy feature is computing changes.  Suppose you can
+ * do (5) and want a neat change up to (771) in s-notation [Mike Day
+ * actually needed this example!]. Write them both in a-notation,
+ * which gives (5) and (551). Now concatenate them (in general, there
+ * may be more than one way to do this, but not in this example), to
+ * get
+ *
+ * ...55555555551551551551551...
+ *
+ * Now convert back to s-notation, to get
  *
- * Engine
+ * ...55555566771771771771771...
  *
- ****************************************************************************
+ * So the answer is to do two 6 throws and then go straight into
+ * (771).  Coming back down of course,
  *
- * The main purpose of the engine is to work out the exact position of all the
- * juggling objects and the juggler's hands at any point in time.  The motion
- * of the objects can be split into two parts: in the air and and being carried.
+ * ...5515515515515515555555555...
  *
- * While in the air, the motion is governed by a standard parabolic trajectory.
- * The only minor complication is that the engine has no fixed concept of
- * gravity, instead it using a term called Alpha that varies according to the
- * pattern (see SetHeightAndAlpha). 
+ * converts to
  *
- * The motion while an object is carried comes from fitting a spline through the
- * catch and throw points and maintaining the catch and throw velocities at
- * each end.  In the simplest case this boils down to cubic Bezier spline.  The
- * only wrinkle occurs when a ball is being carried for a long time.  The simple 
- * cubic spline maths produces a curve that goes miles away -- here we do a
- * bit of reparameterisation so things stay within sensible bounds.
- * (On a related note, this scheme is _much_ simpler than the Juggle Saver
- * one.  Juggle Saver achieves 2nd order continuity and much care is taken
- * to avoid spline ringing.)
- * 
- * The motion of the hands is identical to the ball carrying code. It uses two
- * splines: one while an object is being carried; and another when it moves from
- * the previous throw to the next catch.
+ * ...7717717717716615555555555...
+ *
+ * so the answer is to do a single 661 and then drop straight down to
+ * (5).
+ *
+ * [The number of balls in the generated pattern occasionally changes.
+ * In order to decrease the number of balls I had to introduce a new
+ * symbol into the Adam notation, [*] which means 'lose the current
+ * ball'.]
  */
-static const float CARRY_TIME = 0.56f;
-static const float PI = 3.14159265358979f;
 
+/* This code uses so many linked lists it's worth having a built-in
+ * leak-checker */
+#undef MEMTEST
 
-/* While a ball is thrown it twists slighty about an axis, this routine gives
- * the total about of twist for a given ball throw. */
-static float GetBallTwistAmount(const THROW_INFO* pThrow)
-{
-    if (pThrow->FromPos.x > pThrow->ToPos.x)
-        return 18.0f * powf(pThrow->TimeInAir, 1.5);
-    else
-        return -18.0f * powf(pThrow->TimeInAir, 1.5);
-}
+# define DEFAULTS      "*delay:        10000   \n" \
+                       "*count:        200     \n" \
+                       "*cycles:       1000    \n" \
+                       "*ncolors:      32      \n" \
+                        "*titleFont:  -*-helvetica-bold-r-normal-*-180-*\n" \
+                       "*showFPS:      False   \n" \
+                       "*wireframe:    False   \n" \
 
+# define refresh_juggle 0
+#undef countof
+#define countof(x) (sizeof((x))/sizeof((*x)))
 
-static float NormaliseAngle(float Ang)
-{
-    if (Ang >= 0.0f)
-    {
-        int i = (int) (Ang + 180.0f) / 360;
-        return Ang - 360.0f * i;
-    }
-    else
-    {
-        int i = (int)(180.0f - Ang) / 360;
-        return Ang + i * 360.0f;
-    }
-}
-
+#include "xlockmore.h"
+#include "sphere.h"
+#include "tube.h"
+#include "rotator.h"
+#include "gltrackball.h"
+#include "glxfonts.h"
+#include <ctype.h>
 
-/* The interpolate routine for ball carrying and hand motion.  We are given the
- * start (P0) and end (P1) points and the velocities at these points, the task
- * is to form a function P(t) such that:
- *    P(0) = P0
- *    P(TLen) = P1
- *    P'(0) = V0
- *    P'(TLen) = V1
- */
+#ifdef USE_GL /* whole file */
 
-static POS InterpolatePosition(
-    const POS* pP0, const POS* pV0, const POS* pP1, const POS* pV1,
-    float TLen, float t)
-{
-    POS p;
-    float a, b, c, d, tt, tc;
-    
-    /* The interpolation is based on a simple cubic that achieves 1st order
-     * continuity at the end points.  However the spline can become too long if
-     * the TLen parameter is large.  In this case we cap the curve's length (fix
-     * the shape) and then reparameterise time to achieve the continuity
-     * conditions. */
-
-    tc = CARRY_TIME;
-    
-    if (TLen > tc)
-    {
-        /* The reparameterisation tt(t) gives:
-         *  tt(0) = 0, tt(TLen) = tc, tt'(0) = 1, tt'(TLen) = 1
-         * and means we can set t = tt(t), TLen = tc and then fall through
-         * to use the normal cubic spline fit.
-         *    
-         * The reparameterisation is based on two piecewise quadratics, one
-         * that goes from t = 0 to t = TLen / 2 and the other, mirrored in
-         * tt and t that goes from t = TLen / 2 to t = TLen.
-         * Because TLen > tc we can arrange for tt to be unique in the range if
-         * we specify the quadratic in tt.  i.e. t = A * tt ^ 2 + B * tt + C.
-         *
-         * Considering the first piece and applying initial conditions.
-         *   tt = 0 when t = 0   =>  C = 0
-         *   tt' = 1 when t = 0   =>  B = 1
-         *   tt = tc / 2 when t = TLen / 2  =>  A = 2 * (TLen - tc) / tc^2
-         *
-         * writing in terms of t
-         *   tt = (-B + (B ^ 2 + 4At) ^ 0.5) / 2A
-         * or
-         *   tt = ((1 + 4At) ^ 0.5 - 1) / 2A */
-        
-        float A = 2.0f * (TLen - tc) / (tc * tc);
-        
-        if (t > TLen / 2.0f)
-            t = tc - (sqrtf(1.0f + 4.0f * A * (TLen - t)) - 1.0f) / (2.0f * A);
-        else
-            t = (sqrtf(1.0f + 4.0f * A * t) - 1.0f) / (2.0f * A);
-        
-        TLen = tc;
-    }
-    
-    /* The cubic spline takes the form:
-     *   P(t) = p0 * a(t) + v0 * b(t) + p1 * c(t) + v1 * d(t)
-     * where p0 is the start point, v0 the start velocity, p1 the end point and
-     * v1 the end velocity.  a(t), b(t), c(t) and d(t) are cubics in t.
-     * We can show that:
-     *
-     *  a(t) = 2 * (t / TLen) ^ 3 - 3 * (t / TLen) ^ 2 + 1
-     *  b(t) = t ^ 3 / TLen ^ 2 - 2 * t ^ 2 / TLen + t
-     *  c(t) = -2 * (t / TLen) ^ 3 + 3 * (t / TLen) ^ 2
-     *  d(t) = t ^ 3 / TLen ^ 2 - t ^ 2 / TLen
-     *
-     * statisfy the boundary conditions:
-     *    P(0) = p0, P(TLen) = p1, P'(0) = v0 and P'(TLen) = v1  */
-    
-    tt = t / TLen;
-    
-    a = tt * tt * (2.0f * tt - 3.0f) + 1.0f;
-    b = t * tt * (tt - 2.0f) + t;
-    c = tt * tt * (3.0f - 2.0f * tt);
-    d = t * tt * (tt - 1.0f);
-
-    p.x = a * pP0->x + b * pV0->x + c * pP1->x + d * pV1->x;
-    p.y = a * pP0->y + b * pV0->y + c * pP1->y + d * pV1->y;
-    p.z = a * pP0->z + b * pV0->z + c * pP1->z + d * pV1->z;
-
-    p.Rot = a * NormaliseAngle(pP0->Rot) + b * pV0->Rot + 
-        c * NormaliseAngle(pP1->Rot) + d * pV1->Rot;
-    p.Elev = a * NormaliseAngle(pP0->Elev) + b * pV0->Elev + 
-        c * NormaliseAngle(pP1->Elev) + d * pV1->Elev;
-
-    return p;
-}
+#define DEF_PATTERN "random" /* All patterns */
+#define DEF_TAIL "1" /* No trace */
+#ifdef UNI
+/* Maybe a ROLA BOLA would be at a better angle for viewing */
+#define DEF_UNI "False" /* No unicycle */ /* Not implemented yet */
+#endif
+#define DEF_REAL "True"
+#define DEF_DESCRIBE "True"
+
+#define DEF_BALLS "True" /* Use Balls */
+#define DEF_CLUBS "True" /* Use Clubs */
+#define DEF_TORCHES "True" /* Use Torches */
+#define DEF_KNIVES "True" /* Use Knives */
+#define DEF_RINGS "True" /* Use Rings */
+#define DEF_BBALLS "True" /* Use Bowling Balls */
+
+static char *pattern;
+static int tail;
+#ifdef UNI
+static Bool uni;
+#endif
+static Bool real;
+static Bool describe;
+static Bool balls;
+static Bool clubs;
+static Bool torches;
+static Bool knives;
+static Bool rings;
+static Bool bballs;
+static char *only;
+
+static XrmOptionDescRec opts[] = {
+  {"-pattern",  ".juggle.pattern",  XrmoptionSepArg, NULL  },
+  {"-tail",     ".juggle.tail",     XrmoptionSepArg, NULL  },
+#ifdef UNI
+  {"-uni",      ".juggle.uni",      XrmoptionNoArg,  "on"  },
+  {"+uni",      ".juggle.uni",      XrmoptionNoArg,  "off" },
+#endif
+  {"-real",     ".juggle.real",     XrmoptionNoArg,  "on"  },
+  {"+real",     ".juggle.real",     XrmoptionNoArg,  "off" },
+  {"-describe", ".juggle.describe", XrmoptionNoArg,  "on"  },
+  {"+describe", ".juggle.describe", XrmoptionNoArg,  "off" },
+  {"-balls",    ".juggle.balls",    XrmoptionNoArg,  "on"  },
+  {"+balls",    ".juggle.balls",    XrmoptionNoArg,  "off" },
+  {"-clubs",    ".juggle.clubs",    XrmoptionNoArg,  "on"  },
+  {"+clubs",    ".juggle.clubs",    XrmoptionNoArg,  "off" },
+  {"-torches",  ".juggle.torches",  XrmoptionNoArg,  "on"  },
+  {"+torches",  ".juggle.torches",  XrmoptionNoArg,  "off" },
+  {"-knives",   ".juggle.knives",   XrmoptionNoArg,  "on"  },
+  {"+knives",   ".juggle.knives",   XrmoptionNoArg,  "off" },
+  {"-rings",    ".juggle.rings",    XrmoptionNoArg,  "on"  },
+  {"+rings",    ".juggle.rings",    XrmoptionNoArg,  "off" },
+  {"-bballs",   ".juggle.bballs",   XrmoptionNoArg,  "on"  },
+  {"+bballs",   ".juggle.bballs",   XrmoptionNoArg,  "off" },
+  {"-only",     ".juggle.only",     XrmoptionSepArg, NULL  },
+};
 
+static argtype vars[] = {
+  { &pattern,  "pattern",  "Pattern",  DEF_PATTERN,  t_String },
+  { &tail,     "tail",     "Tail",     DEF_TAIL,     t_Int    },
+#ifdef UNI
+  { &uni,      "uni",      "Uni",      DEF_UNI,      t_Bool   },
+#endif
+  { &real,     "real",     "Real",     DEF_REAL,     t_Bool   },
+  { &describe, "describe", "Describe", DEF_DESCRIBE, t_Bool   },
+  { &balls,    "balls",    "Clubs",    DEF_BALLS,    t_Bool   },
+  { &clubs,    "clubs",    "Clubs",    DEF_CLUBS,    t_Bool   },
+  { &torches,  "torches",  "Torches",  DEF_TORCHES,  t_Bool   },
+  { &knives,   "knives",   "Knives",   DEF_KNIVES,   t_Bool   },
+  { &rings,    "rings",    "Rings",    DEF_RINGS,    t_Bool   },
+  { &bballs,   "bballs",   "BBalls",   DEF_BBALLS,   t_Bool   },
+  { &only,     "only",     "BBalls",   " ",          t_String },
+};
 
-static POS InterpolateCarry(
-    const THROW_INFO* pThrow, const THROW_INFO* pNext, float t)
+static OptionStruct desc[] =
 {
-    float CT = CARRY_TIME + pThrow->TotalTime - pThrow->TimeInAir;
-    return InterpolatePosition(&pThrow->ToPos, &pThrow->ToVelocity,
-        &pNext->FromPos, &pNext->FromVelocity, CT, t);
-}
+  { "-pattern string", "Cambridge Juggling Pattern" },
+  { "-tail num",       "Trace Juggling Patterns" },
+#ifdef UNI
+  { "-/+uni",          "Unicycle" },
+#endif
+  { "-/+real",         "Real-time" },
+  { "-/+describe",     "turn on/off pattern descriptions." },
+  { "-/+balls",        "turn on/off Balls." },
+  { "-/+clubs",        "turn on/off Clubs." },
+  { "-/+torches",      "turn on/off Flaming Torches." },
+  { "-/+knives",       "turn on/off Knives." },
+  { "-/+rings",        "turn on/off Rings." },
+  { "-/+bballs",       "turn on/off Bowling Balls." },
+  { "-only",           "Turn off all objects but the named one." },
+};
 
+ENTRYPOINT ModeSpecOpt juggle_opts =
+ {countof(opts), opts, countof(vars), vars, desc};
+
+
+/* Note: All "lengths" are scaled by sp->scale = MI_HEIGHT/480.  All
+   "thicknesses" are scaled by sqrt(sp->scale) so that they are
+   proportionally thicker for smaller windows.  Objects spinning out
+   of the plane (such as clubs) fake perspective by compressing their
+   horizontal coordinates by PERSPEC  */
+
+/* Figure */
+#define ARMLENGTH 50
+#define ARMWIDTH ((int) (8.0 * sqrt(sp->scale)))
+#define POSE 10
+#define BALLRADIUS ARMWIDTH
+
+/* build all the models assuming a 480px high scene */
+#define SCENE_HEIGHT 480
+#define SCENE_WIDTH ((int)(SCENE_HEIGHT*(MI_WIDTH(mi)/(float)MI_HEIGHT(mi))))
+
+/*#define PERSPEC  0.4*/
+
+/* macros */
+#define GRAVITY(h, t) 4*(double)(h)/((t)*(t))
+
+/* Timing based on count.  Units are milliseconds.  Juggles per second
+       is: 2000 / THROW_CATCH_INTERVAL + CATCH_THROW_INTERVAL */
+
+#define THROW_CATCH_INTERVAL (sp->count)
+#define THROW_NULL_INTERVAL  (sp->count * 0.5)
+#define CATCH_THROW_INTERVAL (sp->count * 0.2)
+
+/********************************************************************
+ * Trace Definitions                                                *
+ *                                                                  *
+ * These record rendering data so that a drawn object can be erased *
+ * later.  Each object has its own Trace list.                      *
+ *                                                                  *
+ ********************************************************************/
+
+typedef struct {double x, y; } DXPoint;
+typedef struct trace *TracePtr;
+typedef struct trace {
+  TracePtr next, prev;
+  double x, y;
+  double angle;
+  int divisions;
+  DXPoint dlast;
+#ifdef MEMTEST
+  char pad[1024];
+#endif
+} Trace;
+
+/*******************************************************************
+ * Object Definitions                                              *
+ *                                                                 *
+ * These describe the various types of Object that can be juggled  *
+ *                                                                 *
+ *******************************************************************/
+typedef int (DrawProc)(ModeInfo*, unsigned long, Trace *);
+
+static DrawProc show_ball, show_europeanclub, show_torch, show_knife;
+static DrawProc show_ring, show_bball;
+
+typedef enum {BALL, CLUB, TORCH, KNIFE, RING, BBALLS,
+              NUM_OBJECT_TYPES} ObjType;
+
+#define OBJMIXPROB 20   /* inverse of the chances of using an odd
+                                                  object in the pattern */
+
+static const GLfloat body_color_1[4] = { 0.9, 0.7, 0.5, 1 };
+static const GLfloat body_color_2[4] = { 0.6, 0.4, 0.2, 1 };
+
+static const struct {
+  DrawProc *draw;                           /* Object Rendering function */
+  int       handle;                         /* Length of object's handle */
+  int       mintrail;                            /* Minimum trail length */
+  double    cor;      /* Coefficient of Restitution.  perfect bounce = 1 */
+  double    weight;          /* Heavier objects don't get thrown as high */
+} ObjectDefs[] = {
+  { /* Ball */
+       show_ball,
+       0,
+       1,
+       0.9,
+       1.0,
+  },
+  { /* Club */
+       show_europeanclub,
+       15,
+       1,
+       0.55, /* Clubs don't bounce too well */
+       1.0,
+  },
+  { /* Torch */
+       show_torch,
+       15,
+       20, /* Torches need flames */
+       0, /* Torches don't bounce -- fire risk! */
+       1.0,
+  },
+  { /* Knife */
+       show_knife,
+       15,
+       1,
+       0, /* Knives don't bounce */
+       1.0,
+  },
+  { /* Ring */
+       show_ring,
+       15,
+       1,
+       0.8,
+       1.0,
+  },
+  { /* Bowling Ball */
+       show_bball,
+       0,
+       1,
+       0.2,
+       5.0,
+  },
+};
 
-/* Determine the position of the hand at a point in time. */
+/**************************
+ * Trajectory definitions *
+ **************************/
+
+typedef enum {HEIGHT, ADAM} Notation;
+typedef enum {Empty, Full, Ball} Throwable;
+typedef enum {LEFT, RIGHT} Hand;
+typedef enum {THROW, CATCH} Action;
+typedef enum {HAND, ELBOW, SHOULDER} Joint;
+typedef enum {ATCH, THRATCH, ACTION, LINKEDACTION,
+                         PTHRATCH, BPREDICTOR, PREDICTOR} TrajectoryStatus;
+typedef struct {double a, b, c, d; } Spline;
+typedef DXPoint Arm[3];
+
+
+/* Object is an arbitrary object being juggled.  Each Trajectory
+ * references an Object ("count" tracks this), and each Object is also
+ * linked into a global Objects list.  Objects may include a Trace
+ * list for tracking erasures. */
+typedef struct object *ObjectPtr;
+typedef struct object {
+  ObjectPtr next, prev;
+
+  ObjType type;
+  int     color;
+  int     count; /* reference count */
+  Bool    active; /* Object is in use */
+
+  Trace  *trace;
+  int     tracelen;
+  int     tail;
+#ifdef MEMTEST
+  char pad[1024];
+#endif
+} Object;
+
+/* Trajectory is a segment of juggling action.  A list of Trajectories
+ * defines the juggling performance.  The Trajectory list goes through
+ * multiple processing steps to convert it from basic juggling
+ * notation into rendering data. */
+
+typedef struct trajectory *TrajectoryPtr;
+typedef struct trajectory {
+  TrajectoryPtr prev, next;  /* for building list */
+  TrajectoryStatus status;
+
+  /* Throw */
+  char posn;
+  int height;
+  int adam;
+  char *pattern;
+  char *name;
+
+  /* Action */
+  Hand hand;
+  Action action;
+
+  /* LinkedAction */
+  int color;
+  Object *object;
+  int divisions;
+  double angle, spin;
+  TrajectoryPtr balllink;
+  TrajectoryPtr handlink;
+
+  /* PThratch */
+  double cx; /* Moving juggler */
+  double x, y; /* current position */
+  double dx, dy; /* initial velocity */
+
+  /* Predictor */
+  Throwable type;
+  unsigned long start, finish;
+  Spline xp, yp;
+
+#ifdef MEMTEST
+  char pad[1024];
+#endif
+} Trajectory;
+
+
+/*******************
+ * Pattern Library *
+ *******************/
+
+typedef struct {
+  const char * pattern;
+  const char * name;
+} patternstruct;
+
+/* List of popular patterns, in any order */
+/* Patterns should be given in Adam notation so the generator can
+   concatenate them safely.  Null descriptions are ok.  Height
+   notation will be displayed automatically.  */
+/* Can't const this because it is qsorted.  This *should* be reentrant,
+   I think... */
+static /*const*/ patternstruct portfolio[] = {
+  {"[+2 1]", /* +3 1 */ "Typical 2 ball juggler"},
+  {"[2 0]", /* 4 0 */ "2 in 1 hand"},
+  {"[2 0 1]", /* 5 0 1 */},
+  {"[+2 0 +2 0 0]" /* +5 0 +5 0 0 */},
+  {"[+2 0 1 2 2]", /* +4 0 1 2 3 */},
+  {"[2 0 1 1]", /* 6 0 1 1 */},
+
+  {"[3]", /* 3 */ "3 cascade"},
+  {"[+3]", /* +3 */ "reverse 3 cascade"},
+  {"[=3]", /* =3 */ "cascade 3 under arm"},
+  {"[&3]", /* &3 */ "cascade 3 catching under arm"},
+  {"[_3]", /* _3 */ "bouncing 3 cascade"},
+  {"[+3 x3 =3]", /* +3 x3 =3 */ "Mill's mess"},
+  {"[3 2 1]", /* 5 3 1" */},
+  {"[3 3 1]", /* 4 4 1" */},
+  {"[3 1 2]", /* 6 1 2 */ "See-saw"},
+  {"[=3 3 1 2]", /* =4 5 1 2 */},
+  {"[=3 2 2 3 1 2]", /* =6 2 2 5 1 2 */ "=4 5 1 2 stretched"},
+  {"[+3 3 1 3]", /* +4 4 1 3 */ "anemic shower box"},
+  {"[3 3 1]", /* 4 4 1 */},
+  {"[+3 2 3]", /* +4 2 3 */},
+  {"[+3 1]", /* +5 1 */ "3 shower"},
+  {"[_3 1]", /* _5 1 */ "bouncing 3 shower"},
+  {"[3 0 3 0 3]", /* 5 0 5 0 5 */ "shake 3 out of 5"},
+  {"[3 3 3 0 0]", /* 5 5 5 0 0 */ "flash 3 out of 5"},
+  {"[3 3 0]", /* 4 5 0 */ "complete waste of a 5 ball juggler"},
+  {"[3 3 3 0 0 0 0]", /* 7 7 7 0 0 0 0 */ "3 flash"},
+  {"[+3 0 +3 0 +3 0 0]", /* +7 0 +7 0 +7 0 0 */},
+  {"[3 2 2 0 3 2 0 2 3 0 2 2 0]", /* 7 3 3 0 7 3 0 3 7 0 3 3 0 */},
+  {"[3 0 2 0]", /* 8 0 4 0 */},
+  {"[_3 2 1]", /* _5 3 1 */},
+  {"[_3 0 1]", /* _8 0 1 */},
+  {"[1 _3 1 _3 0 1 _3 0]", /* 1 _7 1 _7 0 1 _7 0 */},
+  {"[_3 2 1 _3 1 2 1]", /* _6 3 1 _6 1 3 1 */},
+
+  {"[4]", /* 4 */ "4 cascade"},
+  {"[+4 3]", /* +5 3 */ "4 ball half shower"},
+  {"[4 4 2]", /* 5 5 2 */},
+  {"[+4 4 4 +4]", /* +4 4 4 +4 */ "4 columns"},
+  {"[+4 3 +4]", /* +5 3 +4 */},
+  {"[4 3 4 4]", /* 5 3 4 4 */},
+  {"[4 3 3 4]", /* 6 3 3 4 */},
+  {"[4 3 2 4", /* 6 4 2 4 */},
+  {"[+4 1]", /* +7 1 */ "4 shower"},
+  {"[4 4 4 4 0]", /* 5 5 5 5 0 */ "learning 5"},
+  {"[+4 x4 =4]", /* +4 x4 =4 */ "Mill's mess for 4"},
+  {"[+4 2 1 3]", /* +9 3 1 3 */},
+  {"[4 4 1 4 1 4]", /* 6 6 1 5 1 5, by Allen Knutson */},
+  {"[_4 _4 _4 1 _4 1]", /* _5 _6 _6 1 _5 1 */},
+  {"[_4 3 3]", /* _6 3 3 */},
+  {"[_4 3 1]", /* _7 4 1 */},
+  {"[_4 2 1]", /* _8 3 1 */},
+  {"[_4 3 3 3 0]", /* _8 4 4 4 0 */},
+  {"[_4 1 3 1]", /* _9 1 5 1 */},
+  {"[_4 1 3 1 2]", /* _10 1 6 1 2 */},
+
+  {"[5]", /* 5 */ "5 cascade"},
+  {"[_5 _5 _5 _5 _5 5 5 5 5 5]", /* _5 _5 _5 _5 _5 5 5 5 5 5 */},
+  {"[+5 x5 =5]", /* +5 x5 =5 */ "Mill's mess for 5"},
+  {"[5 4 4]", /* 7 4 4 */},
+  {"[_5 4 4]", /* _7 4 4 */},
+  {"[1 2 3 4 5 5 5 5 5]", /* 1 2 3 4 5 6 7 8 9 */ "5 ramp"},
+  {"[5 4 5 3 1]", /* 8 5 7 4 1, by Allen Knutson */},
+  {"[_5 4 1 +4]", /* _9 5 1 5 */},
+  {"[_5 4 +4 +4]", /* _8 4 +4 +4 */},
+  {"[_5 4 4 4 1]", /* _9 5 5 5 1 */},
+  {"[_5 4 4 5 1]",},
+  {"[_5 4 4 +4 4 0]", /*_10 5 5 +5 5 0 */},
+
+  {"[6]", /* 6 */ "6 cascade"},
+  {"[+6 5]", /* +7 5 */},
+  {"[6 4]", /* 8 4 */},
+  {"[+6 3]", /* +9 3 */},
+  {"[6 5 4 4]", /* 9 7 4 4 */},
+  {"[+6 5 5 5]", /* +9 5 5 5 */},
+  {"[6 0 6]", /* 9 0 9 */},
+  {"[_6 0 _6]", /* _9 0 _9 */},
+
+  {"[_7]", /* _7 */ "bouncing 7 cascade"},
+  {"[7]", /* 7 */ "7 cascade"},
+  {"[7 6 6 6 6]", /* 11 6 6 6 6 */ "Gatto's High Throw"},
 
-static void GetHandPosition(
-    PATTERN_INFO* pPattern, int RightHand, float Time, POS* pPos)
-{
-    OBJECT_POSITION* pObj = 
-        RightHand == 0 ? &pPattern->LeftHand : &pPattern->RightHand;
-    THROW_INFO* pLastThrow;
-    
-    /* Upon entry, the throw information for the relevant hand may be out of
-     * sync.  Therefore we advance through the pattern if required. */
-
-    while (pPattern->pThrowInfo[pObj->ThrowIndex].NextForHand + pObj->TimeOffset 
-        <= (int) Time)
-    {
-        int w = pPattern->pThrowInfo[pObj->ThrowIndex].NextForHand;
-        pObj->TimeOffset += w;
-        pObj->ThrowIndex = (pObj->ThrowIndex + w) % pPattern->ThrowLen;
-    }
+};
 
-    pLastThrow = &pPattern->pThrowInfo[pObj->ThrowIndex];
 
-    /* The TimeInAir will only ever be 2 or 0 if no object is ever thrown by
-     * this hand.  In normal circumstances, 2's in the site swap are coalesced
-     * and added to TotalTime of the previous throw.  0 is a hole and means that
-     * an object isn't there.  In this case we just hold the hand still. */
-    if (pLastThrow->TimeInAir == 2 || pLastThrow->TimeInAir == 0)
-    {
-        pPos->x = pLastThrow->FromPos.x;
-        pPos->y = pLastThrow->FromPos.y;
-    }
-    else
-    {
-        /* The hand is either moving to catch the next object or carrying the
-         * next object to its next throw position.  The way THROW_INFO is
-         * structured means the relevant information for the object we're going
-         * to catch is held at the point at which it was thrown 
-         * (pNextThrownFrom).  We can't go straight for it and instead have to
-         * look at the object we've about to throw next and work out where it
-         * came from. */
-        
-        THROW_INFO* pNextThrow = &pPattern->pThrowInfo[
-            (pObj->ThrowIndex + pLastThrow->NextForHand) % pPattern->ThrowLen];
-        
-        THROW_INFO* pNextThrownFrom = 
-            &pPattern->pThrowInfo[pNextThrow->PrevThrow];
-        
-        /* tc is a measure of how long the object we're due to catch is being
-         * carried for.  We use this to work out if we've actually caught it at
-         * this moment in time. */
-        
-        float tc = CARRY_TIME + 
-            pNextThrownFrom->TotalTime - pNextThrownFrom->TimeInAir;
-        
-        Time -= pObj->TimeOffset;
 
-        if (Time > pLastThrow->NextForHand - tc)
-        {
-            /* carrying this ball to it's new location */
-            *pPos = InterpolateCarry(pNextThrownFrom,
-                pNextThrow, (Time - (pLastThrow->NextForHand - tc)));
-        }
-        else
-        {
-            /* going for next catch */
-            *pPos = InterpolatePosition(
-                &pLastThrow->FromPos, &pLastThrow->FromVelocity, 
-                &pNextThrownFrom->ToPos, &pNextThrownFrom->ToVelocity,
-                pLastThrow->NextForHand - tc, Time);
-        }
-    }
-}
+typedef struct { int start; int number; } PatternIndex;
 
+struct patternindex {
+  int minballs;
+  int maxballs;
+  PatternIndex index[countof(portfolio)];
+};
 
-static float SinDeg(float AngInDegrees)
-{
-    return sinf(AngInDegrees * PI / 180.0f);
+
+/* Jugglestruct: per-screen global data.  The master Object
+ * and Trajectory lists are anchored here. */
+typedef struct {
+  GLXContext *glx_context;
+  rotator *rot;
+  trackball_state *trackball;
+  Bool button_down_p;
+
+  double        scale;
+  double        cx;
+  double        Gr;
+  Trajectory   *head;
+  Arm           arm[2][2];
+  char         *pattern;
+  int           count;
+  int           num_balls;
+  time_t        begintime; /* should make 'time' usable for at least 48 days
+                                                       on a 32-bit machine */
+  unsigned long time; /* millisecond timer*/
+  ObjType       objtypes;
+  Object       *objects;
+  struct patternindex patternindex;
+
+  XFontStruct *mode_font;
+  GLuint font_dlist;
+} jugglestruct;
+
+static jugglestruct *juggles = (jugglestruct *) NULL;
+
+/*******************
+ * list management *
+ *******************/
+
+#define DUP_OBJECT(n, t) { \
+  (n)->object = (t)->object; \
+  if((n)->object != NULL) (n)->object->count++; \
 }
 
+/* t must point to an existing element.  t must not be an
+   expression ending ->next or ->prev */
+#define REMOVE(t) { \
+  (t)->next->prev = (t)->prev; \
+  (t)->prev->next = (t)->next; \
+  free(t); \
+}
 
-static float CosDeg(float AngInDegrees)
+/* t receives element to be created and added to the list.  ot must
+   point to an existing element or be identical to t to start a new
+   list. Applicable to Trajectories, Objects and Traces. */
+#define ADD_ELEMENT(type, t, ot) \
+  if (((t) = (type*)calloc(1,sizeof(type))) != NULL) { \
+    (t)->next = (ot)->next; \
+    (t)->prev = (ot); \
+    (ot)->next = (t); \
+    (t)->next->prev = (t); \
+  }
+
+static void
+object_destroy(Object* o)
 {
-    return cosf(AngInDegrees * PI / 180.0f);
+  if(o->trace != NULL) {
+       while(o->trace->next != o->trace) {
+         Trace *s = o->trace->next;
+         REMOVE(s); /* Don't eliminate 's' */
+       }
+       free(o->trace);
+  }
+  REMOVE(o);
 }
 
+static void
+trajectory_destroy(Trajectory *t) {
+  if(t->name != NULL) free(t->name);
+  if(t->pattern != NULL) free(t->pattern);
+  /* Reduce object link count and call destructor if necessary */
+  if(t->object != NULL && --t->object->count < 1 && t->object->tracelen == 0) {
+       object_destroy(t->object);
+  }
+  REMOVE(t); /* Unlink and free */
+}
 
-/* Offset the specified position to get the centre of the object based on the
- * the handle length and the current orientation */
+static void
+free_juggle(jugglestruct *sp) {
+  if (sp->head != NULL) {
+       while (sp->head->next != sp->head) {
+         trajectory_destroy(sp->head->next);
+       }
+       free(sp->head);
+       sp->head = (Trajectory *) NULL;
+  }
+  if(sp->objects != NULL) {
+       while (sp->objects->next != sp->objects) {
+         object_destroy(sp->objects->next);
+       }
+       free(sp->objects);
+       sp->objects = (Object*)NULL;
+  }
+  if(sp->pattern != NULL) {
+       free(sp->pattern);
+       sp->pattern = NULL;
+  }
+  if (sp->mode_font!=None) {
+       XFreeFontInfo(NULL,sp->mode_font,1);
+       sp->mode_font = None;
+  }
+}
 
-static void OffsetHandlePosition(const POS* pPos, float HandleLen, POS* pResult)
+static Bool
+add_throw(jugglestruct *sp, char type, int h, Notation n, const char* name)
 {
-    pResult->x = pPos->x + HandleLen * SinDeg(pPos->Rot) * CosDeg(pPos->Elev);
-    pResult->y = pPos->y + HandleLen * SinDeg(pPos->Elev);
-    pResult->z = pPos->z + HandleLen * CosDeg(pPos->Rot) * CosDeg(pPos->Elev);
-    pResult->Elev = pPos->Elev;
-    pResult->Rot = pPos->Rot;
+  Trajectory *t;
+
+  ADD_ELEMENT(Trajectory, t, sp->head->prev);
+  if(t == NULL){ /* Out of Memory */
+       free_juggle(sp);
+       return False;
+  }
+  t->object = NULL;
+  if(name != NULL)
+       t->name = strdup(name);
+  t->posn = type;
+  if (n == ADAM) {
+       t->adam = h;
+       t->height = 0;
+       t->status = ATCH;
+  } else {
+       t->height = h;
+       t->status = THRATCH;
+  }
+  return True;
 }
 
-
-static void GetObjectPosition(
-    PATTERN_INFO* pPattern, int Obj, float Time, float HandleLen, POS* pPos)
+/* add a Thratch to the performance */
+static Bool
+program(ModeInfo *mi, const char *patn, const char *name, int cycles)
 {
-    OBJECT_POSITION* pObj = &pPattern->pObjectInfo[Obj];
-    THROW_INFO* pThrow;
-    
-    /* Move through the pattern, if required, such that pThrow corresponds to
-     * the current throw for this object. */
-
-    while (pPattern->pThrowInfo[pObj->ThrowIndex].TotalTime + pObj->TimeOffset
-        <= (int) Time)
-    {
-        int w = pPattern->pThrowInfo[pObj->ThrowIndex].TotalTime;
-        pObj->TimeOffset += w;
-        pObj->TotalTwist = NormaliseAngle(pObj->TotalTwist + 
-            GetBallTwistAmount(&pPattern->pThrowInfo[pObj->ThrowIndex]));
-        
-        pObj->ThrowIndex = (pObj->ThrowIndex + w) % pPattern->ThrowLen;
-    }
-
-    pThrow = &pPattern->pThrowInfo[pObj->ThrowIndex];
+  jugglestruct *sp = &juggles[MI_SCREEN(mi)];
+  const char *p;
+  int w, h, i, seen;
+  Notation notation;
+  char type;
+
+  if (MI_IS_VERBOSE(mi)) {
+       (void) fprintf(stderr, "juggle[%d]: Programmed: %s x %d\n",
+                                  MI_SCREEN(mi), (name == NULL) ? patn : name, cycles);
+  }
+
+  for(w=i=0; i < cycles; i++, w++) { /* repeat until at least "cycles" throws
+                                                                               have been programmed */
+       /* title is the pattern name to be supplied to the first throw of
+          a sequence.  If no name if given, use an empty title so that
+          the sequences are still delimited. */
+       const char *title = (name != NULL)? name : "";
+       type=' ';
+       h = 0;
+       seen = 0;
+       notation = HEIGHT;
+       for(p=patn; *p; p++) {
+         if (*p >= '0' && *p <='9') {
+               seen = 1;
+               h = 10*h + (*p - '0');
+         } else {
+               Notation nn = notation;
+               switch (*p) {
+               case '[':            /* begin Adam notation */
+                 notation = ADAM;
+                 break;
+               case '-':            /* Inside throw */
+                 type = ' ';
+                 break;
+               case '+':            /* Outside throw */
+               case '=':            /* Cross throw */
+               case '&':            /* Cross catch */
+               case 'x':            /* Cross throw and catch */
+               case '_':            /* Bounce */
+               case 'k':            /* Kickup */
+                 type = *p;
+                 break;
+               case '*':            /* Lose ball */
+                 seen = 1;
+                 h = -1;
+                 /* fall through */
+               case ']':             /* end Adam notation */
+                 nn = HEIGHT;
+                 /* fall through */
+               case ' ':
+                 if (seen) {
+                       i++;
+                       if (!add_throw(sp, type, h, notation, title))
+                               return False;
+                       title = NULL;
+                       type=' ';
+                       h = 0;
+                       seen = 0;
+                 }
+                 notation = nn;
+                 break;
+               default:
+                 if(w == 0) { /* Only warn on first pass */
+                       (void) fprintf(stderr,
+                                                  "juggle[%d]: Unexpected pattern instruction: '%c'\n",
+                                                  MI_SCREEN(mi), *p);
+                 }
+                 break;
+               }
+         }
+       }
+       if (seen) { /* end of sequence */
+         if (!add_throw(sp, type, h, notation, title))
+               return False;
+         title = NULL;
+       }
+  }
+  return True;
+}
 
-    if (pThrow->TimeInAir == 2 || pThrow->TimeInAir == 0)
-    {
-        *pPos = pThrow->FromPos;
-        OffsetHandlePosition(pPos, HandleLen, pPos);
-    }
-    else
-    {
-        float tc = pThrow->TimeInAir - CARRY_TIME;
-        float BallTwist = GetBallTwistAmount(pThrow);
-        Time -= pObj->TimeOffset;
-        if (Time < tc)
-        {
-            /* object in air */
-            POS From, To;
-            float t, b;
-
-            t = Time / tc;
-            
-            OffsetHandlePosition(&pThrow->FromPos, HandleLen, &From);
-            OffsetHandlePosition(&pThrow->ToPos, HandleLen, &To);
-
-            b = (To.y - From.y) / tc + pPattern->Alpha * tc;
-            
-            pPos->x = (1.0f - t) * From.x + t * To.x;
-            pPos->z = (1.0f - t) * From.z + t * To.z;
-            pPos->y = -pPattern->Alpha * Time * Time + b * Time + From.y;
-            
-            if (pObj->ObjectType == OBJECT_BALL)
-                pPos->Rot = pObj->TotalTwist + t * BallTwist;
-            else
-            {
-                /* We describe the rotation of a club (or ring) with an
-                 * elevation and rotation but don't include a twist.
-                 * If we ignore twist for the moment, the orientation at a
-                 * rotation of r and an elevation of e can be also be expressed
-                 * by rotating the object a further 180 degrees and sort of
-                 * mirroring the rotation, e.g.:
-                 *    rot = r + 180 and elev = 180 - e
-                 * We can easily show that the maths holds, consider the
-                 * x, y ,z position of the end of a unit length club.
-                 *    y = sin(180 - e) = sin(e)
-                 *    x = cos(180 - e) * sin(r + 180) = -cos(e) * - sin(r)
-                 *    z = cos(180 - e) * cos(r + 180) = -cos(e) * - cos(r)
-                 * When a club is thrown these two potential interpretations
-                 * can produce unexpected results.
-                 * The approach we adopt is that we try and minimise the amount
-                 * of rotation we give a club -- normally this is what happens
-                 * when juggling since it's much easier to spin the club.
-                 *
-                 * When we come to drawing the object the two interpretations
-                 * aren't identical, one causes the object to twist a further
-                 * 180 about its axis.  We avoid the issue by ensuring our
-                 * objects have rotational symmetry of order 2 (e.g. we make
-                 * sure clubs have an even number of stripes) this makes the two
-                 * interpretations appear identical. */
-
-                float RotAmt = NormaliseAngle(To.Rot - From.Rot);
-
-                if (RotAmt < -90.0f)
-                {
-                    To.Elev += 180  - 2 * NormaliseAngle(To.Elev);
-                    RotAmt += 180.0f;
-                }
-                else if (RotAmt > 90.0f)
-                {
-                    To.Elev += 180 - 2 * NormaliseAngle(To.Elev);
-                    RotAmt -= 180.0f;
-                }
-
-                pPos->Rot = From.Rot + t * RotAmt;
-            }
+/*
+ ~~~~\~~~~~\~~~
+ \\~\\~\~\\\~~~
+ \\~\\\\~\\\~\~
+ \\\\\\\\\\\~\\
 
-            pPos->Elev = (1.0f - t) * From.Elev + t * To.Elev;
+[ 3 3 1 3 4 2 3 1 3 3 4 0 2 1 ]
 
-        }
-        else
-        {
-            THROW_INFO* pNextThrow = &pPattern->pThrowInfo[
-                   (pObj->ThrowIndex + pThrow->TotalTime) % pPattern->ThrowLen];
+4 4 1 3 12 2 4 1 4 4 13 0 3 1
 
-            *pPos = InterpolateCarry(pThrow, pNextThrow, Time - tc);
+*/
+#define BOUNCEOVER 10
+#define KICKMIN 7
+#define THROWMAX 20
 
-            if (pObj->ObjectType == OBJECT_BALL)
-                pPos->Rot = pObj->TotalTwist + BallTwist;
+/* Convert Adam notation into heights */
+static void
+adam(jugglestruct *sp)
+{
+  Trajectory *t, *p;
+  for(t = sp->head->next; t != sp->head; t = t->next) {
+       if (t->status == ATCH) {
+         int a = t->adam;
+         t->height = 0;
+         for(p = t->next; a > 0; p = p->next) {
+               if(p == sp->head) {
+                 t->height = -9; /* Indicate end of processing for name() */
+                 return;
+               }
+               if (p->status != ATCH || p->adam < 0 || p->adam>= a) {
+                 a--;
+               }
+               t->height++;
+         }
+         if(t->height > BOUNCEOVER && t->posn == ' '){
+               t->posn = '_'; /* high defaults can be bounced */
+         } else if(t->height < 3 && t->posn == '_') {
+               t->posn = ' '; /* Can't bounce short throws. */
+         }
+         if(t->height < KICKMIN && t->posn == 'k'){
+               t->posn = ' '; /* Can't kick short throws */
+         }
+         if(t->height > THROWMAX){
+               t->posn = 'k'; /* Use kicks for ridiculously high throws */
+         }
+         t->status = THRATCH;
+       }
+  }
+}
 
-            OffsetHandlePosition(pPos, HandleLen, pPos);
-        }
-    }
+/* Discover converted heights and update the sequence title */
+static void
+name(jugglestruct *sp)
+{
+  Trajectory *t, *p;
+  char buffer[BUFSIZ];
+  char *b;
+  for(t = sp->head->next; t != sp->head; t = t->next) {
+       if (t->status == THRATCH && t->name != NULL) {
+         b = buffer;
+         for(p = t; p == t || p->name == NULL; p = p->next) {
+               if(p == sp->head || p->height < 0) { /* end of reliable data */
+                 return;
+               }
+               if(p->posn == ' ') {
+                 b += sprintf(b, " %d", p->height);
+               } else {
+                 b += sprintf(b, " %c%d", p->posn, p->height);
+               }
+               if(b - buffer > 500) break; /* otherwise this could eventually
+                                                                          overflow.  It'll be too big to
+                                                                          display anyway. */
+         }
+         if(*t->name != 0) {
+               (void) sprintf(b, ", %s", t->name);
+         }
+         free(t->name); /* Don't need name any more, it's been converted
+                                               to pattern */
+         t->name = NULL;
+         if(t->pattern != NULL) free(t->pattern);
+         t->pattern = strdup(buffer);
+       }
+  }
 }
 
+/* Split Thratch notation into explicit throws and catches.
+   Usually Catch follows Throw in same hand, but take care of special
+   cases. */
 
-/* Alpha is used to represent the acceleration due to gravity (in fact
- * 2 * Alpha is the acceleration).  Alpha is adjusted according to the pattern
- * being juggled.  My preference is to slow down patterns with lots of objects
- * -- they move too fast in realtime.  Also I prefer to see a balance between
- * the size of the figure and the height of objects thrown -- juggling patterns
- * with large numbers of objects under real gravity can mean balls are lobbed
- * severe heights.  Adjusting Alpha achieves both these goals.
- *
- * Basically we pick a height we'd like to see the biggest throw reach and then
- * adjust Alpha to meet this. */
+/* ..n1.. -> .. LTn RT1 LC RC .. */
+/* ..nm.. -> .. LTn LC RTm RC .. */
 
-static void SetHeightAndAlpha(PATTERN_INFO* pPattern, 
-    const int* Site, const EXT_SITE_INFO* pExtInfo, int Len)
+static Bool
+part(jugglestruct *sp)
 {
-    float H;
-    int MaxW = 5;
-    int i;
-    
-    if (Site != NULL)
-    {
-        for (i = 0; i < Len; i++)
-            MaxW = max(MaxW, Site[i]);
-    }
-    else
-    {
-        for (i = 0; i < Len; i++)
-            MaxW = max(MaxW, pExtInfo[i].Weight);
-    }
-    
-    /* H is the ideal max height we'd like our objects to reach.  The formula
-     * was developed by trial and error and was simply stolen from Juggle Saver.
-     * Alpha is then calculated from the classic displacement formula:
-     *   s = 0.5at^2 + ut  (where a = 2 * Alpha)
-     * We know u (the velocity) is zero at the peak, and the object should fall
-     * H units in half the time of biggest throw weight.
-     * Finally we determine the proper height the max throw reaches since this
-     * may not be H because capping may be applied (e.g. for max weights less
-     * than 5). */
-    
-    H = 8.0f * powf(MaxW / 2.0f, 0.8f) + 5.0f;
-    pPattern->Alpha = (2.0f * H) / powf(max(5, MaxW) - CARRY_TIME, 2.0f);
-    pPattern->Height = pPattern->Alpha * powf((MaxW - CARRY_TIME) * 0.5f, 2);
+  Trajectory *t, *nt, *p;
+  Hand hand = (LRAND() & 1) ? RIGHT : LEFT;
+
+  for (t = sp->head->next; t != sp->head; t = t->next) {
+       if (t->status > THRATCH) {
+         hand = t->hand;
+       } else if (t->status == THRATCH) {
+         char posn = '=';
+
+         /* plausibility check */
+         if (t->height <= 2 && t->posn == '_') {
+               t->posn = ' '; /* no short bounces */
+         }
+         if (t->height <= 1 && (t->posn == '=' || t->posn == '&')) {
+               t->posn = ' '; /* 1's need close catches */
+         }
+
+         switch (t->posn) {
+                 /*         throw          catch    */
+         case ' ': posn = '-'; t->posn = '+'; break;
+         case '+': posn = '+'; t->posn = '-'; break;
+         case '=': posn = '='; t->posn = '+'; break;
+         case '&': posn = '+'; t->posn = '='; break;
+         case 'x': posn = '='; t->posn = '='; break;
+         case '_': posn = '_'; t->posn = '-'; break;
+         case 'k': posn = 'k'; t->posn = 'k'; break;
+         default:
+               (void) fprintf(stderr, "juggle: unexpected posn %c\n", t->posn);
+               break;
+         }
+         hand = (Hand) ((hand + 1) % 2);
+         t->status = ACTION;
+         t->hand = hand;
+         p = t->prev;
+
+         if (t->height == 1 && p != sp->head) {
+               p = p->prev; /* '1's are thrown earlier than usual */
+         }
+
+
+
+         t->action = CATCH;
+         ADD_ELEMENT(Trajectory, nt, p);
+         if(nt == NULL){
+               free_juggle(sp);
+               return False;
+         }
+         nt->object = NULL;
+         nt->status = ACTION;
+         nt->action = THROW;
+         nt->height = t->height;
+         nt->hand = hand;
+         nt->posn = posn;
+
+       }
+  }
+  return True;
 }
 
+static ObjType
+choose_object(void) {
+  ObjType o;
+  for (;;) {
+       o = (ObjType)NRAND((ObjType)NUM_OBJECT_TYPES);
+       if(balls && o == BALL) break;
+       if(clubs && o == CLUB) break;
+       if(torches && o == TORCH) break;
+       if(knives && o == KNIFE) break;
+       if(rings && o == RING) break;
+       if(bballs && o == BBALLS) break;
+  }
+  return o;
+}
 
-/* Where positions and spin info is not specified, generate suitable default
* values. */
+/* Connnect up throws and catches to figure out which ball goes where.
  Do the same with the juggler's hands. */
 
-static int GetDefaultSpins(int Weight)
+static void
+lob(ModeInfo *mi)
 {
-    if (Weight < 3)
-        return 0;
-    else if (Weight < 4)
-        return 1;
-    else if (Weight < 7)
-        return 2;
-    else
-        return 3;
+  jugglestruct *sp = &juggles[MI_SCREEN(mi)];
+  Trajectory *t, *p;
+  int h;
+  for (t = sp->head->next; t != sp->head; t = t->next) {
+       if (t->status == ACTION) {
+         if (t->action == THROW) {
+               if (t->type == Empty) {
+                 /* Create new Object */
+                 ADD_ELEMENT(Object, t->object, sp->objects);
+                 t->object->count = 1;
+                 t->object->tracelen = 0;
+                 t->object->active = False;
+                 /* Initialise object's circular trace list */
+                 ADD_ELEMENT(Trace, t->object->trace, t->object->trace);
+
+                 if (MI_NPIXELS(mi) > 2) {
+                       t->object->color = 1 + NRAND(MI_NPIXELS(mi) - 2);
+                 } else {
+#ifdef STANDALONE
+                       t->object->color = 1;
+#else
+                       t->object->color = 0;
+#endif
+                 }
+
+                 /* Small chance of picking a random object instead of the
+                        current theme. */
+                 if(NRAND(OBJMIXPROB) == 0) {
+                       t->object->type = choose_object();
+                 } else {
+                       t->object->type = sp->objtypes;
+                 }
+
+                 /* Check to see if we need trails for this object */
+                 if(tail < ObjectDefs[t->object->type].mintrail) {
+                       t->object->tail = ObjectDefs[t->object->type].mintrail;
+                 } else {
+                       t->object->tail = tail;
+                 }
+               }
+
+               /* Balls can change divisions at each throw */
+                /* no, that looks stupid. -jwz */
+                if (t->divisions < 1)
+                  t->divisions = 2 * (NRAND(2) + 1);
+
+               /* search forward for next catch in this hand */
+               for (p = t->next; t->handlink == NULL; p = p->next) {
+                 if(p->status < ACTION || p == sp->head) return;
+                 if (p->action == CATCH) {
+                       if (t->handlink == NULL && p->hand == t->hand) {
+                         t->handlink = p;
+                       }
+                 }
+               }
+
+               if (t->height > 0) {
+                 h = t->height - 1;
+
+                 /* search forward for next ball catch */
+                 for (p = t->next; t->balllink == NULL; p = p->next) {
+                       if(p->status < ACTION || p == sp->head) {
+                         t->handlink = NULL;
+                         return;
+                       }
+                       if (p->action == CATCH) {
+                         if (t->balllink == NULL && --h < 1) { /* caught */
+                               t->balllink = p; /* complete trajectory */
+# if 0
+                               if (p->type == Full) {
+                                 (void) fprintf(stderr, "juggle[%d]: Dropped %d\n",
+                                                 MI_SCREEN(mi), t->object->color);
+                               }
+#endif
+                               p->type = Full;
+                               DUP_OBJECT(p, t); /* accept catch */
+                               p->angle = t->angle;
+                               p->divisions = t->divisions;
+                         }
+                       }
+                 }
+               }
+               t->type = Empty; /* thrown */
+         } else if (t->action == CATCH) {
+               /* search forward for next throw from this hand */
+               for (p = t->next; t->handlink == NULL; p = p->next) {
+                 if(p->status < ACTION || p == sp->head) return;
+                 if (p->action == THROW && p->hand == t->hand) {
+                       p->type = t->type; /* pass ball */
+                       DUP_OBJECT(p, t); /* pass object */
+                       p->divisions = t->divisions;
+                       t->handlink = p;
+                 }
+               }
+         }
+         t->status = LINKEDACTION;
+       }
+  }
 }
 
-
-static void GetDefaultFromPosition(unsigned char Side, int Weight, POS* pPos)
+/* Clap when both hands are empty */
+static void
+clap(jugglestruct *sp)
 {
-    if (Weight > 4 && Weight % 2 != 0)
-        pPos->x = Side ?  -0.06f : 0.06f;
-    else if (Weight == 0 || Weight == 2)
-        pPos->x = Side ? 1.6f :  -1.6f;
-    else
-        pPos->x = Side? 0.24f :  -0.24f;
-
-    pPos->y = (Weight == 2 || Weight == 0) ? -0.25f : 0.0f;
-
-    pPos->Rot = (Weight % 2 == 0 ? -23.5f : 27.0f) * (Side ? -1.0f : 1.0f);
-
-    pPos->Elev = Weight == 1 ? -30.0f : 0.0f;
-    pPos->z = 0.0f;
+  Trajectory *t, *p;
+  for (t = sp->head->next; t != sp->head; t = t->next) {
+       if (t->status == LINKEDACTION &&
+               t->action == CATCH &&
+               t->type == Empty &&
+               t->handlink != NULL &&
+               t->handlink->height == 0) { /* Completely idle hand */
+
+         for (p = t->next; p != sp->head; p = p->next) {
+               if (p->status == LINKEDACTION &&
+                       p->action == CATCH &&
+                       p->hand != t->hand) { /* Next catch other hand */
+                 if(p->type == Empty &&
+                        p->handlink != NULL &&
+                        p->handlink->height == 0) { /* Also completely idle */
+
+                       t->handlink->posn = '^'; /* Move first hand's empty throw */
+                       p->posn = '^';           /* to meet second hand's empty
+                                                                               catch */
+
+                 }
+                 break; /* Only need first catch */
+               }
+         }
+       }
+  }
 }
 
+#define CUBIC(s, t) ((((s).a * (t) + (s).b) * (t) + (s).c) * (t) + (s).d)
 
-static void GetDefaultToPosition(unsigned char Side, int Weight, POS* pPos)
+/* Compute single spline from x0 with velocity dx0 at time t0 to x1
+   with velocity dx1 at time t1 */
+static Spline
+makeSpline(double x0, double dx0, int t0, double x1, double dx1, int t1)
 {
-    if (Weight == 1)
-        pPos->x = Side ?  -1.0f : 1.0f;
-    else if (Weight % 2 == 0)
-        pPos->x = Side ? 2.8f :  -2.8f;
-    else
-        pPos->x = Side?  -3.1f : 3.1f;
-
-    pPos->y = -0.5f;
-
-    pPos->Rot = (Side ? -35.0f : 35.0f) * (Weight % 2 == 0 ? -1.0f : 1.0f);
-    
-    if (Weight < 2)
-        pPos->Elev = -30.0f;
-
-    else if (Weight < 4)
-        pPos->Elev = 360.0f - 50.0f;
-    else if (Weight < 7)
-        pPos->Elev = 720.0f - 50.0f;
-    else
-        pPos->Elev = 360.0f * GetDefaultSpins(Weight) - 50.0f;
-    pPos->z = 0.0f;
+  Spline s;
+  double a, b, c, d;
+  double x10;
+  double t10;
+
+  x10 = x1 - x0;
+  t10 = t1 - t0;
+  a = ((dx0 + dx1)*t10 - 2*x10) / (t10*t10*t10);
+  b = (3*x10 - (2*dx0 + dx1)*t10) / (t10*t10);
+  c = dx0;
+  d = x0;
+  s.a = a;
+  s.b = -3*a*t0 + b;
+  s.c = (3*a*t0 - 2*b)*t0 + c;
+  s.d = ((-a*t0 + b)*t0 - c)*t0 +d;
+  return s;
 }
 
-
-/* Update the members of PATTERN_INFO for a given juggling pattern.  The pattern
- * can come from an ordinary siteswap (Site != NULL) or from a Juggle Saver
- * compatible pattern that contains, position and object info etc. 
- * We assume that patterns are valid and have at least one object (a site of
- * zeros is invalid).  The ones we generate randomly are safe. */
-
-static void InitPatternInfo(PATTERN_INFO* pPattern,
-    const int* Site, const EXT_SITE_INFO* pExtInfo, int Len)
+/* Compute a pair of splines.  s1 goes from x0 vith velocity dx0 at
+   time t0 to x1 at time t1.  s2 goes from x1 at time t1 to x2 with
+   velocity dx2 at time t2.  The arrival and departure velocities at
+   x1, t1 must be the same. */
+static double
+makeSplinePair(Spline *s1, Spline *s2,
+                          double x0, double dx0, int t0,
+                          double x1,             int t1,
+                          double x2, double dx2, int t2)
 {
-    /* Double up on the length of the site if it's of an odd length. 
-     * This way we can store position information: even indices are on one
-     * side and odds are on the other. */
-    int InfoLen = Len % 2 == 1 ? Len * 2 : Len;
-    int i;
-    THROW_INFO* pInfo = (THROW_INFO*) calloc(InfoLen, sizeof(THROW_INFO));
-    int Objects = 0;
-    unsigned char* pUsed;
-    
-    pPattern->MaxWeight = 0;
-    pPattern->ThrowLen = InfoLen;
-    pPattern->pThrowInfo = pInfo;
-    
-    SetHeightAndAlpha(pPattern, Site, pExtInfo, Len);
-
-    /* First pass through we assign the things we know about for sure just by
-     * looking at the throw weight at this position.  This includes TimeInAir;
-     * the throw and catch positions; and throw and catch velocities.
-     * Other information, like the total time for the throw (i.e. when the
-     * object is thrown again) relies on how the rest of the pattern is 
-     * structured and we defer this task for successive passes and just make
-     * guesses at this stage. */
-    
-    for (i = 0; i < InfoLen; i++)
-    {
-        float t1;
-        int w = pExtInfo != NULL ? pExtInfo[i % Len].Weight : Site[i % Len];
-
-        pInfo[i].TotalTime = pInfo[i].TimeInAir = w;
-        pInfo[(w + i) % Len].PrevThrow = i;
-
-        /* work out where we are throwing this object from and where it's going
-         * to land. */
-
-        if (pExtInfo == NULL || (pExtInfo[i % Len].Flags & HAS_FROM_POS) == 0)
-            GetDefaultFromPosition(i % 2, w, &pInfo[i].FromPos);
-        else
-            pInfo[i].FromPos = pExtInfo[i % Len].FromPos;
-
-        if (pExtInfo == NULL || (pExtInfo[i % Len].Flags & HAS_TO_POS) == 0)
-            GetDefaultToPosition(i % 2, w, &pInfo[i].ToPos);
-        else
-            pInfo[i].ToPos = pExtInfo[i % Len].ToPos;
-
-        /* calculate the velocity the object is moving at the start and end
-         * points -- this information is used to interpolate the hand position
-         * and to determine how the object is moved while it's carried to the 
-         * next throw position.
-         *
-         * The throw motion is governed by a parabola of the form:
-         *   y(t) = a * t ^ 2 + b * t + c
-         * Assuming at the start of the throw y(0) = y0; when it's caught
-         * y(t1) = y1; and the accelation is -2.0 * alpha the equation can be
-         * rewritten as:
-         *   y(t) = -alpha * t ^ 2 + (alpha * t1 + (y1 - y0) / t1) * t + y0
-         * making the velocity:
-         *   y'(t) = -2.0 * alpha * t + (alpha * t1 + (y1 - y0) / t1)
-         * To get the y component of velocity first we determine t1, which is
-         * the throw weight minus the time spent carrying the object.  Then
-         * perform the relevant substitutions into the above.
-         * (note: y'(t) = y'(0) - 2.0 * alpha * t)
-         * 
-         * The velocity in the x direction is constant and can be simply
-         * obtained from:
-         *   x' = (x1 - x0) / t1
-         * where x0 and x1 are the start and end x-positions respectively.
-         */
-
-        t1 = w - CARRY_TIME;
-
-        pInfo[i].FromVelocity.y = pPattern->Alpha * t1 + 
-            (pInfo[i].ToPos.y - pInfo[i].FromPos.y) / t1;
-        pInfo[i].ToVelocity.y = 
-            pInfo[i].FromVelocity.y - 2.0f * pPattern->Alpha * t1;
-        pInfo[i].FromVelocity.x = pInfo[i].ToVelocity.x = 
-            (pInfo[i].ToPos.x - pInfo[i].FromPos.x) / t1;
-        pInfo[i].FromVelocity.z = pInfo[i].ToVelocity.z = 
-            (pInfo[i].ToPos.z - pInfo[i].FromPos.z) / t1;
-        pInfo[i].FromVelocity.Rot = pInfo[i].ToVelocity.Rot =
-            (pInfo[i].ToPos.Rot - pInfo[i].FromPos.Rot) / t1;
-        pInfo[i].FromVelocity.Elev = pInfo[i].ToVelocity.Elev =
-            (pInfo[i].ToPos.Elev - pInfo[i].FromPos.Elev) / t1;
-
-
-        if (pExtInfo != NULL && (pExtInfo[i % Len].Flags & HAS_SNATCH) != 0)
-        {
-            pInfo[i].ToVelocity.x = pExtInfo[i % Len].SnatchX;
-            pInfo[i].ToVelocity.y = pExtInfo[i % Len].SnatchY;
-        }
-
-        if (pExtInfo != NULL && (pExtInfo[i % Len].Flags & HAS_SPINS) != 0)
-        {
-            pInfo[i].ToPos.Elev = 360.0f * pExtInfo[i % Len].Spins +
-                NormaliseAngle(pInfo[i].ToPos.Elev);
-        }
-
-        Objects += w;
-        if (w > pPattern->MaxWeight)
-            pPattern->MaxWeight = w;
-    }
+  double x10, x21, t21, t10, t20, dx1;
+  x10 = x1 - x0;
+  x21 = x2 - x1;
+  t21 = t2 - t1;
+  t10 = t1 - t0;
+  t20 = t2 - t0;
+  dx1 = (3*x10*t21*t21 + 3*x21*t10*t10 + 3*dx0*t10*t21*t21
+                - dx2*t10*t10*t21 - 4*dx0*t10*t21*t21) /
+       (2*t10*t21*t20);
+  *s1 = makeSpline(x0, dx0, t0, x1, dx1, t1);
+  *s2 = makeSpline(x1, dx1, t1, x2, dx2, t2);
+  return dx1;
+}
 
-    Objects /= InfoLen;
+/* Compute a Ballistic path in a pair of degenerate splines.  sx goes
+   from x at time t at constant velocity dx.  sy goes from y at time t
+   with velocity dy and constant acceleration g. */
+static void
+makeParabola(Trajectory *n,
+                        double x, double dx, double y, double dy, double g)
+{
+  double t = (double)n->start;
+  n->xp.a = 0;
+  n->xp.b = 0;
+  n->xp.c = dx;
+  n->xp.d = -dx*t + x;
+  n->yp.a = 0;
+  n->yp.b = g/2;
+  n->yp.c = -g*t + dy;
+  n->yp.d = g/2*t*t - dy*t + y;
+}
 
-    /* Now we go through again and work out exactly how long it is before the
-     * object is thrown again (ie. the TotalTime) typically this is the same
-     * as the time in air, however when we have a throw weight of '2' it's
-     * treated as a hold and we increase the total time accordingly. */
 
-    for (i = 0; i < InfoLen; i++)
-    {
-        if (pInfo[i].TimeInAir != 2)
-        {
-            int Next = pInfo[i].TimeInAir + i;
-            while (pInfo[Next % InfoLen].TimeInAir == 2)
-            {
-                Next += 2;
-                pInfo[i].TotalTime += 2;
-            }
 
-            /* patch up the Prev index.  We don't bother to see if this
-             * is different from before since it's always safe to reassign it */
-            pInfo[Next % InfoLen].PrevThrow = i;
-        }
-    }
 
-    /* then we work our way through again figuring out where the hand goes to
-     * catch something as soon as it has thrown the current object. */
+#define SX 25 /* Shoulder Width */
 
-    for (i = 0; i < InfoLen; i++)
-    {
-        if (pInfo[i].TimeInAir != 0 && pInfo[i].TimeInAir != 2)
-        {
-            /* what we're trying to calculate is how long the hand that threw
-             * the current object has to wait before it throws another.
-             * Typically this is two beats later.  However '0' in the site swap
-             * represents a gap in a catch, and '2' represents a hold.  We skip
-             * over these until we reach the point where a ball is actually
-             * thrown. */
-            int Wait = 2;
-            while (pInfo[(i + Wait) % InfoLen].TimeInAir == 2 || 
-                pInfo[(i + Wait) % InfoLen].TimeInAir == 0)
-            {
-                Wait += 2;
-            }
-            pInfo[i].NextForHand = Wait;
-        }
-        else
-        {
-            /* Be careful to ensure the current weight isn't one we're trying
-             * to step over; otherwise we could potentially end up in an 
-             * infinite loop.  The value we assign may end up being used
-             * in patterns with infinite gaps (e.g. 60) or infinite holds
-             * (e.g. 62) in both cases, setting a wait of 2 ensures things
-             * are well behaved. */
-            pInfo[i].NextForHand = 2;
-        }
-    }
+/* Convert hand position symbols into actual time/space coordinates */
+static void
+positions(jugglestruct *sp)
+{
+  Trajectory *t;
+  unsigned long now = sp->time; /* Make sure we're not lost in the past */
+  for (t = sp->head->next; t != sp->head; t = t->next) {
+       if (t->status >= PTHRATCH) {
+         now = t->start;
+       } else if (t->status == ACTION || t->status == LINKEDACTION) {
+         /* Allow ACTIONs to be annotated, but we won't mark them ready
+                for the next stage */
+
+         double xo = 0, yo;
+         double sx = SX;
+         double pose = SX/2;
+
+         /* time */
+         if (t->action == CATCH) { /* Throw-to-catch */
+               if (t->type == Empty) {
+                 now += (int) THROW_NULL_INTERVAL; /* failed catch is short */
+               } else {     /* successful catch */
+                 now += (int)(THROW_CATCH_INTERVAL);
+               }
+         } else { /* Catch-to-throw */
+               if(t->object != NULL) {
+                 now += (int) (CATCH_THROW_INTERVAL *
+                                               ObjectDefs[t->object->type].weight);
+               } else {
+                 now += (int) (CATCH_THROW_INTERVAL);
+               }
+         }
+
+         if(t->start == 0)
+               t->start = now;
+         else /* Concatenated performances may need clock resync */
+               now = t->start;
+
+         t->cx = 0;
+
+         /* space */
+         yo = 90;
+
+         /* Add room for the handle */
+         if(t->action == CATCH && t->object != NULL)
+               yo -= ObjectDefs[t->object->type].handle;
+
+         switch (t->posn) {
+         case '-': xo = sx - pose; break;
+         case '_':
+         case 'k':
+         case '+': xo = sx + pose; break;
+         case '~':
+         case '=': xo = - sx - pose; yo += pose; break;
+         case '^': xo = 0; yo += pose*2; break; /* clap */
+         default:
+               (void) fprintf(stderr, "juggle: unexpected posn %c\n", t->posn);
+               break;
+         }
+
+#ifdef _2DSpinsDontWorkIn3D
+         t->angle = (((t->hand == LEFT) ^
+                                  (t->posn == '+' || t->posn == '_' || t->posn == 'k' ))?
+                                       -1 : 1) * M_PI/2;
+#else
+         t->angle = -M_PI/2;
+#endif
 
-    /* Now work out the starting positions for the objects.  To do this we
-     * unweave the initial throws so we can pick out the individual threads. */
+         t->x = t->cx + ((t->hand == LEFT) ? xo : -xo);
+         t->y = yo;
 
-    pUsed = (unsigned char*) 
-        malloc(sizeof(unsigned char) * pPattern->MaxWeight);
-    pPattern->Objects = Objects;
-    pPattern->pObjectInfo = (OBJECT_POSITION*) calloc(
-        Objects, sizeof(OBJECT_POSITION));
+         /* Only mark complete if it was already linked */
+         if(t->status == LINKEDACTION) {
+               t->status = PTHRATCH;
+         }
+       }
+  }
+}
 
-    for (i = 0; i < pPattern->MaxWeight; i++)
-        pUsed[i] = 0;
 
-    for (i = 0; i < pPattern->MaxWeight; i++)
-    {
-        int w = pInfo[i % InfoLen].TimeInAir;
-        if (pUsed[i] == 0 &&  w != 0)
-        {
-            Objects--;
-            pPattern->pObjectInfo[Objects].TimeOffset = i;
-            pPattern->pObjectInfo[Objects].ThrowIndex = i % InfoLen;
-            pPattern->pObjectInfo[Objects].TotalTwist = 0.0f;
+/* Private physics functions */
 
-            if (pExtInfo != NULL && 
-                pExtInfo[i % Len].ObjectType != OBJECT_DEFAULT)
-            {
-                pPattern->pObjectInfo[Objects].ObjectType =
-                    pExtInfo[i % Len].ObjectType;
-            }
-            else
-            {
-                pPattern->pObjectInfo[Objects].ObjectType = (1 + random() % 3);
-            }
-        }
+/* Compute the spin-rate for a trajectory.  Different types of throw
+   (eg, regular thows, bounces, kicks, etc) have different spin
+   requirements.
 
-        if (w + i < pPattern->MaxWeight)
-            pUsed[w + i] = 1;
-        
-    }
+   type = type of object
+   h = trajectory of throwing hand (throws), or next throwing hand (catches)
+   old = earlier spin to consider
+   dt = time span of this trajectory
+   height = height of ball throw or 0 if based on old spin
+   turns = full club turns required during this operation
+   togo = partial club turns required to match hands
+*/
+static double
+spinrate(ObjType type, Trajectory *h, double old, double dt,
+                int height, int turns, double togo)
+{
+#ifdef _2DSpinsDontWorkIn3D
+  const int dir = (h->hand == LEFT) ^ (h->posn == '+')? -1 : 1;
+#else
+  const int dir = 1;
+#endif
 
-    pPattern->LeftHand.TimeOffset = pPattern->LeftHand.ThrowIndex = 0;
-    pPattern->RightHand.TimeOffset = pPattern->RightHand.ThrowIndex = 1;
-    
-    free(pUsed);
+  if(ObjectDefs[type].handle != 0) { /* Clubs */
+       return (dir * turns * 2 * M_PI + togo) / dt;
+  } else if(height == 0) { /* Balls already spinning */
+       return old/2;
+  } else { /* Balls */
+       return dir * NRAND(height*10)/20/ObjectDefs[type].weight * 2 * M_PI / dt;
+  }
 }
 
 
-static void ReleasePatternInfo(PATTERN_INFO* pPattern)
+/* compute the angle at the end of a spinning trajectory */
+static double
+end_spin(Trajectory *t)
 {
-    free(pPattern->pObjectInfo);
-    free(pPattern->pThrowInfo);
+  return t->angle + t->spin * (t->finish - t->start);
 }
 
-
-/*****************************************************************************
- *
- * Sites
- *
- ****************************************************************************/
-
-/* Generate a random site swap.  We assume that MaxWeight >= ObjCount and
- * Len >= MaxWeight. */
-static int* Generate(int Len, int MaxWeight, int ObjCount)
+/* Sets the initial angle of the catch following hand movement t to
+   the final angle of the throw n.  Also sets the angle of the
+   subsequent throw to the same angle plus half a turn. */
+static void
+match_spins_on_catch(Trajectory *t, Trajectory *n)
 {
-    int* Weight = (int*) calloc(Len, sizeof(int));
-    int* Used = (int*) calloc(Len, sizeof(int));
-    int* Options = (int*) calloc(MaxWeight + 1, sizeof(int));
-    int nOpts;
-    int i, j;
-
-    for (i = 0; i < Len; i++)
-        Weight[i] = Used[i] = -1;
-    
-    /* Pick out a unique the starting position for each object.  -2 is put in
-     * the Used array to signify this is a starting position. */
-
-    while (ObjCount > 0)
-    {
-        nOpts = 0;
-        for (j = 0; j < MaxWeight; j++)
-        {
-            if (Used[j] == -1)
-                Options[nOpts++] = j;
-        }
-
-        Used[Options[random() % nOpts]] = -2;
-        ObjCount--;
-    }
-    
-    /* Now work our way through the pattern moving throws into an available
-     * landing positions. */
-    for (i = 0; i < Len; i++)
-    {
-        if (Used[i] == -1)
-        {
-            /* patch up holes in the pattern to zeros */
-            Used[i] = 1;
-            Weight[i] = 0;
-        }
-        else
-        {
-            /* Work out the possible places where a throw can land and pick a 
-             * weight at random. */
-            int w;
-            nOpts = 0;
-
-            for (j = 0 ; j <= MaxWeight; j++)
-            {
-                if (Used[(i + j) % Len] == -1)
-                    Options[nOpts++] = j;
-            }
-            
-            w = Options[random() % nOpts];
-            Weight[i] = w;
-            
-            /* For starting throws make position available for a throw to land.
-             * Because Len >= MaxWeight these positions will only be filled when
-             * a throw wraps around the end of the site swap and therefore we
-             * can guarantee the all the object threads will be tied up. */
-            if (Used[i] == -2)
-                Used[i] = -1;
-            
-            Used[(i + w) % Len] = 1;
-        }
-    }
-
-    free(Options);
-    free(Used);
-    return Weight;
+  if(ObjectDefs[t->balllink->object->type].handle == 0) {
+       t->balllink->angle = end_spin(n);
+       if(t->balllink->handlink != NULL) {
+#ifdef _2DSpinsDontWorkIn3D
+         t->balllink->handlink->angle = t->balllink->angle + M_PI;
+#else
+         t->balllink->handlink->angle = t->balllink->angle;
+#endif
+       }
+  }
 }
 
-
-/* Routines to parse the Juggle Saver patterns.  These routines are a bit yucky
- * and make the big assumption that the patterns are well formed.  This is fine
- * as it stands because only 'good' ones are used but if the code is ever
- * extended to read arbitrary patterns (say from a file) then these routines
- * need to be beefed up. */
-
-/* The position text looks something like (x,y,z[,rot[,elev]])
- * where the stuff in square brackets is optional */
-
-static unsigned char ParsePositionText(const char** ppch, POS* pPos)
+static double
+find_bounce(jugglestruct *sp,
+                       double yo, double yf, double yc, double tc, double cor)
 {
-    const char* pch = *ppch;
-    unsigned char OK;
-    char szTemp[32];
-    char* pOut;
-    float* Nums[4];
-    int i;
-    
-    Nums[0] = &pPos->x;
-    Nums[1] = &pPos->y;
-    Nums[2] = &pPos->Rot;
-    Nums[3] = &pPos->Elev;
-
-
-    while (*pch == ' ')
-        pch++;
-    
-    OK = *pch == '(';
-    
-    if (OK)
-        pch++;
-
-    for (i = 0; OK && i < 4; i++)
-    {
-        pOut = szTemp;
-        while (*pch == ' ')
-            pch++;
-        while (*pch != ',' && *pch != '\0' && *pch != ')' && *pch != ' ')
-            *pOut++ = *pch++;
-        *pOut = '\0';
-
-        if (szTemp[0] != '\0')
-            *Nums[i] = (float) atof(szTemp);
-
-        while (*pch == ' ')
-            pch++;
-
-        if (i < 3)
-        {
-            if (*pch == ',')
-                pch++;
-            else if (*pch == ')')
-                break;
-            else
-                OK = 0;
-        }
-    }
-
-    if (OK)
-    {
-        while (*pch == ' ')
-            pch++;        
-        if (*pch == ')')
-            pch++;
-        else
-            OK = 0;
-    }
-
-    *ppch = pch;
-
-    return OK;
+  double tb, i, dy = 0;
+  const double e = 1; /* permissible error in yc */
+
+  /*
+       tb = time to bounce
+       yt = height at catch time after one bounce
+       one or three roots according to timing
+       find one by interval bisection
+  */
+  tb = tc;
+  for(i = tc / 2; i > 0.0001; i/=2){
+       double dt, yt;
+       if(tb == 0){
+         (void) fprintf(stderr, "juggle: bounce div by zero!\n");
+         break;
+       }
+       dy = (yf - yo)/tb + sp->Gr/2*tb;
+       dt = tc - tb;
+       yt = -cor*dy*dt + sp->Gr/2*dt*dt + yf;
+       if(yt < yc + e){
+         tb-=i;
+       }else if(yt > yc - e){
+         tb+=i;
+       }else{
+         break;
+       }
+  }
+  if(dy*THROW_CATCH_INTERVAL < -200) { /* bounce too hard */
+       tb = -1;
+  }
+  return tb;
 }
 
-
-static EXT_SITE_INFO* ParsePattern(const char* Site, int* pLen)
+static Trajectory*
+new_predictor(const Trajectory *t, int start, int finish, double angle)
 {
-    const char* pch = Site;
-    int Len = 0;
-    EXT_SITE_INFO* pInfo = NULL;
-    unsigned char OK = 1;
-
-    while (OK && *pch != 0)
-    {
-        EXT_SITE_INFO Info;
-        Info.Flags = 0;
+  Trajectory *n;
+  ADD_ELEMENT(Trajectory, n, t->prev);
+  if(n == NULL){
+       return NULL;
+  }
+  DUP_OBJECT(n, t);
+  n->divisions = t->divisions;
+  n->type = Ball;
+  n->status = PREDICTOR;
+
+  n->start = start;
+  n->finish = finish;
+  n->angle = angle;
+  return n;
+}
 
-        while (*pch == ' ') pch++;
+/* Turn abstract timings into physically appropriate object trajectories. */
+static Bool
+projectile(jugglestruct *sp)
+{
+  Trajectory *t;
+  const int yf = 0; /* Floor height */
+
+  for (t = sp->head->next; t != sp->head; t = t->next) {
+       if (t->status != PTHRATCH || t->action != THROW) {
+         continue;
+       } else if (t->balllink == NULL) { /* Zero Throw */
+         t->status = BPREDICTOR;
+       } else if (t->balllink->handlink == NULL) { /* Incomplete */
+         return True;
+       } else if(t->balllink == t->handlink) {
+         /* '2' height - hold on to ball.  Don't need to consider
+                flourishes, 'hands' will do that automatically anyway */
+
+         t->type = Full;
+         /* Zero spin to avoid wrist injuries */
+         t->spin = 0;
+         match_spins_on_catch(t, t);
+         t->dx = t->dy = 0;
+         t->status = BPREDICTOR;
+         continue;
+       } else {
+         if (t->posn == '_') { /* Bounce once */
+
+               const int tb = t->start +
+                 find_bounce(sp, t->y, (double) yf, t->balllink->y,
+                                         (double) (t->balllink->start - t->start),
+                                         ObjectDefs[t->object->type].cor);
+
+               if(tb < t->start) { /* bounce too hard */
+                 t->posn = '+'; /* Use regular throw */
+               } else {
+                 Trajectory *n; /* First (throw) trajectory. */
+                 double dt; /* Time span of a trajectory */
+                 double dy; /* Distance span of a follow-on trajectory.
+                                               First trajectory uses t->dy */
+                 /* dx is constant across both trajectories */
+                 t->dx = (t->balllink->x - t->x) / (t->balllink->start - t->start);
+
+                 { /* ball follows parabola down */
+                       n = new_predictor(t, t->start, tb, t->angle);
+                       if(n == NULL) return False;
+                       dt = n->finish - n->start;
+                       /* Ball rate 4, no flight or matching club turns */
+                       n->spin = spinrate(t->object->type, t, 0.0, dt, 4, 0, 0.0);
+                       t->dy = (yf - t->y)/dt - sp->Gr/2*dt;
+                       makeParabola(n, t->x, t->dx, t->y, t->dy, sp->Gr);
+                 }
+
+                 { /* ball follows parabola up */
+                       Trajectory *m = new_predictor(t, n->finish, t->balllink->start,
+                                                                                 end_spin(n));
+                       if(m == NULL) return False;
+                       dt = m->finish - m->start;
+                       /* Use previous ball rate, no flight club turns */
+                       m->spin = spinrate(t->object->type, t, n->spin, dt, 0, 0,
+                                                          t->balllink->angle - m->angle);
+                       match_spins_on_catch(t, m);
+                       dy = (t->balllink->y - yf)/dt - sp->Gr/2 * dt;
+                       makeParabola(m, t->balllink->x - t->dx * dt,
+                                                t->dx, (double) yf, dy, sp->Gr);
+                 }
+
+                 t->status = BPREDICTOR;
+                 continue;
+               }
+         } else if (t->posn == 'k') { /* Drop & Kick */
+               Trajectory *n; /* First (drop) trajectory. */
+               Trajectory *o; /* Second (rest) trajectory */
+               Trajectory *m; /* Third (kick) trajectory */
+               const int td = t->start + 2*THROW_CATCH_INTERVAL; /* Drop time */
+               const int tk = t->balllink->start - 5*THROW_CATCH_INTERVAL; /* Kick */
+               double dt, dy;
+
+               { /* Fall to ground */
+                 n = new_predictor(t, t->start, td, t->angle);
+                 if(n == NULL) return False;
+                 dt = n->finish - n->start;
+                 /* Ball spin rate 4, no flight club turns */
+                 n->spin = spinrate(t->object->type, t, 0.0, dt, 4, 0,
+                                                        t->balllink->angle - n->angle);
+                 t->dx = (t->balllink->x - t->x) / dt;
+                 t->dy = (yf - t->y)/dt - sp->Gr/2*dt;
+                 makeParabola(n, t->x, t->dx, t->y, t->dy, sp->Gr);
+               }
+
+               { /* Rest on ground */
+                 o = new_predictor(t, n->finish, tk, end_spin(n));
+                 if(o == NULL) return False;
+                 o->spin = 0;
+                 makeParabola(o, t->balllink->x, 0.0, (double) yf, 0.0, 0.0);
+               }
+
+               /* Kick up */
+               {
+                 m = new_predictor(t, o->finish, t->balllink->start, end_spin(o));
+                 if(m == NULL) return False;
+                 dt = m->finish - m->start;
+                 /* Match receiving hand, ball rate 4, one flight club turn */
+                 m->spin = spinrate(t->object->type, t->balllink->handlink, 0.0, dt,
+                                                        4, 1, t->balllink->angle - m->angle);
+                 match_spins_on_catch(t, m);
+                 dy = (t->balllink->y - yf)/dt - sp->Gr/2 * dt;
+                 makeParabola(m, t->balllink->x, 0.0, (double) yf, dy, sp->Gr);
+               }
+
+               t->status = BPREDICTOR;
+               continue;
+         }
+
+         /* Regular flight, no bounce */
+         { /* ball follows parabola */
+               double dt;
+               Trajectory *n = new_predictor(t, t->start,
+                                                                         t->balllink->start, t->angle);
+               if(n == NULL) return False;
+               dt = t->balllink->start - t->start;
+               /* Regular spin */
+               n->spin = spinrate(t->object->type, t, 0.0, dt, t->height, t->height/2,
+                                                  t->balllink->angle - n->angle);
+               match_spins_on_catch(t, n);
+               t->dx = (t->balllink->x - t->x) / dt;
+               t->dy = (t->balllink->y - t->y) / dt - sp->Gr/2 * dt;
+               makeParabola(n, t->x, t->dx, t->y, t->dy, sp->Gr);
+         }
+
+         t->status = BPREDICTOR;
+       }
+  }
+  return True;
+}
 
-        OK = *pch != '\0';
+/* Turn abstract hand motions into cubic splines. */
+static void
+hands(jugglestruct *sp)
+{
+  Trajectory *t, *u, *v;
 
-        if (OK)
-            Info.Weight = *pch >= 'A' ? *pch + 10 - 'A' : *pch - '0';
+  for (t = sp->head->next; t != sp->head; t = t->next) {
+       /* no throw => no velocity */
+       if (t->status != BPREDICTOR) {
+         continue;
+       }
 
-        /* parse object type */
-        if (OK)
-        {
-            pch++;
-            while (*pch == ' ') pch++;
+       u = t->handlink;
+       if (u == NULL) { /* no next catch */
+         continue;
+       }
+       v = u->handlink;
+       if (v == NULL) { /* no next throw */
+         continue;
+       }
 
-            if (*pch == 'b' || *pch == 'B')
-            {
-                Info.ObjectType = OBJECT_BALL;
-                pch++;
-            }
-            else if (*pch == 'c' || *pch == 'C')
-            {
-                Info.ObjectType = OBJECT_CLUB;
-                pch++;
-            }
-            else if (*pch == 'r' || *pch == 'R')
-            {
-                Info.ObjectType = OBJECT_RING;
-                pch++;
-            }
-            else if (*pch == 'd' || *pch == 'D')
-            {
-                Info.ObjectType = OBJECT_DEFAULT;
-                pch++;
-            }
-            else
-            {
-                Info.ObjectType = OBJECT_DEFAULT;
-            }
-        }
+       /* double spline takes hand from throw, thru catch, to
+          next throw */
 
-        /* Parse from position */
-        if (OK)
-        {
-            while (*pch == ' ') pch++;
-            if (*pch == '@')
-            {
-                pch++;
-                GetDefaultFromPosition(Len % 2, Info.Weight, &Info.FromPos);
-                Info.Flags |= HAS_FROM_POS;
-                OK = ParsePositionText(&pch, &Info.FromPos);
-            }
-        }
+       t->finish = u->start;
+       t->status = PREDICTOR;
 
-        /* Parse to position */
-        if (OK)
-        {
-            while (*pch == ' ') pch++;
-            if (*pch == '>')
-            {
-                pch++;
-                GetDefaultToPosition(Len % 2, Info.Weight, &Info.ToPos);
-                Info.Flags |= HAS_TO_POS;
-                OK = ParsePositionText(&pch, &Info.ToPos);
-            }
-        }
+       u->finish = v->start;
+       u->status = PREDICTOR;
 
-        /* Parse snatch */
-        if (OK)
-        {
-            while (*pch == ' ') pch++;
-            if (*pch == '/')
-            {
-                POS Snatch;
-                pch++;
-                Info.Flags |= HAS_SNATCH;
-                OK = ParsePositionText(&pch, &Snatch);
-                Info.SnatchX = Snatch.x;
-                Info.SnatchY = Snatch.y;
-            }
-        }
 
-        /* Parse Spins */
-        if (OK)
-        {
-            while (*pch == ' ') pch++;
-            if (*pch == '*')
-            {
-                pch++;
-                OK = 0;
-                Info.Spins = 0;
-                while (*pch >= '0' && *pch <= '9')
-                {
-                    OK = 1;
-                    Info.Spins = Info.Spins * 10 + *pch - '0';
-                    pch++;
-                }
-            }
-            else
-                Info.Spins = GetDefaultSpins(Info.Weight);
+       /* FIXME: These adjustments leave a small glitch when alternating
+          balls and clubs.  Just hope no-one notices.  :-) */
 
-            Info.Flags |= HAS_SPINS;
-        }
+       /* make sure empty hand spin matches the thrown object in case it
+          had a handle */
 
-        if (OK)
-        {
-            if (pInfo == NULL)
-                pInfo = (EXT_SITE_INFO*) malloc(sizeof(EXT_SITE_INFO));
-            else
-                pInfo = (EXT_SITE_INFO*) realloc(pInfo, (Len + 1) * sizeof(EXT_SITE_INFO));
+       t->spin = ((t->hand == LEFT)? -1 : 1 ) *
+         fabs((u->angle - t->angle)/(u->start - t->start));
 
-            pInfo[Len] = Info;
-            Len++;
-        }
-    }
-
-    if (!OK && pInfo != NULL)
-    {
-        free(pInfo);
-        pInfo = NULL;
-    }
+       u->spin = ((v->hand == LEFT) ^ (v->posn == '+')? -1 : 1 ) *
+         fabs((v->angle - u->angle)/(v->start - u->start));
 
-    *pLen = Len;
+       (void) makeSplinePair(&t->xp, &u->xp,
+                                                 t->x, t->dx, t->start,
+                                                 u->x, u->start,
+                                                 v->x, v->dx, v->start);
+       (void) makeSplinePair(&t->yp, &u->yp,
+                                                 t->y, t->dy, t->start,
+                                                 u->y, u->start,
+                                                 v->y, v->dy, v->start);
 
-    return pInfo;
+       t->status = PREDICTOR;
+  }
 }
 
-
-/*****************************************************************************
- *
- *  Juggle Saver Patterns
- *
- *****************************************************************************
- *
- * This is a selection of some of the more interesting patterns from taken
- * from the Juggle Saver sites.txt file.  I've only used patterns that I
- * originally created.
- */
-
-static const char* PatternText[] =
-{
-    "9b@(-2.5,0,-70,40)>(2.5,0,70)*2 1b@(1,0,10)>(-1,0,-10)",
-    
-    "3B@(1,-0.4)>(2,4.2)/(-2,1)3B@(-1.8,4.4)>(-2.1,0)",
-    
-    "7c@(-2,0,-20)>(1.2,0,-5)7c@(2,0,20)>(-1.2,0,5)",
-    
-    "3b@(-0.5,0)>(1.5,0) 3b@(0.5,0)>(-1.5,0) 3r@(-2.5,3,-90,80)>(2,1,90,30)"
-    "3b@(0.5,0)>(-1.5,0) 3b@(-0.5,0)>(1.5,0) 3r@(2.5,3,90,80)>(-2,1,-90,30)",
-    
-    "5c@(2,1.9,10)>(-1,1,10)5c@(2,1.8,10)>(-0.5,1.6,10)/(5,-1)"
-    "5c@(1.6,0.2,10)>(0,-1,10)/(9,-2)5c@(-2,1.9,-10)>(1,1,-10)"
-    "5c@(-2,1.8,-10)>(0.5,1.6,-10)/(-5,-1)5@(-1.6,0.2,-10)>(0,-1,-10)/(-9,-2)",
-    
-    "3c@(-1.5,0,0)>(-1.5,1,0)3c@(1.5,-0.2,0)>(1.5,-0.1,0)3c@(0,-0.5,0)>(0,1,0)"
-    "3@(-1.5,2,0)>(-1.5,-1,0)3@(1.5,0,0)>(1.5,1,0)3@(0,0,0)>(0,-0.5,0)",
-    
-    "9c@(-2.5,0,-70,40)>(2.5,0,70)*2 1c@(1,0,10)>(-1,0,-10)*0",
-    
-    "3c@(2,0.5,60,0)>(1.5,4,60,80)/(-6,-12)"
-    "3c@(-2,0.5,-60,0)>(-1.5,4,-60,80)/(6,-12)",
-    
-    "3c@(-0.2,0)>(1,0)3c@(0.2,0)>(-1,0)3c@(-2.5,2,-85,30)>(2.5,2,85,40)*2 "
-    "3@(0.2,0)>(-1,0) 3@(-0.2,0)>(1,0) 3@(2.5,2,85,30)>(-2.5,2,-85,40)*2",
-    
-    "3c@(-0.5,-0.5,20,-30)>(2.6,4.3,60,60)/(0,1)*1 "
-    "3c@(1.6,5.6,60,80)>(-2.6,0,-80)*0",
-    
-    "5c@(-0.3,0,10)>(1.2,0,10) 5c@(0.3,0,-10)>(-1.2,0,-10)"
-    "5c@(-0.3,0,10)>(1.2,0,10) 5c@(0.3,0,-10)>(-1.2,0,-10)"
-    "5c@(-3,3.5,-65,80)>(3,2.5,65) 5c@(0.3,0,-10)>(-1.2,0,-10)"
-    "5@(-0.3,0,10)>(1.2,0,10) 5@(0.3,0,-10)>(-1.2,0,-10)"
-    "5@(-0.3,0,10)>(1.2,0,10)5@(3,3.5,65,80)>(-3,2.5,-65)"
-};
-
-
-/*****************************************************************************
- *
- * Rendering
- *
- *****************************************************************************/
-
-static const float FOV = 70.0f;
-static const float BodyCol[] = {0.6f, 0.6f, 0.45f, 1.0f};
-static const float HandleCol[] = {0.45f, 0.45f, 0.45f, 1.0f};
-static const float LightPos[] = {0.0f, 200.0f, 400.0f, 1.0f};
-static const float LightDiff[] = {1.0f, 1.0f, 1.0f, 0.0f};
-static const float LightAmb[] = {0.02f, 0.02f, 0.02f, 0.0f};
-static const float ShoulderPos[3] = {0.95f, 2.1f, 1.7f};
-static const float DiffCol[] = {1.0f, 0.0f, 0.0f, 1.0f};
-static const float SpecCol[] = {1.0f, 1.0f, 1.0f, 1.0f};
-
-static const float BallRad = 0.34f;
-static const float UArmLen = 1.9f;
-static const float LArmLen = 2.3f;
-
-#define DL_BALL 0
-#define DL_CLUB 1
-#define DL_RING 2
-#define DL_TORSO 3
-#define DL_FOREARM 4
-#define DL_UPPERARM 5
-
-static const float AltCols[][4] =
-{
-    {0.0f, 0.7f, 0.0f, 1.0f},
-    {0.0f, 0.0f, 0.9f, 1.0f},
-    {0.0f, 0.9f, 0.9f, 1.0f},
-    {0.45f, 0.0f, 0.9f, 1.0f},
-    {0.9f, 0.45f, 0.0f, 1.0f},
-    {0.0f, 0.45f, 0.9f, 1.0f},
-    {0.9f, 0.0f, 0.9f, 1.0f},
-    {0.9f, 0.9f, 0.0f, 1.0f},
-    {0.9f, 0.0f, 0.45f, 1.0f},
-    {0.45f, 0.15f, 0.6f, 1.0f}, 
-    {0.9f, 0.0f, 0.0f, 1.0f},
-    {0.0f, 0.9f, 0.45f, 1.0f},
-};
-
-static const float Cols[][4] =
+/* Given target x, y find_elbow puts hand at target if possible,
+ * otherwise makes hand point to the target */
+static void
+find_elbow(int armlength, DXPoint *h, DXPoint *e, DXPoint *p, DXPoint *s,
+                  int z)
 {
-    {0.9f, 0.0f, 0.0f, 1.0f},  /*  0 */
-    {0.0f, 0.7f, 0.0f, 1.0f},  /*  1 */
-    {0.0f, 0.0f, 0.9f, 1.0f},  /*  2 */
-    {0.0f, 0.9f, 0.9f, 1.0f},  /*  3 */
-    {0.9f, 0.0f, 0.9f, 1.0f},  /*  4 */
-    {0.9f, 0.9f, 0.0f, 1.0f},  /*  5 */
-    {0.9f, 0.45f, 0.0f, 1.0f}, /*  6 */
-    {0.9f, 0.0f, 0.45f, 1.0f}, /*  7 */
-    {0.45f, 0.9f, 0.0f, 1.0f}, /*  8 */
-    {0.0f, 0.9f, 0.45f, 1.0f}, /*  9 */
-    {0.45f, 0.0f, 0.9f, 1.0f}, /* 10 */
-    {0.0f, 0.45f, 0.9f, 1.0f}, /* 11 */
-};
-
-static int InitGLDisplayLists(void);
+  double r, h2, t;
+  double x = p->x - s->x;
+  double y = p->y - s->y;
+  h2 = x*x + y*y + z*z;
+  if (h2 > 4 * armlength * armlength) {
+       t = armlength/sqrt(h2);
+       e->x = t*x + s->x;
+       e->y = t*y + s->y;
+       h->x = 2 * t * x + s->x;
+       h->y = 2 * t * y + s->y;
+  } else {
+       r = sqrt((double)(x*x + z*z));
+       t = sqrt(4 * armlength * armlength / h2 - 1);
+       e->x = x*(1 + y*t/r)/2 + s->x;
+       e->y = (y - r*t)/2 + s->y;
+       h->x = x + s->x;
+       h->y = y + s->y;
+  }
+}
 
 
-static void InitGLSettings(RENDER_STATE* pState, int WireFrame)
+/* NOTE: returned x, y adjusted for arm reach */
+static void
+reach_arm(ModeInfo * mi, Hand side, DXPoint *p)
 {
-    memset(pState, 0, sizeof(RENDER_STATE));
-    
-    pState->trackball = gltrackball_init ();
-
-    if (WireFrame)
-        glPolygonMode(GL_FRONT, GL_LINE);
-    
-    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
-
-    glLightfv(GL_LIGHT0, GL_POSITION, LightPos);
-    glLightfv(GL_LIGHT0, GL_DIFFUSE, LightDiff);
-    glLightfv(GL_LIGHT0, GL_AMBIENT, LightAmb);
-    
-    glEnable(GL_SMOOTH);
-    glEnable(GL_LIGHTING);
-    glEnable(GL_LIGHT0);
-
-    glDepthFunc(GL_LESS);
-    glEnable(GL_DEPTH_TEST);
-
-    glCullFace(GL_BACK);
-    glEnable(GL_CULL_FACE);
-    
-    pState->DLStart = InitGLDisplayLists();
+  jugglestruct *sp = &juggles[MI_SCREEN(mi)];
+  DXPoint h, e;
+  find_elbow(40, &h, &e, p, &sp->arm[1][side][SHOULDER], 25);
+  *p = sp->arm[1][side][HAND] = h;
+  sp->arm[1][side][ELBOW] = e;
 }
 
-
-static void SetCamera(RENDER_STATE* pState)
+#if DEBUG
+/* dumps a human-readable rendition of the current state of the juggle
+   pipeline to stderr for debugging */
+static void
+dump(jugglestruct *sp)
 {
-    /* Try to work out a sensible place to put the camera so that more or less
-     * the whole juggling pattern fits into the screen. We assume that the
-        * pattern is height limited (i.e. if we get the height right then the width
-        * will be OK).  This is a pretty good assumption given that the screen
-        * tends to wider than high, and that a juggling pattern is normally much
-        * higher than wide.
-     *
-     * If I could draw a diagram here then it would be much easier to
-     * understand but my ASCII-art skills just aren't up to it.  
-     *
-     * Basically we estimate a bounding volume for the juggler and objects 
-     * throughout the pattern.  We don't fully account for the fact that the
-     * juggler moves across the stage in an epicyclic-like motion and instead
-     * use the near and far planes in x-y (with z = +/- w).  We also
-     * assume that the scene is centred at x=0, this reduces our task to finding
-     * a bounding rectangle.  Finally we need to make an estimate of the
-     * height - for this we work out the max height of a standard throw or max
-     * weight from the pattern; we then do a bit of adjustment to account for
-     * a throw occurring at non-zero y values.
-     *
-     * Next we work out the best way to fit this rectangle into the perspective
-     * transform.  Based on the angle of elevation (+ve angle looks down) and
-     * the FOV we can work out whether it's the near or far corners that are
-     * the extreme points.  And then trace back from them to find the eye
-     * point.
-     *
-     */
-     
-    float ElevRad = pState->CameraElev * PI / 180.0f;
-    float w = 3.0f;
-    float cy, cz;
-    float ey, ez;
-    float d;
-    float H = 0.0f;
-    int i;
-    float a;
-    
-    float tz, ty, ta;
-    float bz, by, ba;
-    const PATTERN_INFO* pPattern = pState->pPattern;
-
-    glMatrixMode(GL_PROJECTION);
-    glLoadIdentity();
-        
-    for (i = 0; i < pPattern->ThrowLen; i++)
-        H = max(H, pPattern->pThrowInfo[i].FromPos.y);
-        
-    H += pPattern->Height;
-    
-    ElevRad = pState->CameraElev * PI / 180.0f;
-    
-    /* ta is the angle from a point on the top of the bounding area to the eye
-     * similarly ba is the angle from a point on the bottom. */
-    ta = (pState->CameraElev  - (FOV - 10.0f) / 2.0f) * PI / 180.0f;
-    ba = (pState->CameraElev  + (FOV - 10.0f) / 2.0f) * PI / 180.0f;
-
-    /* tz and bz hold the z location of the top and bottom extreme points.
-     * For the top, if the angle to the eye location is positive then the
-     * extreme point is with far z corner (the camera looks in -ve z).
-     * The logic is reserved for the bottom. */
-    tz = ta >= 0.0f ? -w : w;
-    bz = ba >= 0.0f ? w : -w;
-    
-    ty = H;
-    by = -1.0f;
-    
-    /* Solve of the eye location by using a bit of geometry.
-     * We know the eye lies on intersection of two lines.  One comes from the
-     * top and other from the bottom. Giving two equations:
-     *   ez = tz + a * cos(ta) = bz + b * cos(ba)
-     *   ey = ty + a * sin(ta) = by + b * sin(ba)
-     * We don't bother to solve for b and use Crammer's rule to get
-     *         | bz-tz  -cos(ba) |
-     *         | by-ty  -sin(ba) |     
-     *   a =  ----------------------
-     *        | cos(ta)   -cos(ba) |
-     *        | sin(ta)   -sin(ba) |
-     */
-    d = cosf(ba) * sinf(ta) - cosf(ta) * sinf(ba);
-    a = (cosf(ba) * (by - ty) - sinf(ba) * (bz - tz)) / d;
-    
-    ey = ty + a * sinf(ta);
-    ez = tz + a * cosf(ta);
-    
-    /* now work back from the eye point to get the lookat location */
-    cz = 0.0;
-    cy = ey - ez * tanf(ElevRad);
-    
-    /* use the distance from the eye to the scene centre to get a measure
-     * of what the far clipping should be.  We then add on a bit more to be 
-     * comfortable */
-    d = sqrtf(ez * ez + (cy - ey) * (cy - ey));
-    
-    gluPerspective(FOV, pState->AspectRatio, 0.1f, d + 20.0f);
-    gluLookAt(0.0, ey, ez, 0.0, cy, cz, 0.0, 1.0, 0.0);
-
-    glMatrixMode(GL_MODELVIEW);
+  Trajectory *t;
+  for (t = sp->head->next; t != sp->head; t = t->next) {
+       switch (t->status) {
+       case ATCH:
+         (void) fprintf(stderr, "%p a %c%d\n", (void*)t, t->posn, t->adam);
+         break;
+       case THRATCH:
+         (void) fprintf(stderr, "%p T %c%d %s\n", (void*)t, t->posn, t->height,
+                                        t->pattern == NULL?"":t->pattern);
+         break;
+       case ACTION:
+         if (t->action == CATCH)
+           (void) fprintf(stderr, "%p A %c%cC\n",
+                                        (void*)t, t->posn,
+                                        t->hand ? 'R' : 'L');
+         else
+           (void) fprintf(stderr, "%p A %c%c%c%d\n",
+                                        (void*)t, t->posn,
+                                        t->hand ? 'R' : 'L',
+                                        (t->action == THROW)?'T':'N',
+                                        t->height);
+         break;
+       case LINKEDACTION:
+         (void) fprintf(stderr, "%p L %c%c%c%d %d %p %p\n",
+                                        (void*)t, t->posn,
+                                        t->hand?'R':'L',
+                                        (t->action == THROW)?'T':(t->action == CATCH?'C':'N'),
+                                        t->height, t->object == NULL?0:t->object->color,
+                                        (void*)t->handlink, (void*)t->balllink);
+         break;
+       case PTHRATCH:
+         (void) fprintf(stderr, "%p O %c%c%c%d %d %2d %6lu %6lu\n",
+                                        (void*)t, t->posn,
+                                        t->hand?'R':'L',
+                                        (t->action == THROW)?'T':(t->action == CATCH?'C':'N'),
+                                        t->height, t->type, t->object == NULL?0:t->object->color,
+                                        t->start, t->finish);
+         break;
+       case BPREDICTOR:
+         (void) fprintf(stderr, "%p B %c      %2d %6lu %6lu %g\n",
+                                        (void*)t, t->type == Ball?'b':t->type == Empty?'e':'f',
+                                        t->object == NULL?0:t->object->color,
+                                        t->start, t->finish, t->yp.c);
+         break;
+       case PREDICTOR:
+         (void) fprintf(stderr, "%p P %c      %2d %6lu %6lu %g\n",
+                                        (void*)t, t->type == Ball?'b':t->type == Empty?'e':'f',
+                                        t->object == NULL?0:t->object->color,
+                                        t->start, t->finish, t->yp.c);
+         break;
+       default:
+         (void) fprintf(stderr, "%p: status %d not implemented\n",
+                                        (void*)t, t->status);
+         break;
+       }
+  }
+  (void) fprintf(stderr, "---\n");
 }
+#endif
 
-
-static void ResizeGL(RENDER_STATE* pState, int w, int h)
+static int get_num_balls(const char *j)
 {
-    glViewport(0, 0, w, h);
-    pState->AspectRatio = (float) w / h;
-    SetCamera(pState);
+  int balls = 0;
+  const char *p;
+  int h = 0;
+  if (!j) abort();
+  for (p = j; *p; p++) {
+       if (*p >= '0' && *p <='9') { /* digit */
+         h = 10*h + (*p - '0');
+       } else {
+         if (h > balls) {
+               balls = h;
+         }
+         h = 0;
+       }
+  }
+  return balls;
 }
 
-
-/* Determine the angle at the vertex of a triangle given the length of the
- * three sides. */
-
-static double CosineRule(double a, double b, double c)
+static int
+compare_num_balls(const void *p1, const void *p2)
 {
-    double cosang = (a * a + b * b - c * c) / (2 * a * b);
-    /* If lengths don't form a proper triangle return something sensible.
-     * This typically happens with patterns where the juggler reaches too 
-     * far to get hold of an object. */
-    if (cosang < -1.0 || cosang > 1.0)
-        return 0;
-    else
-        return 180.0 * acos(cosang) / PI;
+  int i, j;
+  i = get_num_balls(((patternstruct*)p1)->pattern);
+  j = get_num_balls(((patternstruct*)p2)->pattern);
+  if (i > j) {
+       return (1);
+  } else if (i < j) {
+       return (-1);
+  } else {
+       return (0);
+  }
 }
 
 
-/* Spheres for the balls are generated by subdividing each triangle face into
- * four smaller triangles.  We start with an octahedron (8 sides) and repeat the
- * process a number of times.  The result is a mesh that can be split into four
- * panels (like beanbags) and is smoother than the normal stacks and slices
- * approach. */
+/**************************************************************************
+ *                        Rendering Functions                             *
+ *                                                                        *
+ **************************************************************************/
 
-static void InterpolateVertex(
-    const float* v1, const float* v2, float t, float* result)
+static int
+show_arms(ModeInfo * mi)
 {
-    result[0] = v1[0] * (1.0f - t) + v2[0] * t;
-    result[1] = v1[1] * (1.0f - t) + v2[1] * t;
-    result[2] = v1[2] * (1.0f - t) + v2[2] * t;
-}
+  int polys = 0;
+  jugglestruct *sp = &juggles[MI_SCREEN(mi)];
+  unsigned int i, j;
+  Hand side;
+  XPoint a[countof(sp->arm[0][0])];
+  int slices = 12;
+  int thickness = 7;
+  int soffx = 10;
+  int soffy = 11;
+
+  j = 1;
+  for(side = LEFT; side <= RIGHT; side = (Hand)((int)side + 1)) {
+       /* Translate into device coords */
+       for(i = 0; i < countof(a); i++) {
+         a[i].x = (short)(SCENE_WIDTH/2 + sp->arm[j][side][i].x*sp->scale);
+         a[i].y = (short)(SCENE_HEIGHT  - sp->arm[j][side][i].y*sp->scale);
+         if(j == 1)
+               sp->arm[0][side][i] = sp->arm[1][side][i];
+       }
+
+        glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, body_color_1);
+
+        /* Upper arm */
+        polys += tube (a[2].x - (side == LEFT ? soffx : -soffx), a[2].y + soffy, 0,
+                       a[1].x, a[1].y, ARMLENGTH/2,
+                       thickness, 0, slices,
+                       True, True, MI_IS_WIREFRAME(mi));
+
+        /* Lower arm */
+        polys += tube (a[1].x, a[1].y, ARMLENGTH/2,
+                       a[0].x, a[0].y, ARMLENGTH,
+                       thickness * 0.8, 0, slices,
+                       True, True, MI_IS_WIREFRAME(mi));
+
+        glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, body_color_2);
+
+        /* Shoulder */
+        glPushMatrix();
+        glTranslatef (a[2].x - (side == LEFT ? soffx : -soffx), 
+                      a[2].y + soffy, 
+                      0);
+        glScalef(9, 9, 9);
+        polys += unit_sphere(slices, slices, MI_IS_WIREFRAME(mi));
+        glPopMatrix();
 
+        /* Elbow */
+        glPushMatrix();
+        glTranslatef (a[1].x, a[1].y, ARMLENGTH/2);
+        glScalef(4, 4, 4);
+        polys += unit_sphere(slices, slices, MI_IS_WIREFRAME(mi));
+        glPopMatrix();
 
-static void SetGLVertex(const float* v, float rad)
-{
-    float Len = sqrtf(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
+        /* Hand */
+        glPushMatrix();
+        glTranslatef (a[0].x, a[0].y, ARMLENGTH);
+        glScalef(8, 8, 8);
+        polys += unit_sphere(slices, slices, MI_IS_WIREFRAME(mi));
+        glPopMatrix();
 
-    if (Len >= 1.0e-10f)
-    {
-        glNormal3f(v[0] / Len, v[1] / Len, v[2] / Len);
-        glVertex3f(rad * v[0] / Len, rad * v[1] / Len, rad * v[2] / Len);
-    }
-    else
-        glVertex3fv(v);
+  }
+  return polys;
 }
 
-
-static void SphereSegment(
-    const float* v1, const float* v2, const float* v3, float r, int Levels)
+static int
+show_figure(ModeInfo * mi, Bool init)
 {
-    int i, j;
+  int polys = 0;
+  jugglestruct *sp = &juggles[MI_SCREEN(mi)];
+  /*XPoint p[7];*/
+  int i;
+
+  /*      +-----+ 9
+          |  6  |
+       10 +--+--+
+       2 +---+---+ 3
+          \  5  /
+           \   /
+            \ /
+           1 +
+            / \
+           /   \
+        0 +-----+ 4
+          |     |
+          |     |
+          |     |
+        7 +     + 8
+  */
+
+  /* #### most of this is unused now */
+  static const XPoint figure[] = {
+       { 15,  70}, /* 0  Left Hip */
+       {  0,  90}, /* 1  Waist */
+       { SX, 130}, /* 2  Left Shoulder */
+       {-SX, 130}, /* 3  Right Shoulder */
+       {-15,  70}, /* 4  Right Hip */
+       {  0, 130}, /* 5  Neck */
+       {  0, 140}, /* 6  Chin */
+       { SX,   0}, /* 7  Left Foot */
+       {-SX,   0}, /* 8  Right Foot */
+       {-17, 174}, /* 9  Head1 */
+       { 17, 140}, /* 10 Head2 */
+  };
+  XPoint a[countof(figure)];
+  GLfloat gcolor[4] = { 1, 1, 1, 1 };
+
+  /* Translate into device coords */
+  for(i = 0; i < countof(figure); i++) {
+       a[i].x = (short)(SCENE_WIDTH/2 + (sp->cx + figure[i].x)*sp->scale);
+       a[i].y = (short)(SCENE_HEIGHT - figure[i].y*sp->scale);
+  }
+
+  glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, gcolor);
+
+  {
+    GLfloat scale = ((GLfloat) a[10].x - a[9].x) / 2;
+    int slices = 12;
 
-    for (i = 0; i < Levels; i++)
+    glPushMatrix();
     {
-        float A[3], B[3], C[3], D[3];
+      glTranslatef(a[6].x, a[6].y - scale, 0);
+      glScalef(scale, scale, scale);
+
+      /* Head */
+      glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, body_color_1);
+      glPushMatrix();
+      scale = 0.75;
+      glScalef(scale, scale, scale);
+      glTranslatef(0, 0.3, 0);
+      glPushMatrix();
+      glTranslatef(0, 0, 0.35);
+      polys += tube (0, 0, 0,
+                     0, 1.1, 0,
+                     0.64, 0,
+                     slices, True, True, MI_IS_WIREFRAME(mi));
+      glPopMatrix();
+      glScalef(0.9, 0.9, 1);
+      polys += unit_sphere(2*slices, 2*slices, MI_IS_WIREFRAME(mi));
+      glPopMatrix();
+
+      /* Neck */
+      glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, body_color_2);
+      glTranslatef(0, 1.1, 0);
+      glPushMatrix();
+      scale = 0.35;
+      glScalef(scale, scale, scale);
+      polys += unit_sphere(slices, slices, MI_IS_WIREFRAME(mi));
+      glPopMatrix();
+
+      /* Torso */
+      glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, body_color_1);
+      glTranslatef(0, 1.1, 0);
+      glPushMatrix();
+      glScalef(0.9, 1.0, 0.9);
+      polys += unit_sphere(slices, slices, MI_IS_WIREFRAME(mi));
+      glPopMatrix();
+
+      /* Belly */
+      glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, body_color_2);
+      glTranslatef(0, 1.0, 0);
+      glPushMatrix();
+      scale = 0.6;
+      glScalef(scale, scale, scale);
+      polys += unit_sphere(slices, slices, MI_IS_WIREFRAME(mi));
+      glPopMatrix();
+
+      /* Hips */
+      glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, body_color_1);
+      glTranslatef(0, 0.8, 0);
+      glPushMatrix();
+      scale = 0.85;
+      glScalef(scale, scale, scale);
+      polys += unit_sphere(slices, slices, MI_IS_WIREFRAME(mi));
+      glPopMatrix();
+
+
+      /* Legs */
+      glTranslatef(0, 0.7, 0);
+
+      for (i = -1; i <= 1; i += 2) {
+        glPushMatrix();
+
+        glRotatef (i*10, 0, 0, 1);
+        glTranslatef(-i*0.65, 0, 0);
         
-        InterpolateVertex(v3, v1, (float) i / Levels, D);
-        InterpolateVertex(v3, v1, (float)(i + 1) / Levels, A);
-        InterpolateVertex(v3, v2, (float)(i + 1) / Levels, B);
-        InterpolateVertex(v3, v2, (float) i / Levels, C);
+        /* Hip socket */
+        glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, body_color_2);
+        scale = 0.45;
+        glScalef(scale, scale, scale);
+        polys += unit_sphere(slices, slices, MI_IS_WIREFRAME(mi));
+
+        /* Thigh */
+        glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, body_color_1);
+        glPushMatrix();
+        glTranslatef(0, 0.6, 0);
+        polys += tube (0, 0, 0,
+                       0, 3.5, 0,
+                       1, 0,
+                       slices, True, True, MI_IS_WIREFRAME(mi));
+        glPopMatrix();
 
-        glBegin(GL_TRIANGLE_STRIP);
+        /* Knee */
+        glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, body_color_2);
+        glPushMatrix();
+        glTranslatef(0, 4.4, 0);
+        scale = 0.7;
+        glScalef(scale, scale, scale);
+        polys += unit_sphere(slices, slices, MI_IS_WIREFRAME(mi));
+        glPopMatrix();
 
-        SetGLVertex(B, r);
-        SetGLVertex(C, r);
-        
-        for (j = 1; j <= i; j++)
-        {
-            float v[3];
+        /* Calf */
+        glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, body_color_1);
+        glPushMatrix();
+        glTranslatef(0, 4.7, 0);
+        polys += tube (0, 0, 0,
+                       0, 4.7, 0,
+                       0.8, 0,
+                       slices, True, True, MI_IS_WIREFRAME(mi));
+        glPopMatrix();
 
-            InterpolateVertex(B, A, (float) j / (i + 1), v);
-            SetGLVertex(v, r);
+        /* Ankle */
+        glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, body_color_2);
+        glPushMatrix();
+        glTranslatef(0, 9.7, 0);
+        scale = 0.5;
+        glScalef(scale, scale, scale);
+        polys += unit_sphere(slices, slices, MI_IS_WIREFRAME(mi));
+        glPopMatrix();
 
-            InterpolateVertex(C, D, (float) j / i, v);
-            SetGLVertex(v, r);
-        }
+        /* Foot */
+        glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, body_color_1);
+        glPushMatrix();
+        glRotatef (-i*10, 0, 0, 1);
+        glTranslatef(-i*1.75, 9.7, 0.9);
+
+        glScalef (0.4, 1, 1);
+        polys += tube (0, 0, 0,
+                       0, 0.6, 0,
+                       1.9, 0,
+                       slices*4, True, True, MI_IS_WIREFRAME(mi));
+        glPopMatrix();
 
-        SetGLVertex(A, r);
-        
-        glEnd();
+        glPopMatrix();
+      }
     }
+    glPopMatrix();
+  }
+
+  sp->arm[1][LEFT][SHOULDER].x = sp->cx + figure[2].x;
+  sp->arm[1][RIGHT][SHOULDER].x = sp->cx + figure[3].x;
+  if(init) {
+       /* Initialise arms */
+       unsigned int i;
+       for(i = 0; i < 2; i++){
+         sp->arm[i][LEFT][SHOULDER].y = figure[2].y;
+         sp->arm[i][LEFT][ELBOW].x = figure[2].x;
+         sp->arm[i][LEFT][ELBOW].y = figure[1].y;
+         sp->arm[i][LEFT][HAND].x = figure[0].x;
+         sp->arm[i][LEFT][HAND].y = figure[1].y;
+         sp->arm[i][RIGHT][SHOULDER].y = figure[3].y;
+         sp->arm[i][RIGHT][ELBOW].x = figure[3].x;
+         sp->arm[i][RIGHT][ELBOW].y = figure[1].y;
+         sp->arm[i][RIGHT][HAND].x = figure[4].x;
+         sp->arm[i][RIGHT][HAND].y = figure[1].y;
+       }
+  }
+  return polys;
 }
 
+typedef struct { GLfloat x, y, z; } XYZ;
 
-/* OK, this function is a bit of misnomer, it only draws half a sphere.  Indeed
- * it draws two panels and allows us to colour this one way,  then draw the
- * same shape again rotated 90 degrees in a different colour.  Resulting in what
- * looks like a four-panel beanbag in two complementary colours. */
-static void DrawSphere(float rad)
+/* lifted from sphere.c */
+static int
+striped_unit_sphere (int stacks, int slices, 
+                     int stripes, 
+                     GLfloat *color1, GLfloat *color2,
+                     int wire_p)
 {
-    int Levels = 4;
-    float v1[3], v2[3], v3[3];
-    
-    v1[0] = 1.0f, v1[1] = 0.0f; v1[2] = 0.0f;
-    v2[0] = 0.0f, v2[1] = 1.0f; v2[2] = 0.0f;
-    v3[0] = 0.0f, v3[1] = 0.0f; v3[2] = 1.0f;
-    SphereSegment(v1, v2, v3, rad, Levels);
-    
-    v2[1] = -1.0f;
-    SphereSegment(v2, v1, v3, rad, Levels);
-    
-    v1[0] = v3[2] = -1.0f;
-    SphereSegment(v2, v1, v3, rad, Levels);
-
-    v2[1] = 1.0f;
-    SphereSegment(v1, v2, v3, rad, Levels);
-}
-
+  int polys = 0;
+  int i,j;
+  double theta1, theta2, theta3;
+  XYZ e, p;
+  XYZ la = { 0, 0, 0 }, lb = { 0, 0, 0 };
+  XYZ c = {0, 0, 0};  /* center */
+  double r = 1.0;     /* radius */
+  int stacks2 = stacks * 2;
+
+  if (r < 0)
+    r = -r;
+  if (slices < 0)
+    slices = -slices;
+
+  if (slices < 4 || stacks < 2 || r <= 0)
+    {
+      glBegin (GL_POINTS);
+      glVertex3f (c.x, c.y, c.z);
+      glEnd();
+      return 1;
+    }
 
-static void DrawRing(void)
-{
-    const int Facets = 22;
-    const float w = 0.1f;
-    GLUquadric* pQuad = gluNewQuadric();
-    glRotatef(90.0f, 0.0f, 1.0f, 0.0f);
-    glTranslatef(0.0f, 0.0f, -w / 2.0f);
+  glFrontFace(GL_CW);
 
-    gluCylinder(pQuad, 1.0f, 1.0f, w, Facets, 1);
-    gluQuadricOrientation(pQuad, GLU_INSIDE);
+  for (j = 0; j < stacks; j++)
+    {
+      theta1 = j       * (M_PI+M_PI) / stacks2 - M_PI_2;
+      theta2 = (j + 1) * (M_PI+M_PI) / stacks2 - M_PI_2;
 
-    gluCylinder(pQuad, 0.7f, 0.7f, w, Facets, 1);
-    gluQuadricOrientation(pQuad, GLU_OUTSIDE);
+      glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE,
+                    ((j == 0 || j == stacks-1 ||
+                     j % (stacks / (stripes+1)))
+                     ? color1 : color2));
 
-    glTranslatef(0.0f, 0.0f, w);
-    gluDisk(pQuad, 0.7, 1.0f, Facets, 1);
+      glBegin (wire_p ? GL_LINE_LOOP : GL_TRIANGLE_STRIP);
+      for (i = 0; i <= slices; i++)
+        {
+          theta3 = i * (M_PI+M_PI) / slices;
 
-    glRotatef(180.0f, 0.0f, 1.0f, 0.0f);
-    glTranslatef(0.0f, 0.0f, w);
-    gluDisk(pQuad, 0.7, 1.0f, Facets, 1);
+          if (wire_p && i != 0)
+            {
+              glVertex3f (lb.x, lb.y, lb.z);
+              glVertex3f (la.x, la.y, la.z);
+            }
 
-    gluDeleteQuadric(pQuad);
+          e.x = cos (theta2) * cos(theta3);
+          e.y = sin (theta2);
+          e.z = cos (theta2) * sin(theta3);
+          p.x = c.x + r * e.x;
+          p.y = c.y + r * e.y;
+          p.z = c.z + r * e.z;
+
+          glNormal3f (e.x, e.y, e.z);
+          glTexCoord2f (i       / (double)slices,
+                        2*(j+1) / (double)stacks2);
+          glVertex3f (p.x, p.y, p.z);
+          if (wire_p) la = p;
+
+          e.x = cos(theta1) * cos(theta3);
+          e.y = sin(theta1);
+          e.z = cos(theta1) * sin(theta3);
+          p.x = c.x + r * e.x;
+          p.y = c.y + r * e.y;
+          p.z = c.z + r * e.z;
+
+          glNormal3f (e.x, e.y, e.z);
+          glTexCoord2f (i   / (double)slices,
+                        2*j / (double)stacks2);
+          glVertex3f (p.x, p.y, p.z);
+          if (wire_p) lb = p;
+          polys++;
+        }
+      glEnd();
+    }
+  return polys;
 }
 
 
-/* The club follows a 'circus club' design i.e. it has stripes running down the
- * body.  The club is draw such that the one stripe uses the current material
- * and the second stripe the standard silver colour. */
 
-static void DrawClub(void)
+static int
+show_ball(ModeInfo *mi, unsigned long color, Trace *s)
 {
-    const float r[4] = {0.06f, 0.1f, 0.34f, 0.34f / 2.0f};
-    const float z[4] = {-0.4f, 0.6f, 1.35f, 2.1f};
-    float na[4];
-    const int n = 18;
-    int i, j;
-    GLUquadric* pQuad;
-
-    na[0] = (float) atan((r[1] - r[0]) / (z[1] - z[0]));
-    na[1] = (float) atan((r[2] - r[1]) / (z[2] - z[1]));
-    na[2] = (float) atan((r[3] - r[1]) / (z[3] - z[1]));
-    na[3] = (float) atan((r[3] - r[2]) / (z[3] - z[2]));
-
-    for (i = 0; i < n; i += 2)
-    {
-        float a1 = i * PI * 2.0f / n;
-        float a2 = (i + 1) * PI * 2.0f / n;
-
-        glBegin(GL_TRIANGLE_STRIP);
-            for (j = 1; j < 4; j++)
-            {
-                glNormal3f(cosf(na[j]) * cosf(a1),
-                    cosf(na[j]) * sinf(a1), sinf(na[j]));
-
-                glVertex3f(r[j] * cosf(a1), r[j] * sinf(a1), z[j]);
+  int polys = 0;
+  jugglestruct *sp = &juggles[MI_SCREEN(mi)];
+  /*int offset = (int)(s->angle*64*180/M_PI);*/
+  short x = (short)(SCENE_WIDTH/2 + s->x * sp->scale);
+  short y = (short)(SCENE_HEIGHT - s->y * sp->scale);
+  GLfloat gcolor1[4] = { 0, 0, 0, 1 };
+  GLfloat gcolor2[4] = { 0, 0, 0, 1 };
+  int slices = 24;
+
+  /* Avoid wrapping */
+  if(s->y*sp->scale >  SCENE_HEIGHT * 2) return 0;
+
+  gcolor1[0] = mi->colors[color].red   / 65536.0;
+  gcolor1[1] = mi->colors[color].green / 65536.0;
+  gcolor1[2] = mi->colors[color].blue  / 65536.0;
+
+  gcolor2[0] = gcolor1[0] / 3;
+  gcolor2[1] = gcolor1[1] / 3;
+  gcolor2[2] = gcolor1[2] / 3;
+
+  {
+    GLfloat scale = BALLRADIUS;
+    glPushMatrix();
+    glTranslatef(x, y, 0);
+    glScalef(scale, scale, scale);
 
-                glNormal3f(cosf(na[j]) * cosf(a2),
-                    cosf(na[j]) * sinf(a2),    sinf(na[j]));
+    glRotatef (s->angle / M_PI*180, 1, 1, 0);
 
-                glVertex3f(r[j] * cosf(a2), r[j] * sinf(a2), z[j]);
-            }
-        glEnd();
-    }
+    polys += striped_unit_sphere (slices, slices, s->divisions, 
+                                  gcolor1, gcolor2, MI_IS_WIREFRAME(mi));
+    glPopMatrix();
+  }
+  return polys;
+}
 
-    glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, HandleCol);
+static int
+show_europeanclub(ModeInfo *mi, unsigned long color, Trace *s)
+{
+  int polys = 0;
+  jugglestruct *sp = &juggles[MI_SCREEN(mi)];
+  /*int offset = (int)(s->angle*64*180/M_PI);*/
+  short x = (short)(SCENE_WIDTH/2 + s->x * sp->scale);
+  short y = (short)(SCENE_HEIGHT - s->y * sp->scale);
+  double radius = 12 * sp->scale;
+  GLfloat gcolor1[4] = { 0, 0, 0, 1 };
+  GLfloat gcolor2[4] = { 1, 1, 1, 1 };
+  int slices = 16;
+  int divs = s->divisions;
+  divs = 4;
+
+  /*    6   6
+         +-+
+        /   \
+     4 +-----+ 7
+      ////////\
+   3 +---------+ 8
+   2 +---------+ 9
+      |///////|
+    1 +-------+ 10
+       |     |
+       |     |
+        |   |
+        |   |
+         | |
+         | |
+         +-+
+        0  11  */
+
+  /* Avoid wrapping */
+  if(s->y*sp->scale >  SCENE_HEIGHT * 2) return 0;
+
+  gcolor1[0] = mi->colors[color].red   / 65536.0;
+  gcolor1[1] = mi->colors[color].green / 65536.0;
+  gcolor1[2] = mi->colors[color].blue  / 65536.0;
+
+  {
+    GLfloat scale = radius;
+    glPushMatrix();
+    glTranslatef(x, y, 0);
+    glScalef(scale, scale, scale);
 
-    for (i = 1; i < n; i += 2)
-    {
-        float a1 = i * PI * 2.0f / n;
-        float a2 = (i + 1) * PI * 2.0f / n;
+    glTranslatef (0, 0, 2);  /* put end of handle in hand */
 
-        glBegin(GL_TRIANGLE_STRIP);
-            for (j = 1; j < 4; j++)
-            {
-                glNormal3f(cosf(na[j]) * cosf(a1),
-                    cosf(na[j]) * sinf(a1),    sinf(na[j]));
+    glRotatef (s->angle / M_PI*180, 1, 0, 0);
 
-                glVertex3f(r[j] * cosf(a1), r[j] * sinf(a1), z[j]);
+    glPushMatrix();
+    glScalef (0.5, 1, 0.5);
+    polys += striped_unit_sphere (slices, slices, divs, gcolor2, gcolor1, 
+                                  MI_IS_WIREFRAME(mi));
+    glPopMatrix();
+    glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, gcolor2);
+    polys += tube (0, 0, 0,
+                   0, 2, 0,
+                   0.2, 0,
+                   slices, True, True, MI_IS_WIREFRAME(mi));
 
-                glNormal3f(cosf(na[j]) * cosf(a2),
-                    cosf(na[j]) * sinf(a2), sinf(na[j]));
+    glTranslatef (0, 2, 0);
+    glScalef (0.25, 0.25, 0.25);
+    polys += unit_sphere(slices, slices, MI_IS_WIREFRAME(mi));
 
-                glVertex3f(r[j] * cosf(a2), r[j] * sinf(a2), z[j]);
-            }
-        glEnd();
-    }
+    glPopMatrix();
+  }
+  return polys;
+}
 
-    pQuad = gluNewQuadric();
-    glTranslatef(0.0f, 0.0f, z[0]);
-    gluCylinder(pQuad, r[0], r[1], z[1] - z[0], n, 1);
 
-    glTranslatef(0.0f, 0.0f, z[3] - z[0]);
-    gluDisk(pQuad, 0.0, r[3], n, 1);
-    glRotatef(180.0f, 0.0f, 1.0f, 0.0f);
-    glTranslatef(0.0f, 0.0f, z[3] - z[0]);
-    gluDisk(pQuad, 0.0, r[0], n, 1);
-    gluDeleteQuadric(pQuad);
+static int
+show_torch(ModeInfo *mi, unsigned long color, Trace *s)
+{
+  int polys = 0;
+#if 0
+       jugglestruct *sp = &juggles[MI_SCREEN(mi)];
+       XPoint head, tail, last;
+       DXPoint dhead, dlast;
+       const double sa = sin(s->angle);
+       const double ca = cos(s->angle);
+
+       const double TailLen = -24;
+       const double HeadLen = 16;
+       const short Width   = (short)(5 * sqrt(sp->scale));
+
+       /*
+      +///+ head
+    last  |
+          |
+          |
+          |
+          |
+          + tail
+       */
+
+       dhead.x = s->x + HeadLen * PERSPEC * sa;
+       dhead.y = s->y - HeadLen * ca;
+
+       if(color == MI_BLACK_PIXEL(mi)) { /* Use 'last' when erasing */
+         dlast = s->dlast;
+       } else { /* Store 'last' so we can use it later when s->prev has
+                               gone */
+         if(s->prev != s->next) {
+               dlast.x = s->prev->x + HeadLen * PERSPEC * sin(s->prev->angle);
+               dlast.y = s->prev->y - HeadLen * cos(s->prev->angle);
+         } else {
+               dlast = dhead;
+         }
+         s->dlast = dlast;
+       }
+
+       /* Avoid wrapping (after last is stored) */
+       if(s->y*sp->scale >  SCENE_HEIGHT * 2) return 0;
+
+       head.x = (short)(SCENE_WIDTH/2 + dhead.x*sp->scale);
+       head.y = (short)(SCENE_HEIGHT - dhead.y*sp->scale);
+
+       last.x = (short)(SCENE_WIDTH/2 + dlast.x*sp->scale);
+       last.y = (short)(SCENE_HEIGHT - dlast.y*sp->scale);
+
+       tail.x = (short)(SCENE_WIDTH/2 +
+                                        (s->x + TailLen * PERSPEC * sa)*sp->scale );
+       tail.y = (short)(SCENE_HEIGHT - (s->y - TailLen * ca)*sp->scale );
+
+       if(color != MI_BLACK_PIXEL(mi)) {
+         XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_BLACK_PIXEL(mi));
+         XSetLineAttributes(MI_DISPLAY(mi), MI_GC(mi),
+                                                Width, LineSolid, CapRound, JoinRound);
+         draw_line(mi, head.x, head.y, tail.x, tail.y);
+       }
+       XSetForeground(MI_DISPLAY(mi), MI_GC(mi), color);
+       XSetLineAttributes(MI_DISPLAY(mi), MI_GC(mi),
+                                          Width * 2, LineSolid, CapRound, JoinRound);
+
+       draw_line(mi, head.x, head.y, last.x, last.y);
+
+#endif /* 0 */
+   return polys;
 }
 
 
-/* In total 6 display lists are used.  There are created based on the DL_
- * constants defined earlier.  The function returns the index of the first
- * display list, all others can be calculated based on an offset from there. */
-
-static int InitGLDisplayLists(void)
+static int
+show_knife(ModeInfo *mi, unsigned long color, Trace *s)
 {
-    int s = glGenLists(6);
-    GLUquadric* pQuad;
-
-    glNewList(s + DL_BALL, GL_COMPILE);
-    DrawSphere(BallRad);
-    glEndList();
-
-    glNewList(s + DL_CLUB, GL_COMPILE);
-    DrawClub();
-    glEndList();
-
-    glNewList(s + DL_RING, GL_COMPILE);
-    DrawRing();
-    glEndList();
-    
-    pQuad =  gluNewQuadric();
-    gluQuadricNormals(pQuad, GLU_SMOOTH);    
-    
-    glNewList(s + DL_TORSO, GL_COMPILE);
-        glPushMatrix();
-            glTranslatef(ShoulderPos[0], ShoulderPos[1], -ShoulderPos[2]);
-            glRotatef(-90.0f, 0.0f, 1.0f, 0.0f);
-            gluCylinder(pQuad, 0.3, 0.3, ShoulderPos[0] * 2, 18, 1);
-        glPopMatrix();
-
-        glPushMatrix();
-            glTranslatef(0.0f, -1.0f, -ShoulderPos[2]);
-            glRotatef(-90.0f, 1.0f, 0.0f, 0.0f);
-            gluCylinder(pQuad, 0.3, 0.3, ShoulderPos[1] + 1.0f, 18, 1);
-            glRotatef(180.0f, 1.0f, 0.0f, 0.0f);
-            gluDisk(pQuad, 0.0, 0.3, 18, 1);
-        glPopMatrix();
-        
-        /* draw the head */
-        glPushMatrix();
-            glTranslatef(0.0f, ShoulderPos[1] + 1.0f, -ShoulderPos[2]);
-            glRotatef(-30.0f, 1.0f, 0.0f, 0.0f);
-            gluCylinder(pQuad, 0.5, 0.5, 0.3, 15, 1);
-            
-            glPushMatrix();
-                glRotatef(180.0f, 1.0f, 0.0f, 0.0f);
-                glRotatef(180.0f, 0.0f, 0.0f, 1.0f);
-                gluDisk(pQuad, 0.0, 0.5, 15, 1);
-            glPopMatrix(); 
-                
-            glTranslatef(0.0f, 0.0f, .3f);
-            gluDisk(pQuad, 0.0, 0.5, 15, 1);
-        glPopMatrix();        
-    glEndList();
-    
-    glNewList(s + DL_UPPERARM, GL_COMPILE);
-        gluQuadricNormals(pQuad, GLU_SMOOTH);
-        gluQuadricDrawStyle(pQuad, GLU_FILL);
-        gluSphere(pQuad, 0.3, 12, 8);
-
-        gluCylinder(pQuad, 0.3, 0.3, UArmLen, 12, 1); 
-        glTranslatef(0.0f, 0.0f, UArmLen);
-        gluSphere(pQuad, 0.3, 12, 8);
-    glEndList();
-
-    glNewList(s + DL_FOREARM, GL_COMPILE);
-        gluCylinder(pQuad, 0.3, 0.3 / 2.0f, LArmLen, 12, 1);
-        glTranslatef(0.0f, 0.0f, LArmLen);
-        gluDisk(pQuad, 0, 0.3 / 2.0f, 18, 1);
-    glEndList();
-
-    gluDeleteQuadric(pQuad);
-    return s;
+  int polys = 0;
+  jugglestruct *sp = &juggles[MI_SCREEN(mi)];
+  /*int offset = (int)(s->angle*64*180/M_PI);*/
+  short x = (short)(SCENE_WIDTH/2 + s->x * sp->scale);
+  short y = (short)(SCENE_HEIGHT - s->y * sp->scale);
+  GLfloat gcolor1[4] = { 0, 0, 0, 1 };
+  GLfloat gcolor2[4] = { 1, 1, 1, 1 };
+  int slices = 8;
+
+  /* Avoid wrapping */
+  if(s->y*sp->scale >  SCENE_HEIGHT * 2) return 0;
+
+  gcolor1[0] = mi->colors[color].red   / 65536.0;
+  gcolor1[1] = mi->colors[color].green / 65536.0;
+  gcolor1[2] = mi->colors[color].blue  / 65536.0;
+
+  glPushMatrix();
+  glTranslatef(x, y, 0);
+  glScalef (2, 2, 2);
+
+  glTranslatef (0, 0, 2);  /* put end of handle in hand */
+  glRotatef (s->angle / M_PI*180, 1, 0, 0);
+
+  glScalef (0.3, 1, 1);  /* flatten blade */
+
+  glTranslatef(0, 6, 0);
+  glRotatef (180, 1, 0, 0);
+
+  glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, gcolor1);
+  polys += tube (0, 0, 0,
+                 0, 10, 0,
+                 1, 0,
+                 slices, True, True, MI_IS_WIREFRAME(mi));
+
+  glTranslatef (0, 12, 0);
+  glScalef (0.7, 10, 0.7);
+  glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, gcolor2);
+  polys += unit_sphere (slices, slices, MI_IS_WIREFRAME(mi));
+
+  glPopMatrix();
+  return polys;
 }
 
 
-/* Drawing the arm requires connecting the upper and fore arm between the
- * shoulder and hand position.  Thinking about things kinematically by treating
- * the shoulder and elbow as ball joints then, provided the arm can stretch far
- * enough, there's a infnite number of ways to position the elbow.  Basically
- * it's possible to fix and hand and shoulder and then rotate the elbow a full
- * 360 degrees.  Clearly human anatomy isn't like this and picking a natural
- * elbow position can be complex.  We chicken out and assume that poking the
- * elbow out by 20 degrees from the lowest position gives a reasonably looking
- * orientation. */
-
-static void DrawArm(RENDER_STATE* pState, float TimePos, int Left)
+static int
+show_ring(ModeInfo *mi, unsigned long color, Trace *s)
 {
-    POS Pos;
-    float x, y, len, len2, ang, ang2;
-    
-    GetHandPosition(pState->pPattern, Left, TimePos, &Pos);
+  int polys = 0;
+  jugglestruct *sp = &juggles[MI_SCREEN(mi)];
+  /*int offset = (int)(s->angle*64*180/M_PI);*/
+  short x = (short)(SCENE_WIDTH/2 + s->x * sp->scale);
+  short y = (short)(SCENE_HEIGHT - s->y * sp->scale);
+  double radius = 12 * sp->scale;
+  GLfloat gcolor1[4] = { 0, 0, 0, 1 };
+  GLfloat gcolor2[4] = { 0, 0, 0, 1 };
+  int slices = 24;
+  int i, j;
+  int wire_p = MI_IS_WIREFRAME(mi);
+  GLfloat width = M_PI * 2 / slices;
+  GLfloat ra = 1.0;
+  GLfloat rb = 0.7;
+  GLfloat thickness = 0.15;
+
+  /* Avoid wrapping */
+  if(s->y*sp->scale >  SCENE_HEIGHT * 2) return 0;
+
+  gcolor1[0] = mi->colors[color].red   / 65536.0;
+  gcolor1[1] = mi->colors[color].green / 65536.0;
+  gcolor1[2] = mi->colors[color].blue  / 65536.0;
+
+  gcolor2[0] = gcolor1[0] / 3;
+  gcolor2[1] = gcolor1[1] / 3;
+  gcolor2[2] = gcolor1[2] / 3;
+
+  glPushMatrix();
+  glTranslatef(0, 0, 12);  /* back of ring in hand */
+
+  glTranslatef(x, y, 0);
+  glScalef(radius, radius, radius);
+
+  glRotatef (90, 0, 1, 0);
+  glRotatef (s->angle / M_PI*180, 0, 0, 1);
+
+  glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, gcolor1);
+
+  /* discs */
+  for (j = -1; j <= 1; j += 2)
+    {
+      GLfloat z = j * thickness/2;
+      glFrontFace (j < 0 ? GL_CCW : GL_CW);
+      glNormal3f (0, 0, j*1);
+      glBegin (wire_p ? GL_LINES : GL_QUAD_STRIP);
+      for (i = 0; i < slices + (wire_p ? 0 : 1); i++) {
+        glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE,
+                      (i % (slices/3) ? gcolor1 : gcolor2));
+        GLfloat th = i * width;
+        GLfloat cth = cos(th);
+        GLfloat sth = sin(th);
+        glVertex3f (cth * ra, sth * ra, z);
+        glVertex3f (cth * rb, sth * rb, z);
+        polys++;
+      }
+      glEnd();
+    }
 
-    x = Pos.x + (Left ? -ShoulderPos[0] : ShoulderPos[0]);
-    y = Pos.y - ShoulderPos[1];
+  /* outer ring */
+  glFrontFace (GL_CCW);
+  glBegin (wire_p ? GL_LINES : GL_QUAD_STRIP);
+  for (i = 0; i < slices + (wire_p ? 0 : 1); i++)
+    {
+      GLfloat th = i * width;
+      GLfloat cth = cos(th);
+      GLfloat sth = sin(th);
+      glNormal3f (cth, sth, 0);
+      glVertex3f (cth * ra, sth * ra, thickness/2);
+      glVertex3f (cth * ra, sth * ra, -thickness/2);
+      polys++;
+    }
+  glEnd();
 
+  /* inner ring */
+  glFrontFace (GL_CW);
+  glBegin (wire_p ? GL_LINES : GL_QUAD_STRIP);
+  for (i = 0; i < slices + (wire_p ? 0 : 1); i++)
+    {
+      GLfloat th = i * width;
+      GLfloat cth = cos(th);
+      GLfloat sth = sin(th);
+      glNormal3f (-cth, -sth, 0);
+      glVertex3f (cth * rb, sth * ra, thickness/2);
+      glVertex3f (cth * rb, sth * ra, -thickness/2);
+      polys++;
+    }
+  glEnd();
 
-    len = sqrtf(x * x + y * y + ShoulderPos[2] * ShoulderPos[2]);
-    len2 = sqrtf(x * x + ShoulderPos[2] * ShoulderPos[2]);
+  glFrontFace (GL_CCW);
+  glPopMatrix();
+  return polys;
+}
 
-    ang = (float) CosineRule(UArmLen, len, LArmLen);
-    ang2 = (float) CosineRule(UArmLen, LArmLen, len);
 
-    if (ang == 0.0 && ang2 == 0)
-        ang2 = 180.0;
+static int
+show_bball(ModeInfo *mi, unsigned long color, Trace *s)
+{
+  int polys = 0;
+  jugglestruct *sp = &juggles[MI_SCREEN(mi)];
+  /*int offset = (int)(s->angle*64*180/M_PI);*/
+  short x = (short)(SCENE_WIDTH/2 + s->x * sp->scale);
+  short y = (short)(SCENE_HEIGHT - s->y * sp->scale);
+  double radius = 12 * sp->scale;
+  GLfloat gcolor1[4] = { 0, 0, 0, 1 };
+  GLfloat gcolor2[4] = { 0, 0, 0, 1 };
+  int slices = 16;
+  int i, j;
+
+  /* Avoid wrapping */
+  if(s->y*sp->scale >  SCENE_HEIGHT * 2) return 0;
+
+  gcolor1[0] = mi->colors[color].red   / 65536.0;
+  gcolor1[1] = mi->colors[color].green / 65536.0;
+  gcolor1[2] = mi->colors[color].blue  / 65536.0;
+
+  {
+    GLfloat scale = radius;
+    glPushMatrix();
 
+    glTranslatef(0, -6, 5);  /* position on top of hand */
+
+    glTranslatef(x, y, 0);
+    glScalef(scale, scale, scale);
+    glRotatef (s->angle / M_PI*180, 1, 0, 1);
+
+    glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, gcolor1);
+    polys += unit_sphere (slices, slices, MI_IS_WIREFRAME(mi));
+
+    glRotatef (90, 0, 0, 1);
+    glTranslatef (0, 0, 0.81);
+    glScalef(0.15, 0.15, 0.15);
+    glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, gcolor2);
+    for (i = 0; i < 3; i++) {
+      glPushMatrix();
+      glTranslatef (0, 0, 1);
+      glRotatef (360 * i / 3, 0, 0, 1);
+      glTranslatef (2, 0, 0);
+      glRotatef (18, 0, 1, 0);
+      glBegin (MI_IS_WIREFRAME(mi) ? GL_LINE_LOOP : GL_TRIANGLE_FAN);
+      glVertex3f (0, 0, 0);
+      for (j = slices; j >= 0; j--) {
+        GLfloat th = j * M_PI*2 / slices;
+        glVertex3f (cos(th), sin(th), 0);
+        polys++;
+      }
+      glEnd();
+      glPopMatrix();
+    }
 
-    glPushMatrix();
-        glTranslatef(Left ? ShoulderPos[0] : -ShoulderPos[0], ShoulderPos[1],
-            -ShoulderPos[2]);
-        glRotatef((float)(180.0f * asin(x / len2) / 3.14f), 0.0f, 1.0f, 0.0f);
-        glRotatef((float)(-180.f * asin(y / len) / 3.14), 1.0f, 0.0f, 0.0f);
-        glRotatef(Left ? 20.0f : -20.0f, 0.0f, 0.0f, 1.0f);
-        glRotatef((float) ang, 1.0f, 0.0f, 0.0f);
-        glCallList(DL_UPPERARM + pState->DLStart);
-
-        glRotatef((float)(ang2 - 180.0), 1.0f, 0.0f, 0.f);
-        glCallList(DL_FOREARM + pState->DLStart);
     glPopMatrix();
+  }
+  return polys;
 }
 
 
-static void DrawGLScene(RENDER_STATE* pState)
-{
-    float Time = pState->Time;
-    int nCols = sizeof(Cols) / sizeof(Cols[0]);
-    int i;
+/**************************************************************************
+ *                    Public Functions                                    *
+ *                                                                        *
+ **************************************************************************/
 
-    PATTERN_INFO* pPattern = pState->pPattern;
 
-    glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
+ENTRYPOINT void
+release_juggle (ModeInfo * mi)
+{
+  if (juggles != NULL) {
+       int screen;
+
+       for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
+         free_juggle(&juggles[screen]);
+       free(juggles);
+       juggles = (jugglestruct *) NULL;
+  }
+}
 
-    glMatrixMode(GL_MODELVIEW);
-    glLoadIdentity();
-    glTranslatef(5.0f * sinf(pState->TranslateAngle), 0.0f, 0.0f);
+/* FIXME: refill_juggle currently just appends new throws to the
+ * programme.  This is fine if the programme is empty, but if there
+ * are still some trajectories left then it really should take these
+ * into account */
 
-    gltrackball_rotate (pState->trackball);
+static void
+refill_juggle(ModeInfo * mi)
+{
+  jugglestruct *sp = NULL;
+  int i;
+
+  if (juggles == NULL)
+       return;
+  sp = &juggles[MI_SCREEN(mi)];
+
+  /* generate pattern */
+
+  if (pattern == NULL) {
+
+#define MAXPAT 10
+#define MAXREPEAT 300
+#define CHANGE_BIAS 8 /* larger makes num_ball changes less likely */
+#define POSITION_BIAS 20 /* larger makes hand movements less likely */
+
+       int count = 0;
+       while (count < MI_CYCLES(mi)) {
+         char buf[MAXPAT * 3 + 3], *b = buf;
+         int maxseen = 0;
+         int l = NRAND(MAXPAT) + 1;
+         int t = NRAND(MIN(MAXREPEAT, (MI_CYCLES(mi) - count))) + 1;
+
+         { /* vary number of balls */
+               int new_balls = sp->num_balls;
+               int change;
+
+               if (new_balls == 2) /* Do not juggle 2 that often */
+                 change = NRAND(2 + CHANGE_BIAS / 4);
+               else
+                 change = NRAND(2 + CHANGE_BIAS);
+               switch (change) {
+               case 0:
+                 new_balls++;
+                 break;
+               case 1:
+                 new_balls--;
+                 break;
+               default:
+                 break; /* NO-OP */
+               }
+               if (new_balls < sp->patternindex.minballs) {
+                 new_balls += 2;
+               }
+               if (new_balls > sp->patternindex.maxballs) {
+                 new_balls -= 2;
+               }
+               if (new_balls < sp->num_balls) {
+                 if (!program(mi, "[*]", NULL, 1)) /* lose ball */
+                       return;
+               }
+               sp->num_balls = new_balls;
+         }
+
+         count += t;
+         if (NRAND(2) && sp->patternindex.index[sp->num_balls].number) {
+               /* Pick from PortFolio */
+               int p = sp->patternindex.index[sp->num_balls].start +
+                 NRAND(sp->patternindex.index[sp->num_balls].number);
+               if (!program(mi, portfolio[p].pattern, portfolio[p].name, t))
+                 return;
+         } else {
+               /* Invent a new pattern */
+               *b++='[';
+               for(i = 0; i < l; i++){
+                 int n, m;
+                 do { /* Triangular Distribution => high values more likely */
+                       m = NRAND(sp->num_balls + 1);
+                       n = NRAND(sp->num_balls + 1);
+                 } while(m >= n);
+                 if (n == sp->num_balls) {
+                       maxseen = 1;
+                 }
+                 switch(NRAND(5 + POSITION_BIAS)){
+                 case 0:            /* Outside throw */
+                       *b++ = '+'; break;
+                 case 1:            /* Cross throw */
+                       *b++ = '='; break;
+                 case 2:            /* Cross catch */
+                       *b++ = '&'; break;
+                 case 3:            /* Cross throw and catch */
+                       *b++ = 'x'; break;
+                 case 4:            /* Bounce */
+                       *b++ = '_'; break;
+                 default:
+                       break;             /* Inside throw (default) */
+                 }
+
+                 *b++ = n + '0';
+                 *b++ = ' ';
+               }
+               *b++ = ']';
+               *b = '\0';
+               if (maxseen) {
+                 if (!program(mi, buf, NULL, t))
+                       return;
+               }
+         }
+       }
+  } else { /* pattern supplied in height or 'a' notation */
+       if (!program(mi, pattern, NULL, MI_CYCLES(mi)))
+         return;
+  }
+
+  adam(sp);
+
+  name(sp);
+
+  if (!part(sp))
+       return;
+
+  lob(mi);
+
+  clap(sp);
+
+  positions(sp);
+
+  if (!projectile(sp)) {
+       free_juggle(sp);
+       return;
+  }
+
+  hands(sp);
+#ifdef DEBUG
+  if(MI_IS_DEBUG(mi)) dump(sp);
+#endif
+}
 
-    glRotatef(pState->SpinAngle, 0.0f, 1.0f, 0.0f);
-    glTranslatef(0.0, 0.0, -1.0f);
+static void
+change_juggle(ModeInfo * mi)
+{
+  jugglestruct *sp = NULL;
+  Trajectory *t;
 
-    glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, DiffCol);
-    glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, SpecCol);
-    glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 60.0f);
+  if (juggles == NULL)
+       return;
+  sp = &juggles[MI_SCREEN(mi)];
 
-    for (i = 0; i < pPattern->Objects; i++)
-    {
-        POS ObjPos;
-        
-        glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, Cols[i % nCols]);
-        glPushMatrix();
+  /* Strip pending trajectories */
+  for (t = sp->head->next; t != sp->head; t = t->next) {
+       if(t->start > sp->time || t->finish < sp->time) {
+         Trajectory *n = t;
+         t=t->prev;
+         trajectory_destroy(n);
+       }
+  }
 
-        switch (pPattern->pObjectInfo[i].ObjectType)
-        {
-            case OBJECT_CLUB:
-                GetObjectPosition(pPattern, i, Time, 1.0f, &ObjPos);
-                glTranslatef(ObjPos.x, ObjPos.y, ObjPos.z);
-                glRotatef(ObjPos.Rot, 0.0f, 1.0f, 0.0f);
-                glRotatef(ObjPos.Elev, -1.0f, 0.0f, 0.0f);
-                glTranslatef(0.0f, 0.0f, -1.0f);
-                glCallList(DL_CLUB + pState->DLStart);
-                break;
-
-            case OBJECT_RING:
-                GetObjectPosition(pPattern, i, Time, 1.0f, &ObjPos);
-                glTranslatef(ObjPos.x, ObjPos.y, ObjPos.z);
-                glRotatef(ObjPos.Rot, 0.0f, 1.0f, 0.0f);
-                glRotatef(ObjPos.Elev, -1.0f, 0.0f, 0.0f);
-                glCallList(DL_RING + pState->DLStart);
-                break;
-
-            default:
-                GetObjectPosition(pPattern, i, Time, 0.0f, &ObjPos);
-                glTranslatef(ObjPos.x, ObjPos.y, ObjPos.z);        
-                glRotatef(ObjPos.Rot, 0.6963f, 0.6963f, 0.1742f);
-                glCallList(DL_BALL + pState->DLStart);
-                glRotatef(90.0f, 0.0f, 1.0f, 0.0f);
-                glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, 
-                    AltCols[i % nCols]);
-                glCallList(DL_BALL + pState->DLStart);
-                break;
-        }
+  /* Pick the current object theme */
+  sp->objtypes = choose_object();
 
-        glPopMatrix();
-    }
+  refill_juggle(mi);
 
-    glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, BodyCol);
-    glCallList(DL_TORSO + pState->DLStart);
-    DrawArm(pState, Time, 1);
-    DrawArm(pState, Time, 0);
+  mi->polygon_count += show_figure(mi, True);
 }
 
 
-static int RandInRange(int Min, int Max)
+ENTRYPOINT void
+reshape_juggle (ModeInfo *mi, int width, int height)
 {
-    return Min + random() % (1 + Max - Min);
-}
+  GLfloat h = (GLfloat) height / (GLfloat) width;
 
+  glViewport (0, 0, (GLint) width, (GLint) height);
 
-static void UpdatePattern(
-    RENDER_STATE* pState, int MinBalls, int MaxBalls, 
-    int MinHeightInc, int MaxHeightInc)
-{
-    if (pState->pPattern != NULL)
-        ReleasePatternInfo(pState->pPattern);
-    
-    pState->pPattern = (PATTERN_INFO*) malloc(sizeof(PATTERN_INFO));
-    
-    if ((random() % 3) == 1)
-    {    
-        int ExtSiteLen;
-        int n = random() % (sizeof(PatternText) / sizeof(PatternText[0]));
-        EXT_SITE_INFO* pExtInfo = ParsePattern(PatternText[n], &ExtSiteLen);
-        InitPatternInfo(pState->pPattern, NULL, pExtInfo, ExtSiteLen);
-        free(pExtInfo);
-    }
-    else
-    {
-        int* pRand;
-        int ballcount, maxweight;
-        const int RandPatternLen = 1500;
-        
-        ballcount = RandInRange(MinBalls, MaxBalls);
-        maxweight = ballcount  + RandInRange(MinHeightInc, MaxHeightInc);
-        
-        pRand = Generate(RandPatternLen, maxweight, ballcount);
-        InitPatternInfo(pState->pPattern, pRand, NULL, RandPatternLen);
-        free(pRand);
-    }
-    
-    pState->CameraElev = 50.0f - random() % 90;
-    pState->TranslateAngle = random() % 360;
-    pState->SpinAngle = random() % 360;
-    pState->Time = 50.0f;
-    SetCamera(pState);
-}
-
+  glMatrixMode(GL_PROJECTION);
+  glLoadIdentity();
+  gluPerspective (30.0, 1/h, 1.0, 100.0);
 
-/*******************************************************************************
- *
- *  XScreenSaver Configuration
- *
- ******************************************************************************/
+  glMatrixMode(GL_MODELVIEW);
+  glLoadIdentity();
+  gluLookAt( 0.0, 0.0, 30.0,
+             0.0, 0.0, 0.0,
+             0.0, 1.0, 0.0);
 
-typedef struct
-{
-    GLXContext* glxContext;
-    RENDER_STATE RenderState;
-    float CurrentFrameRate;
-    unsigned FramesSinceSync;
-    unsigned LastSyncTime;
-} JUGGLER3D_CONFIG;
-
-
-#define DEF_MAX_OBJS           "8"
-#define DEF_MIN_OBJS           "3"
-#define DEF_MAX_HINC           "6"
-#define DEF_MIN_HINC           "2"
-#define DEF_JUGGLE_SPEED       "2.2"
-#define DEF_TRANSLATE_SPEED    "0.1"
-#define DEF_SPIN_SPEED         "20.0"
-
-static JUGGLER3D_CONFIG* pConfigInfo = NULL;
-static int MaxObjects;
-static int MinObjects;
-static int MaxHeightInc;
-static int MinHeightInc;
-static float SpinSpeed;
-static float TranslateSpeed;
-static float JuggleSpeed;
-
-static XrmOptionDescRec opts[] =
-{
-    {"-spin", ".spinSpeed", XrmoptionSepArg, 0},
-    {"-trans", ".translateSpeed", XrmoptionSepArg, 0},
-    {"-speed", ".juggleSpeed", XrmoptionSepArg, 0},
-    {"-maxobjs", ".maxObjs", XrmoptionSepArg, 0},
-    {"-minobjs", ".minObjs", XrmoptionSepArg, 0},
-    {"-maxhinc", ".maxHinc", XrmoptionSepArg, 0},
-    {"-minhinc", ".minHinc", XrmoptionSepArg, 0},
-};
+  glClear(GL_COLOR_BUFFER_BIT);
+}
 
 
-static argtype vars[] = 
+ENTRYPOINT void
+init_juggle (ModeInfo * mi)
 {
-    {&MaxObjects, "maxObjs", "MaxObjs", DEF_MAX_OBJS, t_Int},
-    {&MinObjects, "minObjs", "MinObjs", DEF_MIN_OBJS, t_Int},
-    {&MaxHeightInc, "maxHinc", "MaxHinc", DEF_MAX_HINC, t_Int},
-    {&MinHeightInc, "minHinc", "MinHinc", DEF_MIN_HINC, t_Int},
-    {&JuggleSpeed, "juggleSpeed", "JuggleSpeed", DEF_JUGGLE_SPEED, t_Float},
-    {&TranslateSpeed, "translateSpeed", "TranslateSpeed", DEF_TRANSLATE_SPEED, t_Float},
-    {&SpinSpeed, "spinSpeed", "SpinSpeed", DEF_SPIN_SPEED, t_Float},
-};
-
+  jugglestruct *sp = 0;
+  int wire = MI_IS_WIREFRAME(mi);
+
+  if (!juggles) {
+    juggles = (jugglestruct *)
+      calloc (MI_NUM_SCREENS(mi), sizeof (jugglestruct));
+    if (!juggles) {
+      fprintf(stderr, "%s: out of memory\n", progname);
+      exit(1);
+    }
+  }
 
-ENTRYPOINT ModeSpecOpt juggler3d_opts = {countof(opts), opts, countof(vars), vars};
+  sp = &juggles[MI_SCREEN(mi)];
 
+  sp->glx_context = init_GL(mi);
 
-ENTRYPOINT void reshape_juggler3d(ModeInfo *mi, int width, int height)
-{
-    JUGGLER3D_CONFIG* pConfig = &pConfigInfo[MI_SCREEN(mi)];
-    ResizeGL(&pConfig->RenderState, width, height);
-}
+  load_font (mi->dpy, "titleFont",  &sp->mode_font, &sp->font_dlist);
 
+  reshape_juggle (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
 
-ENTRYPOINT void init_juggler3d(ModeInfo* mi)
-{
-    JUGGLER3D_CONFIG* pConfig;
-    
-    if (pConfigInfo == NULL)
+  if (!wire)
     {
-        /* Apply suitable bounds checks to the input parameters */
-        MaxObjects = max(3, min(MaxObjects, 36));
-        MinObjects = max(3, min(MinObjects, MaxObjects));
-
-        MaxHeightInc = max(1, min(MaxHeightInc, 32));
-        MinHeightInc = max(1, min(MinHeightInc, MaxHeightInc));
-            
-        pConfigInfo = (JUGGLER3D_CONFIG*) calloc(
-            MI_NUM_SCREENS(mi), sizeof(JUGGLER3D_CONFIG));
-        if (pConfigInfo == NULL)
-        {
-            fprintf(stderr, "%s: out of memory\n", progname);
-            exit(1);
-        }
+      GLfloat pos[4] = {1.0, 1.0, 1.0, 0.0};
+      GLfloat amb[4] = {0.0, 0.0, 0.0, 1.0};
+      GLfloat dif[4] = {1.0, 1.0, 1.0, 1.0};
+      GLfloat spc[4] = {0.0, 1.0, 1.0, 1.0};
+
+      glEnable(GL_LIGHTING);
+      glEnable(GL_LIGHT0);
+      glEnable(GL_DEPTH_TEST);
+      glEnable(GL_CULL_FACE);
+
+      glLightfv(GL_LIGHT0, GL_POSITION, pos);
+      glLightfv(GL_LIGHT0, GL_AMBIENT,  amb);
+      glLightfv(GL_LIGHT0, GL_DIFFUSE,  dif);
+      glLightfv(GL_LIGHT0, GL_SPECULAR, spc);
     }
-    
-    pConfig = &pConfigInfo[MI_SCREEN(mi)];
-    pConfig->glxContext = init_GL(mi);
-    pConfig->CurrentFrameRate = 0.0f;
-    pConfig->FramesSinceSync = 0;
-    pConfig->LastSyncTime = 0;
-    InitGLSettings(&pConfig->RenderState, MI_IS_WIREFRAME(mi));
-
-    UpdatePattern(&pConfig->RenderState, MinObjects, MaxObjects, 
-        MinHeightInc, MaxHeightInc);
-    
-    reshape_juggler3d(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
-}
-
 
-ENTRYPOINT void draw_juggler3d(ModeInfo* mi)
-{
-    JUGGLER3D_CONFIG* pConfig = &pConfigInfo[MI_SCREEN(mi)];
-    Display* pDisplay = MI_DISPLAY(mi);
-    Window hwnd = MI_WINDOW(mi);
-
-    if (pConfig->glxContext == NULL)
-        return;
-
-    glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(pConfig->glxContext));
-    
-    /* While drawing, keep track of the rendering speed so we can adjust the
-     * animation speed so things appear consistent.  The basis of the this
-     * code comes from the frame rate counter (fps.c) but has been modified
-     * so that it reports the initial frame rate earlier (after 0.02 secs
-     * instead of 1 sec). */
-    
-    if (pConfig->FramesSinceSync >=  1 * (int) pConfig->CurrentFrameRate)
-    {
-        struct timeval tvnow;
-        unsigned now;
-            
-        # ifdef GETTIMEOFDAY_TWO_ARGS
-            struct timezone tzp;
-            gettimeofday(&tvnow, &tzp);
-        # else
-            gettimeofday(&tvnow);
-        # endif
-        
-        now = (unsigned) (tvnow.tv_sec * 1000000 + tvnow.tv_usec);
-        if (pConfig->FramesSinceSync == 0)
-        {
-            pConfig->LastSyncTime = now;
-        }
-        else
-        {
-            unsigned Delta = now - pConfig->LastSyncTime;
-            if (Delta > 20000)
-            {
-                pConfig->LastSyncTime = now;
-                pConfig->CurrentFrameRate = 
-                    (pConfig->FramesSinceSync * 1.0e6f) / Delta;
-                pConfig->FramesSinceSync = 0;
-            }
-        }
-    }
-    
-    pConfig->FramesSinceSync++;
-    
-    if (pConfig->RenderState.Time > 150.0f)
-    {
-        UpdatePattern(&pConfig->RenderState, MinObjects, MaxObjects, 
-            MinHeightInc, MaxHeightInc);
-    }
-    DrawGLScene(&pConfig->RenderState);
-    
-    if (pConfig->CurrentFrameRate > 1.0e-6f)
-    {
-        pConfig->RenderState.Time += JuggleSpeed / pConfig->CurrentFrameRate;
-        pConfig->RenderState.SpinAngle += SpinSpeed / pConfig->CurrentFrameRate;
-        pConfig->RenderState.TranslateAngle += 
-            TranslateSpeed / pConfig->CurrentFrameRate;
+  make_random_colormap (0, 0, 0,
+                        mi->colors, &MI_NPIXELS(mi),
+                        True, False, 0, False);
+
+  {
+    double spin_speed   = 0.05;
+    double wander_speed = 0.001;
+    double spin_accel   = 0.05;
+    sp->rot = make_rotator (0, spin_speed, 0, 
+                            spin_accel, wander_speed, False);
+    sp->trackball = gltrackball_init ();
+  }
+
+  if (only && *only && strcmp(only, " ")) {
+    balls = clubs = torches = knives = rings = bballs = False;
+    if (!strcasecmp (only, "balls"))   balls   = True;
+    else if (!strcasecmp (only, "clubs"))   clubs   = True;
+    else if (!strcasecmp (only, "torches")) torches = True;
+    else if (!strcasecmp (only, "knives"))  knives  = True;
+    else if (!strcasecmp (only, "rings"))   rings   = True;
+    else if (!strcasecmp (only, "bballs"))  bballs  = True;
+    else {
+      (void) fprintf (stderr,
+               "Juggle: -only must be one of: balls, clubs, torches, knives,\n"
+               "\t rings, or bballs (not \"%s\")\n", only);
+#ifdef STANDALONE /* xlock mustn't exit merely because of a bad argument */
+      exit (1);
+#endif
     }
-    
-    if (mi->fps_p)
-        do_fps(mi);
-  
-    glFinish();
-    glXSwapBuffers(pDisplay, hwnd);
-}
+  }
+
+  /* #### hard to make this look good in OpenGL... */
+  torches = False;
+
+
+  if (sp->head == 0) {  /* first time initializing this juggler */
+
+       sp->count = ABS(MI_COUNT(mi));
+       if (sp->count == 0)
+         sp->count = 200;
+
+       /* record start time */
+       sp->begintime = time(NULL);
+       if(sp->patternindex.maxballs > 0) {
+         sp->num_balls = sp->patternindex.minballs +
+               NRAND(sp->patternindex.maxballs - sp->patternindex.minballs);
+       }
+
+        mi->polygon_count +=
+          show_figure(mi, True); /* Draw figure.  Also discovers
+                                    information about the juggler's
+                                    proportions */
+
+       /* "7" should be about three times the height of the juggler's
+          shoulders */
+       sp->Gr = -GRAVITY(3 * sp->arm[0][RIGHT][SHOULDER].y,
+                                         7 * THROW_CATCH_INTERVAL);
+
+       if(!balls && !clubs && !torches && !knives && !rings && !bballs)
+         balls = True; /* Have to juggle something! */
+
+       /* create circular trajectory list */
+       ADD_ELEMENT(Trajectory, sp->head, sp->head);
+       if(sp->head == NULL){
+         free_juggle(sp);
+         return;
+       }
+
+       /* create circular object list */
+       ADD_ELEMENT(Object, sp->objects, sp->objects);
+       if(sp->objects == NULL){
+         free_juggle(sp);
+         return;
+       }
+
+       sp->pattern =  strdup(""); /* Initialise saved pattern with 
+                                      free-able memory */
+  }
+
+  sp = &juggles[MI_SCREEN(mi)];
+
+  if (pattern &&
+      (!*pattern ||
+       !strcasecmp (pattern, ".") ||
+       !strcasecmp (pattern, "random")))
+       pattern = NULL;
+
+  if (pattern == NULL && sp->patternindex.maxballs == 0) {
+       /* pattern list needs indexing */
+       int nelements = countof(portfolio);
+       int numpat = 0;
+       int i;
+
+       /* sort according to number of balls */
+       qsort((void*)portfolio, nelements,
+                 sizeof(portfolio[1]), compare_num_balls);
+
+       /* last pattern has most balls */
+       sp->patternindex.maxballs = get_num_balls(portfolio[nelements - 1].pattern);
+       /* run through sorted list, indexing start of each group
+          and number in group */
+       sp->patternindex.maxballs = 1;
+       for (i = 0; i < nelements; i++) {
+         int b = get_num_balls(portfolio[i].pattern);
+         if (b > sp->patternindex.maxballs) {
+               sp->patternindex.index[sp->patternindex.maxballs].number = numpat;
+               if(numpat == 0) sp->patternindex.minballs = b;
+               sp->patternindex.maxballs = b;
+               numpat = 1;
+               sp->patternindex.index[sp->patternindex.maxballs].start = i;
+         } else {
+               numpat++;
+         }
+       }
+       sp->patternindex.index[sp->patternindex.maxballs].number = numpat;
+  }
+
+  /* Set up programme */
+  change_juggle(mi);
+
+  /* Only put things here that won't interrupt the programme during
+        a window resize */
+
+  /* Use MIN so that users can resize in interesting ways, eg
+        narrow windows for tall patterns, etc */
+  sp->scale = MIN(SCENE_HEIGHT/480.0, SCENE_WIDTH/160.0);
 
+}
 
-ENTRYPOINT Bool juggler3d_handle_event(ModeInfo* mi, XEvent* pEvent)
+ENTRYPOINT Bool
+juggle_handle_event (ModeInfo *mi, XEvent *event)
 {
-  JUGGLER3D_CONFIG* pConfig = &pConfigInfo[MI_SCREEN(mi)];
-  RENDER_STATE* pState = &pConfig->RenderState;
+  jugglestruct *sp = &juggles[MI_SCREEN(mi)];
 
-    if (pEvent->xany.type == ButtonPress &&
-        pEvent->xbutton.button == Button1)
+  if (event->xany.type == ButtonPress &&
+      event->xbutton.button == Button1)
     {
-      pState->button_down_p = True;
-      gltrackball_start (pState->trackball,
-                         pEvent->xbutton.x, pEvent->xbutton.y,
+      sp->button_down_p = True;
+      gltrackball_start (sp->trackball,
+                         event->xbutton.x, event->xbutton.y,
                          MI_WIDTH (mi), MI_HEIGHT (mi));
       return True;
     }
-    else if (pEvent->xany.type == ButtonRelease &&
-             pEvent->xbutton.button == Button1)
+  else if (event->xany.type == ButtonRelease &&
+           event->xbutton.button == Button1)
     {
-      pState->button_down_p = False;
+      sp->button_down_p = False;
       return True;
     }
-    else if (pEvent->xany.type == ButtonPress &&
-             (pEvent->xbutton.button == Button4 ||
-              pEvent->xbutton.button == Button5 ||
-              pEvent->xbutton.button == Button6 ||
-              pEvent->xbutton.button == Button7))
+  else if (event->xany.type == ButtonPress &&
+           (event->xbutton.button == Button4 ||
+            event->xbutton.button == Button5 ||
+            event->xbutton.button == Button6 ||
+            event->xbutton.button == Button7))
     {
-      gltrackball_mousewheel (pState->trackball, pEvent->xbutton.button, 2,
-                              !pEvent->xbutton.state);
+      gltrackball_mousewheel (sp->trackball, event->xbutton.button, 10,
+                              !!event->xbutton.state);
       return True;
     }
-    else if (pEvent->xany.type == MotionNotify &&
-             pState->button_down_p)
+  else if (event->xany.type == MotionNotify &&
+           sp->button_down_p)
     {
-      gltrackball_track (pState->trackball,
-                         pEvent->xmotion.x, pEvent->xmotion.y,
+      gltrackball_track (sp->trackball,
+                         event->xmotion.x, event->xmotion.y,
                          MI_WIDTH (mi), MI_HEIGHT (mi));
       return True;
     }
-    else if (pEvent->xany.type == KeyPress)
+  else if (event->xany.type == KeyPress)
     {
-        char str[20];
-        KeySym Key = 0;
-        int count = XLookupString(&pEvent->xkey, str, 20, &Key, 0);
-        str[count] = '\0';
-        if (*str == ' ')
+      KeySym keysym;
+      char c = 0;
+      XLookupString (&event->xkey, &c, 1, &keysym, 0);
+      if (c == ' ' || c == '\n' || c == '\r' || c == '\t')
         {
-            UpdatePattern(&pConfig->RenderState, MinObjects, MaxObjects, 
-                MinHeightInc, MaxHeightInc);
+          change_juggle (mi);
+          return True;
         }
     }
-    
-    return False;
+
+
+  return False;
 }
 
-XSCREENSAVER_MODULE ("Juggler3D", juggler3d)
 
+ENTRYPOINT void
+draw_juggle (ModeInfo *mi)
+{
+  jugglestruct *sp = &juggles[MI_SCREEN(mi)];
+  Display *dpy = MI_DISPLAY(mi);
+  Window window = MI_WINDOW(mi);
+
+  Trajectory *traj = NULL;
+  Object *o = NULL;
+  unsigned long future = 0;
+  char *pattern = NULL;
+
+  if (!sp->glx_context)
+    return;
+
+  glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(sp->glx_context));
+
+  glShadeModel(GL_SMOOTH);
+
+  glEnable(GL_DEPTH_TEST);
+  glEnable(GL_NORMALIZE);
+  glEnable(GL_CULL_FACE);
+
+  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+  glPushMatrix ();
+
+  glTranslatef(0,-3,0);
+
+  {
+    double x, y, z;
+    get_position (sp->rot, &x, &y, &z, !sp->button_down_p);
+    glTranslatef((x - 0.5) * 8,
+                 (y - 0.5) * 3,
+                 (z - 0.5) * 15);
+
+    gltrackball_rotate (sp->trackball);
+
+    get_rotation (sp->rot, &x, &y, &z, !sp->button_down_p);
+
+    if (y < 0.8) y = 0.8 - (y - 0.8);  /* always face forward */
+    if (y > 1.2) y = 1.2 - (y - 1.2);
+
+    glRotatef (x * 360, 1.0, 0.0, 0.0);
+    glRotatef (y * 360, 0.0, 1.0, 0.0);
+    glRotatef (z * 360, 0.0, 0.0, 1.0);
+  }
+
+  {
+    GLfloat scale = 20.0 / SCENE_HEIGHT;
+    glScalef(scale, scale, scale);
+  }
+
+  glRotatef (180, 0, 0, 1);
+  glTranslatef(-SCENE_WIDTH/2, -SCENE_HEIGHT/2, 0);
+  glTranslatef(0, -150, 0);
+
+  mi->polygon_count = 0;
+
+  /* Update timer */
+  if (real) {
+       struct timeval tv;
+       (void)gettimeofday(&tv, NULL);
+       sp->time = (int) ((tv.tv_sec - sp->begintime)*1000 + tv.tv_usec/1000);
+  } else {
+       sp->time += MI_DELAY(mi) / 1000;
+  }
+
+  /* First pass: Move arms and strip out expired elements */
+  for (traj = sp->head->next; traj != sp->head; traj = traj->next) {
+       if (traj->status != PREDICTOR) {
+         /* Skip any elements that need further processing */
+         /* We could remove them, but there shoudn't be many and they
+                would be needed if we ever got the pattern refiller
+                working */
+         continue;
+       }
+       if (traj->start > future) { /* Lookahead to the end of the show */
+         future = traj->start;
+       }
+       if (sp->time < traj->start) { /* early */
+         continue;
+       } else if (sp->time < traj->finish) { /* working */
+
+         /* Look for pattern name */
+         if(traj->pattern != NULL) {
+               pattern=traj->pattern;
+         }
+
+         if (traj->type == Empty || traj->type == Full) {
+               /* Only interested in hands on this pass */
+/*             double angle = traj->angle + traj->spin * (sp->time - traj->start);*/
+               double xd = 0, yd = 0;
+               DXPoint p;
+
+               /* Find the catching offset */
+               if(traj->object != NULL) {
+#if 0
+                  /* #### not sure what this is doing, but I'm guessing
+                     that the use of PERSPEC means this isn't needed
+                     in the OpenGL version? -jwz
+                   */
+                 if(ObjectDefs[traj->object->type].handle > 0) {
+                       /* Handles Need to be oriented */
+                       xd = ObjectDefs[traj->object->type].handle *
+                         PERSPEC * sin(angle);
+                       yd = ObjectDefs[traj->object->type].handle *
+                         cos(angle);
+                 } else
+#endif
+                    {
+                       /* Balls are always caught at the bottom */
+                       xd = 0;
+                       yd = -4;
+                 }
+               }
+               p.x = (CUBIC(traj->xp, sp->time) - xd);
+               p.y = (CUBIC(traj->yp, sp->time) + yd);
+               reach_arm(mi, traj->hand, &p);
+
+               /* Store updated hand position */
+               traj->x = p.x + xd;
+               traj->y = p.y - yd;
+         }
+         if (traj->type == Ball || traj->type == Full) {
+               /* Only interested in objects on this pass */
+               double x, y;
+               Trace *s;
+
+               if(traj->type == Full) {
+                 /* Adjusted these in the first pass */
+                 x = traj->x;
+                 y = traj->y;
+               } else {
+                 x = CUBIC(traj->xp, sp->time);
+                 y = CUBIC(traj->yp, sp->time);
+               }
+
+               ADD_ELEMENT(Trace, s, traj->object->trace->prev);
+               s->x = x;
+               s->y = y;
+               s->angle = traj->angle + traj->spin * (sp->time - traj->start);
+               s->divisions = traj->divisions;
+               traj->object->tracelen++;
+               traj->object->active = True;
+         }
+       } else { /* expired */
+         Trajectory *n = traj;
+         traj=traj->prev;
+         trajectory_destroy(n);
+       }
+  }
+
+
+  mi->polygon_count += show_figure(mi, False);
+  mi->polygon_count += show_arms(mi);
+
+  /* Draw Objects */
+  glTranslatef(0, 0, ARMLENGTH);
+  for (o = sp->objects->next; o != sp->objects; o = o->next) {
+       if(o->active) {
+         mi->polygon_count += ObjectDefs[o->type].draw(mi, o->color, 
+                                                        o->trace->prev);
+         o->active = False;
+       }
+  }
+
+
+  /* Save pattern name so we can erase it when it changes */
+  if(pattern != NULL && strcmp(sp->pattern, pattern) != 0 ) {
+       free(sp->pattern);
+       sp->pattern = strdup(pattern);
+
+       if (MI_IS_VERBOSE(mi)) {
+         (void) fprintf(stderr, "Juggle[%d]: Running: %s\n",
+                                        MI_SCREEN(mi), sp->pattern);
+       }
+  }
+
+  if(sp->mode_font != None) {
+    print_gl_string (mi->dpy, sp->mode_font, sp->font_dlist,
+                     mi->xgwa.width, mi->xgwa.height,
+                     10, mi->xgwa.height - 10,
+                     sp->pattern, False);
+  }
+
+#ifdef MEMTEST
+  if((int)(sp->time/10) % 1000 == 0)
+       (void) fprintf(stderr, "sbrk: %d\n", (int)sbrk(0));
 #endif
+
+  if (future < sp->time + 100 * THROW_CATCH_INTERVAL) {
+       refill_juggle(mi);
+  } else if (sp->time > 1<<30) { /* Hard Reset before the clock wraps */
+       release_juggle(mi);
+       init_juggle(mi);
+  }
+
+  glPopMatrix ();
+
+  if (mi->fps_p) do_fps (mi);
+  glFinish();
+
+  glXSwapBuffers(dpy, window);
+}
+
+XSCREENSAVER_MODULE_2 ("Juggler3D", juggler3d, juggle)
+
+#endif /* USE_GL */
index 6ae9044a89ca346889d2aef51dffe90c03f018c0..48d47160fc561da99d13af7bdf3c6057c1c03647 100644 (file)
+'\" t
+.\" ** The above line should force tbl to be used as a preprocessor **
 .TH XScreenSaver 1 "" "X Version 11"
 .SH NAME
-Juggler3D - a 3D juggling simulation.
+juggler3d - juggling man screen saver.
 .SH SYNOPSIS
 .B juggler3d
-[\-display \fIhost:display.screen\fP]
-[\-visual \fIvisual\fP]
-[\-window]
-[\-root]
-[\-delay \fInumber\fP]
-[\-speed \fInumber\fP]
-[\-trans \fInumber\fP]
-[\-spin \fInumber\fP]
-[\-maxobjs \fInumber\fP]
-[\-minobjs \fInumber\fP]
-[\-maxhinc \fInumber\fP]
-[\-minhinc \fInumber\fP]
-[\-wireframe]
+[\-display host:display.screen ]
+[\-root ]
+[\-window ]
+[\-mono ]
+[\-install | \-noinstall ]
+[\-visual visual ]
+[\-window\-id id ]
+[\-pattern pattern ]
+[\-tail number ]
+[\-real | \-no\-real ]
+[\-describe | \-no\-describe ]
+[\-balls | \-no\-balls ]
+[\-clubs | \-no\-clubs ]
+[\-torches | \-no\-torches ]
+[\-knives | \-no\-knives ]
+[\-rings | \-no\-rings ]
+[\-bballs | \-no\-bballs ]
+[\-count count ]
+[\-cycles cycles ]
+[\-delay delay ]
+[\-ncolors ncolors ]
 [\-fps]
 .SH DESCRIPTION
-Displays a 3D simulation of a juggler performing with balls, clubs and rings. 
-Juggling patterns are either created randomly using siteswaps or from a 
-small library of predefined patterns.  \fBjuggler3d\fP is partially based on the
-Win32 screensaver Juggle Saver (www.jugglesaver.co.uk) by the same author.
+Draws a stick-man juggling various collections of objects.
 .SH OPTIONS
+.I juggler3d
+accepts the following options:
 .TP 8
-.B \-visual \fIvisual\fP
+.B \-display host:display.screen
+X11 display to use.  Overrides
+.B DISPLAY
+environment variable.
+.TP 8
+.B \-root
+Draw on the root window.
+.TP 8
+.B \-window
+Draw on a newly-created X window.  This is the default.
+.TP 8
+.B \-mono
+Draw in monochrome.
+.TP 8
+.B \-install | \-noinstall
+Turn on/off installing colormap.
+.TP 8
+.B \-visual visual
 Specify which visual to use.  Legal values are the name of a visual class,
 or the id number (decimal or hex) of a specific visual.
 .TP 8
-.B \-window
-Draw on a newly-created window.  This is the default.
+.B \-window\-id id
+Draw on an already existing X window.
 .TP 8
-.B \-root
-Draw on the root window.
+.B \-pattern\ \(dq pattern \(dq
+Specify juggling pattern in annotated
+.B site-swap
+notation.  In 
+.B site-swap
+notation, the "height" of each throw is given.  E.g., "3" is the height
+needed to juggle a 3\-Cascade.  Note that these sequences need to be
+chosen carefully, to avoid collisions.
+
+Annotations indicate relative hand movements or tricks:
+.TS
+cb l.
+\&\-   Inside throw (default)
++      Outside throw
+\&=    Cross Throw
+&      Cross Catch
+x      Cross Throw and Catch
+\&_    Bounce
+.TE
+.TP 8
+.B \-pattern\ \(dq[ pattern ]\(dq
+Specify juggling pattern in annotated
+.B Adam
+notation.  Adam notation is a little harder to visualize.  Each
+integer
+.B n
+represents a cyclic permutation of (0...n).  The equivalent
+.B site-swap
+value is determined by calculating how many of the permutations it
+takes to get back to the identity.  The largest number used is the
+same as the number of objects in the pattern.  The advantage of Adam
+notation is that these sequences do not need to be chosen carefully,
+since all possible sequences are juggle-able.  Annotations are the same
+as in
+.B site-swap
+notation.
+
+For example, both of these describe a 3\-Shower:
+.IP
+.B \-pattern\ "+5 1"
+.IP
+.B \-pattern\ "[+3 1]"
+
+For further examples, see the
+.B portfolio
+list in the source code.
+.TP 8
+.B \-tail number
+Minimum Trail Length.  0 \- 100.  Default: 1.  Objects may override
+this, for example flaming torches always leave a trail.
+.TP 8
+.BR \-real | \-no\-real
+Turn on/off real-time juggling.
+.B Deprecated.
+There should be no need to turn off real-time juggling, even on slow
+systems.  Adjust speed using
+.B \-count
+above.
+.TP 8
+.BR \-describe | \-no\-describe
+Turn on/off pattern descriptions.
+.TP 8 
+.BR \-balls | \-no\-balls
+Turn on/off Balls.
+.TP 8
+.BR \-clubs | \-no\-clubs
+Turn on/off Clubs.
 .TP 8
-.B \-delay \fInumber\fP
-Per-frame delay, in microseconds.  Default: 20000 (0.02 seconds.).
+.BR \-torches | \-no\-torches
+Turn on/off Flaming Torches.
 .TP 8
-.B \-speed \fInumber\fP
-Speed of objects being juggled in beats per seconds.  Default: 2.2.
+.BR \-knives | \-no\-knives
+Turn on/off Knives.
 .TP 8
-.B \-trans \fInumber\fP
-Speed of horizontal juggler movement (translational) across the screen in
-degrees/seconds.  Default: 0.1
+.BR \-rings | \-no\-rings
+Turn on/off Rings.
 .TP 8
-.B \-spin \fInumber\fP
-Speed of juggler rotation in degrees/seconds.  Default: 20
+.BR \-bballs | \-no\-bballs
+Turn on/off Bowling Balls.
 .TP 8
-.B \-maxobj \fInumber\fP
-Maximum number of objects used in a random juggling pattern. 3 - 36.
+.B \-count number
+Speed. 50 \- 1000.  Default: 200.  This determines the expected time
+interval between a throw and the next catch, in milliseconds.
 .TP 8
-.B \-minobj \fInumber\fP
-Minimum number of objects used in a random juggling pattern. 3 - \fBmaxobj\fP.
+.B \-cycles number
+Performance Length. 50 \- 1000.  Default: 1000.  Setting this smaller
+will force the juggler to switch patterns (and objects) more often.
 .TP 8
-.B \-minhinc \fInumber\fP | -maxhinc \fInumber\fP
-Used to determine maximum throw weight in random siteswap.  Options refer to
-minimum height increment and maximum height increment.  Maximum weight chosen
-will lie between \fBmaxobj\fP + \fBminhinc\fP and \fBmaxobj\fP + \fBmaxhinc\fP.
-Defaults: \fBminhinc\fP=1 and \fBmaxhinc\fP=6.
+.B \-delay delay
+Additional delay between frames, in microseconds.  Default: 10000.
+.B Deprecated.
+Adjust speed using
+.BR \-count .
 .TP 8
-.B \-wireframe | \-no-wireframe
-Render in wireframe instead of solid.
+.B \-ncolors ncolors
+Maximum number of colors to use.  Default: 32.
 .TP 8
 .B \-fps
-Display the current frame rate, CPU load, and polygon count.
+Display the current frame rate and CPU load.
 .SH ENVIRONMENT
 .PP
 .TP 8
@@ -77,12 +169,15 @@ stored in the RESOURCE_MANAGER property.
 .BR X (1),
 .BR xscreensaver (1)
 .SH COPYRIGHT
-Copyright \(co 2005 by Brian Apps.  Permission to use, copy, modify, 
-distribute, and sell this software and its documentation for any purpose is 
-hereby granted without fee, provided that the above copyright notice appear 
-in all copies and that both that copyright notice and this permission notice
-appear in supporting documentation.  No representations are made about the 
-suitability of this software for any purpose.  It is provided "as is" without
-express or implied warranty.
+Copyright \(co 1996,2000,2002,2004 by Tim Auckland.  Permission to
+use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided
+that the above copyright notice appear in all copies and that both
+that copyright notice and this permission notice appear in supporting
+documentation.  No representations are made about the suitability of
+this software for any purpose.  It is provided "as is" without express
+or implied warranty.
 .SH AUTHOR
-Brian Apps <brian@jugglesaver.co.uk>
+Tim Auckland.
+
+Converted to OpenGL by Jamie Zawinski, 2009.
index b90644da9f289e7f007ded0d4fc1a5e6ad42cc73..9753ac69ab8827c180eb414b214d073af7ba99bd 100644 (file)
-/* -*- Mode: C; tab-width: 4 -*- */
-/* Klein --- Klein Bottle, Moebius and other parametric surfaces
- * visualization */
+/* klein --- Shows a Klein bottle that rotates in 4d or on which you
+   can walk */
+
+#if 0
+static const char sccsid[] = "@(#)klein.c  1.1 08/10/04 xlockmore";
+#endif
+
+/* Copyright (c) 2005-2009 Carsten Steger <carsten@mirsanmir.org>. */
 
 /*
- * Revision History:
- * 2000: written by Andrey Mirtchovski <mirtchov@cpsc.ucalgary.ca
- *       
- * 01-Mar-2003  mirtchov    modified as a xscreensaver hack
+ * 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:
+ * C. Steger - 08/10/04: Initial version
+ * C. Steger - 09/08/03: Changes to the parameter handling
  */
 
+/*
+ * This program shows two different Klein bottles in 4d: the figure-8 Klein
+ * bottle or the Lawson Klein bottle.  You can walk on the Klein bottle, see
+ * it turn in 4d, or walk on it while it turns in 4d.  The figure-8 Klein
+ * bottle is well known in its 3d form.  The 4d form used in this program is
+ * an extension of the 3d form to 4d that does not intersect itself in 4d
+ * (which can be seen in the depth colors mode).  The Lawson Klein bottle,
+ * on the other hand, does intersect itself in 4d.  Its primary use is that
+ * it has a nice appearance for walking and for turning in 3d.  The Klein
+ * bottle is a non-orientable surface.  To make this apparent, the two-sided
+ * color mode can be used.  Alternatively, orientation markers (curling
+ * arrows) can be drawn as a texture map on the surface of the Klein bottle.
+ * While walking on the Klein bottle, you will notice that the orientation
+ * of the curling arrows changes (which it must because the Klein bottle is
+ * non-orientable).  The program projects the 4d Klein bottle to 3d using
+ * either a perspective or an orthographic projection.  Which of the two
+ * alternatives looks more appealing depends on the viewing mode and the
+ * Klein bottle.  For example, the Lawson Klein bottle looks nicest when
+ * projected perspectively.  The figure-8 Klein bottle, on the other
+ * hand, looks nicer while walking when projected orthographically from 4d.
+ * The projected Klein bottle can then be projected to the screen either
+ * perspectively or orthographically.  When using the walking modes,
+ * perspective projection to the screen should be used.  There are three
+ * display modes for the Klein bottle: mesh (wireframe), solid, or
+ * transparent.  Furthermore, the appearance of the Klein bottle can be as
+ * a solid object or as a set of see-through bands.  Finally, the colors
+ * with with the Klein bottle is drawn can be set to two-sided, rainbow, or
+ * depth.  In the first case, the Klein bottle is drawn with red on one
+ * "side" and green on the "other side".  Of course, the Klein bottle only
+ * has one side, so the color jumps from red to green along a curve on the
+ * surface of the Klein bottle.  This mode enables you to see that the Klein
+ * bottle is non-orientable.  The second mode draws the Klein bottle with
+ * fully saturated rainbow colors.  This gives a very nice effect when
+ * combined with the see-through bands mode or with the orientation markers
+ * drawn.  The third mode draws the Klein bottle with colors that are chosen
+ * according to the 4d "depth" of the points.  This mode enables you to see
+ * that the figure-8 Klein bottle does not intersect itself in 4d, while the
+ * Lawson Klein bottle does intersect itself.  The rotation speed for each
+ * of the six planes around which the Klein bottle rotates can be chosen.
+ * For the walk-and-turn more, only the rotation speeds around the true 4d
+ * planes are used (the xy, xz, and yz planes).  Furthermore, in the walking
+ * modes the walking direction in the 2d base square of the Klein bottle and
+ * the walking speed can be chosen.  This program is somewhat inspired by
+ * Thomas Banchoff's book "Beyond the Third Dimension: Geometry, Computer
+ * Graphics, and Higher Dimensions", Scientific American Library, 1990.
+ */
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+#define KLEIN_BOTTLE_FIGURE_8      0
+#define KLEIN_BOTTLE_LAWSON        1
+#define NUM_KLEIN_BOTTLES          2
+
+#define DISP_WIREFRAME             0
+#define DISP_SURFACE               1
+#define DISP_TRANSPARENT           2
+#define NUM_DISPLAY_MODES          3
+
+#define APPEARANCE_SOLID           0
+#define APPEARANCE_BANDS           1
+#define NUM_APPEARANCES            2
+
+#define COLORS_TWOSIDED            0
+#define COLORS_RAINBOW             1
+#define COLORS_DEPTH               2
+#define NUM_COLORS                 3
+
+#define VIEW_WALK                  0
+#define VIEW_TURN                  1
+#define VIEW_WALKTURN              2
+#define NUM_VIEW_MODES             3
+
+#define DISP_3D_PERSPECTIVE        0
+#define DISP_3D_ORTHOGRAPHIC       1
+#define NUM_DISP_3D_MODES          2
+
+#define DISP_4D_PERSPECTIVE        0
+#define DISP_4D_ORTHOGRAPHIC       1
+#define NUM_DISP_4D_MODES          2
+
+#define DEF_KLEIN_BOTTLE           "random"
+#define DEF_DISPLAY_MODE           "random"
+#define DEF_APPEARANCE             "random"
+#define DEF_COLORS                 "random"
+#define DEF_VIEW_MODE              "random"
+#define DEF_MARKS                  "False"
+#define DEF_PROJECTION_3D          "random"
+#define DEF_PROJECTION_4D          "random"
+#define DEF_SPEEDWX                "1.1"
+#define DEF_SPEEDWY                "1.3"
+#define DEF_SPEEDWZ                "1.5"
+#define DEF_SPEEDXY                "1.7"
+#define DEF_SPEEDXZ                "1.9"
+#define DEF_SPEEDYZ                "2.1"
+#define DEF_WALK_DIRECTION         "7.0"
+#define DEF_WALK_SPEED             "20.0"
+
 #ifdef STANDALONE
-# define DEFAULTS                                      "*delay:                20000   \n" \
-                                                                       "*showFPS:      False   \n"
+# define DEFAULTS           "*delay:      10000 \n" \
+                            "*showFPS:    False \n" \
 
 # define refresh_klein 0
-# include "xlockmore.h"                /* from the xscreensaver distribution */
+# include "xlockmore.h"         /* from the xscreensaver distribution */
 #else  /* !STANDALONE */
-# include "xlock.h"                    /* from the xlockmore distribution */
+# include "xlock.h"             /* from the xlockmore distribution */
 #endif /* !STANDALONE */
 
 #ifdef USE_GL
 
-#define DEF_SPIN                               "True"
-#define DEF_WANDER                             "False"
-#define DEF_RAND                               "True"
-#define DEF_SPEED                              "150"
+#include <X11/keysym.h>
 
-#include "rotator.h"
 #include "gltrackball.h"
 
-#undef countof
-#define countof(x) (sizeof((x))/sizeof((*x)))
-
-/* surfaces being drawn */
-enum { 
-       KLEIN = 0,
-       DINI,
-       ENNEPER,
-       KUEN,
-       MOEBIUS,
-       SEASHELL,
-       SWALLOWTAIL,
-       BOHEM,
-    SURFACE_LAST
-};
 
-/* primitives to draw with 
- * note that we skip the polygons and
- * triangle fans -- too slow
- *
- * also removed triangle_strip and quads -- 
- * just doesn't look good enough
- */
-enum {
-       MY_POINTS = 0,
-       MY_LINES,
-       MY_LINE_LOOP,
-       MY_PRIM_LAST
-};
+#ifdef USE_MODULES
+ModStruct   klein_description =
+{"klein", "init_klein", "draw_klein", "release_klein",
+ "draw_klein", "change_klein", NULL, &klein_opts,
+ 25000, 1, 1, 1, 1.0, 4, "",
+ "Rotate a Klein bottle in 4d or walk on it", 0, NULL};
 
+#endif
 
-static Bool rand;
-static int render;
-static int speed;
-static Bool do_spin;
-static Bool do_wander;
-
-static XrmOptionDescRec opts[] = {
-  {"-speed",   ".speed",    XrmoptionSepArg, 0 },
-  { "-spin",   ".spin",   XrmoptionNoArg, "True" },
-  { "+spin",   ".spin",   XrmoptionNoArg, "False" },
-  { "-wander", ".wander", XrmoptionNoArg, "True" },
-  { "+wander", ".wander", XrmoptionNoArg, "False" },
-  { "-random", ".rand", XrmoptionNoArg, "True" },
-  { "+random", ".rand", XrmoptionNoArg, "False" },
+
+static char *klein_bottle;
+static int bottle_type;
+static char *mode;
+static int display_mode;
+static char *appear;
+static int appearance;
+static char *color_mode;
+static int colors;
+static char *view_mode;
+static int view;
+static Bool marks;
+static char *proj_3d;
+static int projection_3d;
+static char *proj_4d;
+static int projection_4d;
+static float speed_wx;
+static float speed_wy;
+static float speed_wz;
+static float speed_xy;
+static float speed_xz;
+static float speed_yz;
+static float walk_direction;
+static float walk_speed;
+
+
+static XrmOptionDescRec opts[] =
+{
+  {"-klein-bottle",      ".kleinBottle",   XrmoptionSepArg, 0 },
+  {"-figure-8",          ".kleinBottle",   XrmoptionNoArg,  "figure-8" },
+  {"-lawson",            ".kleinBottle",   XrmoptionNoArg,  "lawson" },
+  {"-mode",              ".displayMode",   XrmoptionSepArg, 0 },
+  {"-wireframe",         ".displayMode",   XrmoptionNoArg,  "wireframe" },
+  {"-surface",           ".displayMode",   XrmoptionNoArg,  "surface" },
+  {"-transparent",       ".displayMode",   XrmoptionNoArg,  "transparent" },
+  {"-appearance",        ".appearance",    XrmoptionSepArg, 0 },
+  {"-solid",             ".appearance",    XrmoptionNoArg,  "solid" },
+  {"-bands",             ".appearance",    XrmoptionNoArg,  "bands" },
+  {"-colors",            ".colors",        XrmoptionSepArg, 0 },
+  {"-twosided",          ".colors",        XrmoptionNoArg,  "two-sided" },
+  {"-rainbow",           ".colors",        XrmoptionNoArg,  "rainbow" },
+  {"-depth",             ".colors",        XrmoptionNoArg,  "depth" },
+  {"-view-mode",         ".viewMode",      XrmoptionSepArg, 0 },
+  {"-walk",              ".viewMode",      XrmoptionNoArg,  "walk" },
+  {"-turn",              ".viewMode",      XrmoptionNoArg,  "turn" },
+  {"-walk-turn",         ".viewMode",      XrmoptionNoArg,  "walk-turn" },
+  {"-orientation-marks", ".marks",         XrmoptionNoArg, "on"},
+  {"+orientation-marks", ".marks",         XrmoptionNoArg, "off"},
+  {"-projection-3d",     ".projection3d",  XrmoptionSepArg, 0 },
+  {"-perspective-3d",    ".projection3d",  XrmoptionNoArg,  "perspective" },
+  {"-orthographic-3d",   ".projection3d",  XrmoptionNoArg,  "orthographic" },
+  {"-projection-4d",     ".projection4d",  XrmoptionSepArg, 0 },
+  {"-perspective-4d",    ".projection4d",  XrmoptionNoArg,  "perspective" },
+  {"-orthographic-4d",   ".projection4d",  XrmoptionNoArg,  "orthographic" },
+  {"-speed-wx",          ".speedwx",       XrmoptionSepArg, 0 },
+  {"-speed-wy",          ".speedwy",       XrmoptionSepArg, 0 },
+  {"-speed-wz",          ".speedwz",       XrmoptionSepArg, 0 },
+  {"-speed-xy",          ".speedxy",       XrmoptionSepArg, 0 },
+  {"-speed-xz",          ".speedxz",       XrmoptionSepArg, 0 },
+  {"-speed-yz",          ".speedyz",       XrmoptionSepArg, 0 },
+  {"-walk-direction",    ".walkDirection", XrmoptionSepArg, 0 },
+  {"-walk-speed",        ".walkSpeed",     XrmoptionSepArg, 0 }
 };
 
-static argtype vars[] = {
-  {&rand,      "rand",   "Random", DEF_RAND,   t_Bool},
-  {&do_spin,   "spin",   "Spin",   DEF_SPIN,   t_Bool},
-  {&do_wander, "wander", "Wander", DEF_WANDER, t_Bool},
-  {&speed,     "speed",  "Speed",  DEF_SPEED,  t_Int},
+static argtype vars[] =
+{
+  { &klein_bottle,   "kleinBottle",   "KleinBottle",   DEF_KLEIN_BOTTLE,   t_String },
+  { &mode,           "displayMode",   "DisplayMode",   DEF_DISPLAY_MODE,   t_String },
+  { &appear,         "appearance",    "Appearance",    DEF_APPEARANCE,     t_String },
+  { &color_mode,     "colors",        "Colors",        DEF_COLORS,         t_String },
+  { &view_mode,      "viewMode",      "ViewMode",      DEF_VIEW_MODE,      t_String },
+  { &marks,          "marks",         "Marks",         DEF_MARKS,          t_Bool },
+  { &proj_3d,        "projection3d",  "Projection3d",  DEF_PROJECTION_3D,  t_String },
+  { &proj_4d,        "projection4d",  "Projection4d",  DEF_PROJECTION_4D,  t_String },
+  { &speed_wx,       "speedwx",       "Speedwx",       DEF_SPEEDWX,        t_Float},
+  { &speed_wy,       "speedwy",       "Speedwy",       DEF_SPEEDWY,        t_Float},
+  { &speed_wz,       "speedwz",       "Speedwz",       DEF_SPEEDWZ,        t_Float},
+  { &speed_xy,       "speedxy",       "Speedxy",       DEF_SPEEDXY,        t_Float},
+  { &speed_xz,       "speedxz",       "Speedxz",       DEF_SPEEDXZ,        t_Float},
+  { &speed_yz,       "speedyz",       "Speedyz",       DEF_SPEEDYZ,        t_Float},
+  { &walk_direction, "walkDirection", "WalkDirection", DEF_WALK_DIRECTION, t_Float},
+  { &walk_speed,     "walkSpeed",     "WalkSpeed",     DEF_WALK_SPEED,     t_Float}
 };
 
+ENTRYPOINT ModeSpecOpt klein_opts =
+{sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, NULL};
+
 
-ENTRYPOINT ModeSpecOpt klein_opts = {countof(opts), opts, countof(vars), vars, NULL};
+/* Radius of the Figure 8 Klein bottle */
+#define FIGURE_8_RADIUS 2.0
 
+/* Offset by which we walk above the Klein bottle */
+#define DELTAY  0.02
 
+/* Number of subdivisions of the Klein bottle */
+#define NUMU 128
+#define NUMV 128
+
+/* Number of subdivisions per band */
+#define NUMB 8
 
-typedef struct{
-  GLfloat x;
-  GLfloat y;
-  GLfloat z;
-} GL_VECTOR;
 
 typedef struct {
-       GLXContext *glx_context;
-       Window      window;
-       rotator    *rot;
-       trackball_state *trackball;
-       Bool              button_down_p;
+  GLint      WindH, WindW;
+  GLXContext *glx_context;
+  /* 4D rotation angles */
+  float alpha, beta, delta, zeta, eta, theta;
+  /* Movement parameters */
+  float umove, vmove, dumove, dvmove;
+  int side;
+  /* The viewing offset in 4d */
+  float offset4d[4];
+  /* The viewing offset in 3d */
+  float offset3d[4];
+  /* The 4d coordinates of the Klein bottle and their derivatives */
+  float x[(NUMU+1)*(NUMV+1)][4];
+  float xu[(NUMU+1)*(NUMV+1)][4];
+  float xv[(NUMU+1)*(NUMV+1)][4];
+  float pp[(NUMU+1)*(NUMV+1)][3];
+  float pn[(NUMU+1)*(NUMV+1)][3];
+  /* The precomputed colors of the Klein bottle */
+  float col[(NUMU+1)*(NUMV+1)][4];
+  /* The precomputed texture coordinates of the Klein bottle */
+  float tex[(NUMU+1)*(NUMV+1)][2];
+  /* The "curlicue" texture */
+  GLuint tex_name;
+  /* Aspect ratio of the current window */
+  float aspect;
+  /* Trackball states */
+  trackball_state *trackballs[2];
+  int current_trackball;
+  Bool button_pressed;
+  /* A random factor to modify the rotation speeds */
+  float speed_scale;
+} kleinstruct;
 
-       int render;
-       int surface;
+static kleinstruct *klein = (kleinstruct *) NULL;
+
+
+/* A texture map containing a "curlicue" */
+#define TEX_DIMENSION 64
+static const unsigned char texture[TEX_DIMENSION*TEX_DIMENSION] = {
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255, 58, 43, 43, 43, 43, 45, 70, 70, 70,
+   70, 70, 70, 70, 74, 98, 98, 98,100,194,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255, 18,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0, 30,186,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255, 18,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  1,111,244,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255, 18,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0, 43,198,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255, 18,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  5,123,248,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255, 18,  0,  0,  0,  0,  0,  0,  0,  0,
+    0, 50,209,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,246,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255, 18,  0,  0,  0,  0,  0,  0,  0,  0,
+   74,252,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,138,  4,
+   66,229,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255, 18,  0,  0,  0,  0,  0,  0,  0,  0,
+    1,170,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,153,  0,  0,
+    0, 53,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255, 18,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  6,188,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,213,  7,  0,  0,
+    0,  0,226,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255, 45,  0,  0,  0,  0,  0, 47,  0,  0,
+    0,  0, 22,225,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,254, 54,  0,  0,  0,
+    0, 81,254,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255, 45,  0,  0,  0,  0, 56,247, 82,  0,
+    0,  0,  0, 59,253,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,152,  0,  0,  0,  0,
+   52,243,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255, 45,  0,  0,  0,  8,215,255,250, 56,
+    0,  0,  0,  0,142,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,241, 19,  0,  0,  0, 15,
+  220,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255, 45,  0,  0,  0,129,255,255,255,230,
+   23,  0,  0,  0, 12,230,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,131,  0,  0,  0,  0,157,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255, 45,  0,  0, 49,250,255,255,255,255,
+  171,  0,  0,  0,  0,112,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,246, 19,  0,  0,  0, 54,253,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255, 45,  0,  5,208,255,255,255,255,255,
+  255, 77,  0,  0,  0,  9,231,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,163,  0,  0,  0,  0,186,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255, 45,  0,121,255,255,255,255,255,255,
+  255,211,  2,  0,  0,  0,134,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255, 69,  0,  0,  0, 50,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255, 45, 41,247,255,255,255,255,255,255,
+  255,255, 73,  0,  0,  0, 38,254,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,237,  4,  0,  0,  0,145,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255, 52,201,255,255,255,255,255,255,255,
+  255,255,169,  0,  0,  0,  0,216,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,181,  0,  0,  0,  0,229,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,186,255,255,255,255,255,255,255,255,
+  255,255,247,  7,  0,  0,  0,150,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,130,  0,  0,  0, 42,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255, 67,  0,  0,  0, 91,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255, 79,  0,  0,  0, 95,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,120,  0,  0,  0, 56,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255, 55,  0,  0,  0,130,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,157,  0,  0,  0, 21,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255, 34,  0,  0,  0,161,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,179,  0,  0,  0,  2,250,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255, 27,  0,  0,  0,168,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,200,  0,  0,  0,  0,249,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255, 27,  0,  0,  0,168,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,200,  0,  0,  0,  0,249,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255, 27,  0,  0,  0,163,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,183,  0,  0,  0,  0,249,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255, 42,  0,  0,  0,135,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,161,  0,  0,  0, 17,254,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255, 76,  0,  0,  0,100,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,126,  0,  0,  0, 48,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,114,  0,  0,  0, 53,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255, 78,  0,  0,  0, 84,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,165,  0,  0,  0,  3,241,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,252, 16,  0,  0,  0,139,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,228,  0,  0,  0,  0,161,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,192,  0,  0,  0,  0,198,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255, 46,  0,  0,  0, 67,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255, 93,  0,  0,  0, 21,250,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,139,  0,  0,  0,  1,211,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,226,  7,  0,  0,  0,108,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,230,  6,  0,  0,  0, 79,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,106,  0,  0,  0,  1,206,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255, 97,  0,  0,  0,  0,183,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  202,  3,  0,  0,  0, 67,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,221,  8,  0,  0,  0, 27,
+  235,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,243,
+   40,  0,  0,  0,  0,198,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,126,  0,  0,  0,  0,
+   71,252,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,253, 85,
+    0,  0,  0,  0, 96,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,247, 44,  0,  0,  0,
+    0, 91,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,116,  0,
+    0,  0,  0, 25,233,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,216, 11,  0,  0,
+    0,  0, 90,251,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,252,112,  0,  0,
+    0,  0,  4,191,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,174,  4,  0,
+    0,  0,  0, 72,235,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,242, 84,  0,  0,  0,
+    0,  0,146,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,150,  1,
+    0,  0,  0,  0, 27,181,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,194, 39,  0,  0,  0,  0,
+    0,120,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,151,
+    4,  0,  0,  0,  0,  0, 77,209,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,216, 92,  1,  0,  0,  0,  0,  0,
+  125,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  175, 12,  0,  0,  0,  0,  0,  1, 70,164,241,255,255,255,255,255,
+  255,255,255,255,255,242,171, 77,  2,  0,  0,  0,  0,  0,  4,150,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,214, 41,  0,  0,  0,  0,  0,  0,  0,  4, 48, 98,138,163,163,
+  163,163,140,103, 55,  5,  0,  0,  0,  0,  0,  0,  0, 30,199,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,245,125,  8,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  3,105,240,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,222,100,  5,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  2, 83,210,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,228,136, 45,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0, 37,125,220,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,225,166,112, 74, 43, 32, 12,
+    8, 32, 40, 71,105,162,218,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+  255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+};
 
-       float du, dv;
-       float a, b, c;
 
-    float draw_step;
+/* Add a rotation around the wx-plane to the matrix m. */
+static void rotatewx(float m[4][4], float phi)
+{
+  float c, s, u, v;
+  int i;
+
+  phi *= M_PI/180.0;
+  c = cos(phi);
+  s = sin(phi);
+  for (i=0; i<4; i++)
+  {
+    u = m[i][1];
+    v = m[i][2];
+    m[i][1] = c*u+s*v;
+    m[i][2] = -s*u+c*v;
+  }
+}
 
-} kleinstruct;
 
-static kleinstruct *klein = NULL;
+/* Add a rotation around the wy-plane to the matrix m. */
+static void rotatewy(float m[4][4], float phi)
+{
+  float c, s, u, v;
+  int i;
+
+  phi *= M_PI/180.0;
+  c = cos(phi);
+  s = sin(phi);
+  for (i=0; i<4; i++)
+  {
+    u = m[i][0];
+    v = m[i][2];
+    m[i][0] = c*u-s*v;
+    m[i][2] = s*u+c*v;
+  }
+}
 
 
-static void
-draw(ModeInfo *mi)
+/* Add a rotation around the wz-plane to the matrix m. */
+static void rotatewz(float m[4][4], float phi)
 {
-       kleinstruct *kp = &klein[MI_SCREEN(mi)];
-       double u, v;
-       float coord[3];
-       
-    mi->polygon_count = 0;
-       glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
-       glEnable(GL_DEPTH_TEST);
-       glEnable(GL_NORMALIZE);
-       glEnable(GL_CULL_FACE);
-
-       glPushMatrix();
-
-       {
-               double x, y, z;
-               get_position (kp->rot, &x, &y, &z, !kp->button_down_p);
-               glTranslatef((x - 0.5) * 10,
-                                                                (y - 0.5) * 10,
-                                                                (z - 0.5) * 20);
-
-               gltrackball_rotate (kp->trackball);
-
-               get_rotation (kp->rot, &x, &y, &z, !kp->button_down_p);
-               glRotatef (x * 360, 1.0, 0.0, 0.0);
-               glRotatef (y * 360, 0.0, 1.0, 0.0);
-               glRotatef (z * 360, 0.0, 0.0, 1.0);
-       }
-
-       glScalef( 4.0, 4.0, 4.0 );
-
-       glBegin(kp->render);
-       switch(kp->surface) {
-       case KLEIN:
-               for(u = -M_PI; u < M_PI; u+=kp->du){
-                       for(v = -M_PI; v < M_PI; v+=kp->dv){
-                               coord[0] = cos(u)*(kp->a + sin(v)*cos(u/2) -
-                                                       sin(2*v)*sin(u/2)/2);
-                               coord[1] = sin(u)*(kp->a + sin(v)*cos(u/2) -
-                                                       sin(2*v)*sin(u/2)/2);
-                               coord[2] = sin(u/2)*sin(v) + cos(u/2)*sin(2*v)/2;
-                               glColor3f(coord[0]+0.7, coord[1]+0.7, coord[2]+0.7);
-                               glVertex3fv(coord);
-                mi->polygon_count++;
-                       }
-               }
-               break;
-               case DINI:
-                       for(u = -M_PI; u < M_PI; u+=kp->du){
-                               for(v = -M_PI; v < M_PI; v+=kp->dv){
-                                       coord[0] = kp->a*cos(u)*sin(v);
-                                       coord[1] = kp->a*sin(u)*sin(v);
-                                       coord[2] = kp->a*(cos(v) + sin(tan((v/2))))+0.2*u;
-                                       glColor3f(coord[0]+0.7, coord[1]+0.7, coord[2]+0.7);
-                                       glVertex3fv(coord);
-                    mi->polygon_count++;
-                               }
-                       }
-                       break;
-               case ENNEPER:
-                       for(u = -M_PI; u < M_PI; u+=kp->du){
-                               for(v = -M_PI; v < M_PI; v+=kp->dv){
-                                       coord[0] = kp->a*(u-(u*u*u/3)+u*v*v);
-                                       coord[1] = kp->b*(v-(v*v*v/3)+u*u*v);
-                                       coord[2] = u*u-v*v;
-                                       glColor3f(coord[0]+0.7, coord[1]+0.7, coord[2]+0.7);
-                                       glVertex3fv(coord);
-                    mi->polygon_count++;
-                               }
-                       }
-                       break;
-               case KUEN:
-                       for(u = -M_PI; u < M_PI; u+=kp->du){
-                               for(v = -M_PI; v < M_PI; v+=kp->dv){
-                                       coord[0] = 2*(cos(u)+u*sin(u))*sin(v)/(1+u*u*sin(v)*sin(v));
-                                       coord[1] = 2*(sin(u)-u*cos(u))*sin(v)/(1+u*u*sin(v)*sin(v));
-                                       coord[2] = sin(tan(v/2))+2*cos(v)/(1+u*u*sin(v)*sin(v));
-
-                                       glColor3f(coord[0]+0.7, coord[1]+0.7, coord[2]+0.7);
-                                       glVertex3fv(coord);
-                    mi->polygon_count++;
-                               }
-                       }
-                       break;
-               case MOEBIUS:
-                       for(u = -M_PI; u < M_PI; u+=kp->du){
-                               for(v = -M_PI; v < M_PI; v+=kp->dv){
-                                       coord[0] = cos(u)+v*cos(u/2)*cos(u);
-                                       coord[1] = sin(u)+v*cos(u/2)*sin(u);
-                                       coord[2] = v*sin(u/2);
-                                       glColor3f(coord[0]+0.7, coord[1]+0.7, coord[2]+0.7);
-                                       glVertex3fv(coord);
-                    mi->polygon_count++;
-                               }
-                       }
-                       break;
-               case SEASHELL:
-                       for(u = 0; u < 2*M_PI; u+=kp->du){
-                               for(v = 0; v < 2*M_PI; v+=kp->dv){
-                                       coord[0] = kp->a*(1-v/(2*M_PI))*cos(2*v)*(1+cos(u))+sin(kp->c+=0.00001)*cos(2*v);
-                                       coord[1] = kp->a*(1-v/(2*M_PI))*sin(2*v)*(1+cos(u))+cos(kp->c+=0.00001)*sin(2*v);
-                                       coord[2] = sin(kp->b+=0.00001)*v/(2*M_PI)+kp->a*(1-v/(2*M_PI))*sin(u);
-                                       glColor3f(coord[0]+0.7, coord[1]+0.7, coord[2]+0.7);
-                                       glVertex3fv(coord);
-                    mi->polygon_count++;
-                               }
-                       }
-                       break;
-               case SWALLOWTAIL:
-                       for(u = -M_PI; u < M_PI; u+=kp->du){
-                               for(v = -M_PI; v < M_PI; v+=kp->dv){
-                                       coord[0] = u*pow(v,2) + 3*pow(v,4);
-                                       coord[1] = -2*u*v - 4*pow(v,3);
-                                       coord[2] = u;
-                                       glColor3f(coord[0]+0.7, coord[1]+0.7, coord[2]+0.7);
-                                       glVertex3fv(coord);
-                    mi->polygon_count++;
-                               }
-                       }
-                       break;
-               case BOHEM:
-                       for(u = -M_PI; u < M_PI; u+=kp->du){
-                               for(v = -M_PI; v < M_PI; v+=kp->dv){
-                                       coord[0] = kp->a*cos(u);
-                                       coord[1] = 1.5*cos(v) + kp->a*sin(u);
-                                       coord[2] = sin(v);
-                                       glColor3f(coord[0]+0.7, coord[1]+0.7, coord[2]+0.7);
-                                       glVertex3fv(coord);
-                    mi->polygon_count++;
-                               }
-                       }
-                       break;
-               default:
-                       for(u = -M_PI; u < M_PI; u+=kp->du){
-                               for(v = -M_PI; v < M_PI; v+=kp->dv){
-                                       coord[0] = sin(u)*kp->a;        
-                                       coord[1] = cos(u)*kp->a;
-                                       coord[2] = sin(u/2)*cos(v) + cos(u/2)*sin(v);
-                                       glColor3f(coord[0]+0.7, coord[1]+0.7, coord[2]+0.7);
-                                       glVertex3fv(coord);
-                    mi->polygon_count++;
-                               }
-                       }
-                       break;
-       }
-       glEnd();
-       glPopMatrix();
-
-    if (kp->render == GL_LINES)
-      mi->polygon_count /= 2;
-
-       kp->a = sin(kp->draw_step+=0.01);
-       kp->b = cos(kp->draw_step+=0.01);
+  float c, s, u, v;
+  int i;
+
+  phi *= M_PI/180.0;
+  c = cos(phi);
+  s = sin(phi);
+  for (i=0; i<4; i++)
+  {
+    u = m[i][0];
+    v = m[i][1];
+    m[i][0] = c*u+s*v;
+    m[i][1] = -s*u+c*v;
+  }
 }
 
 
-/* new window size or exposure */
-ENTRYPOINT void
-reshape_klein(ModeInfo *mi, int width, int height)
+/* Add a rotation around the xy-plane to the matrix m. */
+static void rotatexy(float m[4][4], float phi)
 {
-       GLfloat h = (GLfloat) height / (GLfloat) width;
-
-       glViewport(0, 0, (GLint) width, (GLint) height);
-       glMatrixMode(GL_PROJECTION);
-       glLoadIdentity();
-       gluPerspective (30.0, 1/h, 1.0, 100.0);
-
-       glMatrixMode(GL_MODELVIEW);
-       glLoadIdentity();
-       gluLookAt( 0.0, 0.0, 30.0,
-                        0.0, 0.0, 0.0,
-                        0.0, 1.0, 0.0);
-       
-       glClear(GL_COLOR_BUFFER_BIT);
+  float c, s, u, v;
+  int i;
+
+  phi *= M_PI/180.0;
+  c = cos(phi);
+  s = sin(phi);
+  for (i=0; i<4; i++)
+  {
+    u = m[i][2];
+    v = m[i][3];
+    m[i][2] = c*u+s*v;
+    m[i][3] = -s*u+c*v;
+  }
 }
 
 
-ENTRYPOINT Bool
-klein_handle_event (ModeInfo *mi, XEvent *event)
+/* Add a rotation around the xz-plane to the matrix m. */
+static void rotatexz(float m[4][4], float phi)
 {
-       kleinstruct *kp = &klein[MI_SCREEN(mi)];
-
-       if (event->xany.type == ButtonPress && event->xbutton.button == Button1) {
-                       kp->button_down_p = True;
-                       gltrackball_start (kp->trackball, event->xbutton.x, event->xbutton.y, MI_WIDTH (mi), MI_HEIGHT (mi));
-                       return True;
-       } else if (event->xany.type == ButtonRelease && event->xbutton.button == Button1) {
-                       kp->button_down_p = False;
-                       return True;
-       } else if (event->xany.type == ButtonPress &&
-               (event->xbutton.button == Button4 ||
-                event->xbutton.button == Button5 ||
-                event->xbutton.button == Button6 ||
-                event->xbutton.button == Button7)) {
-      gltrackball_mousewheel (kp->trackball, event->xbutton.button, 10,
-                              !!event->xbutton.state);
-      return True;
-    } else if (event->xany.type == MotionNotify && kp->button_down_p) {
-                       gltrackball_track (kp->trackball, event->xmotion.x, event->xmotion.y, MI_WIDTH (mi), MI_HEIGHT (mi));
-                       return True;
-       }
+  float c, s, u, v;
+  int i;
+
+  phi *= M_PI/180.0;
+  c = cos(phi);
+  s = sin(phi);
+  for (i=0; i<4; i++)
+  {
+    u = m[i][1];
+    v = m[i][3];
+    m[i][1] = c*u-s*v;
+    m[i][3] = s*u+c*v;
+  }
+}
 
-       return False;
+
+/* Add a rotation around the yz-plane to the matrix m. */
+static void rotateyz(float m[4][4], float phi)
+{
+  float c, s, u, v;
+  int i;
+
+  phi *= M_PI/180.0;
+  c = cos(phi);
+  s = sin(phi);
+  for (i=0; i<4; i++)
+  {
+    u = m[i][0];
+    v = m[i][3];
+    m[i][0] = c*u-s*v;
+    m[i][3] = s*u+c*v;
+  }
 }
 
 
-ENTRYPOINT void
-init_klein(ModeInfo *mi)
+/* Compute the rotation matrix m from the rotation angles. */
+static void rotateall(float al, float be, float de, float ze, float et,
+                      float th, float m[4][4])
 {
-       int      screen = MI_SCREEN(mi);
-       kleinstruct *kp;
-
-       if (klein == NULL) {
-               if ((klein = (kleinstruct *) calloc(MI_NUM_SCREENS(mi), sizeof (kleinstruct))) == NULL)
-                       return;
-       }
-       kp = &klein[screen];
-
-       kp->window = MI_WINDOW(mi);
-
-       {
-               double spin_speed        = 1.0;
-               double wander_speed = 0.03;
-               kp->rot = make_rotator (do_spin ? spin_speed : 0,
-                                               do_spin ? spin_speed : 0,
-                                               do_spin ? spin_speed : 0,
-                                               1.0,
-                                               do_wander ? wander_speed : 0,
-                                               True);
-               kp->trackball = gltrackball_init ();
-       }
-
-       if(rand) {
-               render = random() % MY_PRIM_LAST;
-               kp->surface = random() % SURFACE_LAST;
-       } else {
-               render = MY_LINE_LOOP;
-               kp->surface = KLEIN;
-       }
-
-       switch (render) {
-       case MY_POINTS: kp->render = GL_POINTS; break;
-       case MY_LINES: kp->render = GL_LINES; break;
-       case MY_LINE_LOOP: kp->render = GL_LINE_LOOP; break;
-       default:
-                       kp->render = GL_LINE_LOOP;
-       }
-/*kp->render=GL_TRIANGLE_FAN;*/
-/*kp->render=GL_POLYGON;*/
-
-       kp->du = 0.07;
-       kp->dv = 0.07;
-       kp->a = kp->b = 1;
-       kp->c = 0.1;
-
-
-       if ((kp->glx_context = init_GL(mi)) != NULL) {
-               reshape_klein(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
-       } else {
-               MI_CLEARWINDOW(mi);
-       }
+  int i, j;
+
+  for (i=0; i<4; i++)
+    for (j=0; j<4; j++)
+      m[i][j] = (i==j);
+  rotatewx(m,al);
+  rotatewy(m,be);
+  rotatewz(m,de);
+  rotatexy(m,ze);
+  rotatexz(m,et);
+  rotateyz(m,th);
 }
 
-ENTRYPOINT void
-draw_klein(ModeInfo * mi)
+
+/* Compute the rotation matrix m from the 4d rotation angles. */
+static void rotateall4d(float ze, float et, float th, float m[4][4])
 {
-       kleinstruct *kp = &klein[MI_SCREEN(mi)];
-       Display *display = MI_DISPLAY(mi);
-       Window  window = MI_WINDOW(mi);
+  int i, j;
+
+  for (i=0; i<4; i++)
+    for (j=0; j<4; j++)
+      m[i][j] = (i==j);
+  rotatexy(m,ze);
+  rotatexz(m,et);
+  rotateyz(m,th);
+}
 
-       if (!kp->glx_context) return;
 
-       glDrawBuffer(GL_BACK);
+/* Multiply two rotation matrices: o=m*n. */
+static void mult_rotmat(float m[4][4], float n[4][4], float o[4][4])
+{
+  int i, j, k;
+
+  for (i=0; i<4; i++)
+  {
+    for (j=0; j<4; j++)
+    {
+      o[i][j] = 0.0;
+      for (k=0; k<4; k++)
+        o[i][j] += m[i][k]*n[k][j];
+    }
+  }
+}
+
 
-       glXMakeCurrent(display, window, *(kp->glx_context));
-       draw(mi);
-       if (mi->fps_p) do_fps (mi);
-       glFinish();
-       glXSwapBuffers(display, window);
+/* Compute a 4D rotation matrix from two unit quaternions. */
+static void quats_to_rotmat(float p[4], float q[4], float m[4][4])
+{
+  double al, be, de, ze, et, th;
+  double r00, r01, r02, r12, r22;
+
+  r00 = 1.0-2.0*(p[1]*p[1]+p[2]*p[2]);
+  r01 = 2.0*(p[0]*p[1]+p[2]*p[3]);
+  r02 = 2.0*(p[2]*p[0]-p[1]*p[3]);
+  r12 = 2.0*(p[1]*p[2]+p[0]*p[3]);
+  r22 = 1.0-2.0*(p[1]*p[1]+p[0]*p[0]);
+
+  al = atan2(-r12,r22)*180.0/M_PI;
+  be = atan2(r02,sqrt(r00*r00+r01*r01))*180.0/M_PI;
+  de = atan2(-r01,r00)*180.0/M_PI;
+
+  r00 = 1.0-2.0*(q[1]*q[1]+q[2]*q[2]);
+  r01 = 2.0*(q[0]*q[1]+q[2]*q[3]);
+  r02 = 2.0*(q[2]*q[0]-q[1]*q[3]);
+  r12 = 2.0*(q[1]*q[2]+q[0]*q[3]);
+  r22 = 1.0-2.0*(q[1]*q[1]+q[0]*q[0]);
+
+  et = atan2(-r12,r22)*180.0/M_PI;
+  th = atan2(r02,sqrt(r00*r00+r01*r01))*180.0/M_PI;
+  ze = atan2(-r01,r00)*180.0/M_PI;
+
+  rotateall(al,be,de,ze,et,-th,m);
 }
 
-ENTRYPOINT void
-release_klein(ModeInfo * mi)
+
+/* Compute a fully saturated and bright color based on an angle. */
+static void color(double angle, float col[4])
 {
-       if (klein != NULL) {
-               int      screen;
-
-               for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) {
-                       kleinstruct *kp = &klein[screen];
-
-                       if (kp->glx_context) {
-                               /* Display lists MUST be freed while their glXContext is current. */
-                               glXMakeCurrent(MI_DISPLAY(mi), kp->window, *(kp->glx_context));
-                       }
-               }
-               (void) free((void *) klein);
-               klein = NULL;
-       }
-       FreeAllGL(mi);
+  int s;
+  double t;
+
+  if (colors == COLORS_TWOSIDED)
+    return;
+
+  if (angle >= 0.0)
+    angle = fmod(angle,2.0*M_PI);
+  else
+    angle = fmod(angle,-2.0*M_PI);
+  s = floor(angle/(M_PI/3));
+  t = angle/(M_PI/3)-s;
+  if (s >= 6)
+    s = 0;
+  switch (s)
+  {
+    case 0:
+      col[0] = 1.0;
+      col[1] = t;
+      col[2] = 0.0;
+      break;
+    case 1:
+      col[0] = 1.0-t;
+      col[1] = 1.0;
+      col[2] = 0.0;
+      break;
+    case 2:
+      col[0] = 0.0;
+      col[1] = 1.0;
+      col[2] = t;
+      break;
+    case 3:
+      col[0] = 0.0;
+      col[1] = 1.0-t;
+      col[2] = 1.0;
+      break;
+    case 4:
+      col[0] = t;
+      col[1] = 0.0;
+      col[2] = 1.0;
+      break;
+    case 5:
+      col[0] = 1.0;
+      col[1] = 0.0;
+      col[2] = 1.0-t;
+      break;
+  }
+  if (display_mode == DISP_TRANSPARENT)
+    col[3] = 0.7;
+  else
+    col[3] = 1.0;
 }
 
 
-XSCREENSAVER_MODULE ("Klein", klein)
+/* Set up the figure-8 Klein bottle coordinates, colors, and texture. */
+static void setup_figure8(ModeInfo *mi, double umin, double umax, double vmin,
+                          double vmax)
+{
+  int i, j, k, l;
+  double u, v, ur, vr;
+  double cu, su, cv, sv, cv2, sv2, c2u, s2u;
+  kleinstruct *kb = &klein[MI_SCREEN(mi)];
+
+  ur = umax-umin;
+  vr = vmax-vmin;
+  for (i=0; i<=NUMU; i++)
+  {
+    for (j=0; j<=NUMV; j++)
+    {
+      k = i*(NUMV+1)+j;
+      u = -ur*j/NUMU+umin;
+      v = vr*i/NUMV+vmin;
+      if (colors == COLORS_DEPTH)
+        color((cos(u)+1.0)*M_PI*2.0/3.0,kb->col[k]);
+      else
+        color(v,kb->col[k]);
+      kb->tex[k][0] = -32*u/(2.0*M_PI);
+      kb->tex[k][1] = 32*v/(2.0*M_PI);
+      cu = cos(u);
+      su = sin(u);
+      cv = cos(v);
+      sv = sin(v);
+      cv2 = cos(0.5*v);
+      sv2 = sin(0.5*v);
+      c2u = cos(2.0*u);
+      s2u = sin(2.0*u);
+      kb->x[k][0] = (su*cv2-s2u*sv2+FIGURE_8_RADIUS)*cv;
+      kb->x[k][1] = (su*cv2-s2u*sv2+FIGURE_8_RADIUS)*sv;
+      kb->x[k][2] = su*sv2+s2u*cv2;
+      kb->x[k][3] = cu;
+      kb->xu[k][0] = (cu*cv2-2.0*c2u*sv2)*cv;
+      kb->xu[k][1] = (cu*cv2-2.0*c2u*sv2)*sv;
+      kb->xu[k][2] = cu*sv2+2.0*c2u*cv2;
+      kb->xu[k][3] = -su;
+      kb->xv[k][0] = ((-0.5*su*sv2-0.5*s2u*cv2)*cv-
+                      (su*cv2-s2u*sv2+FIGURE_8_RADIUS)*sv);
+      kb->xv[k][1] = ((-0.5*su*sv2-0.5*s2u*cv2)*sv+
+                      (su*cv2-s2u*sv2+FIGURE_8_RADIUS)*cv);
+      kb->xv[k][2] = 0.5*su*cv2-0.5*s2u*sv2;
+      kb->xv[k][3] = 0.0;
+      for (l=0; l<4; l++)
+      {
+        kb->x[k][l] /= FIGURE_8_RADIUS+1.25;
+        kb->xu[k][l] /= FIGURE_8_RADIUS+1.25;
+        kb->xv[k][l] /= FIGURE_8_RADIUS+1.25;
+      }
+    }
+  }
+}
 
-/*********************************************************/
 
-#endif
+/* Set up the Lawson Klein bottle coordinates, colors, and texture. */
+static void setup_lawson(ModeInfo *mi, double umin, double umax, double vmin,
+                         double vmax)
+{
+  int i, j, k;
+  double u, v, ur, vr;
+  double cu, su, cv, sv, cv2, sv2;
+  kleinstruct *kb = &klein[MI_SCREEN(mi)];
+
+  ur = umax-umin;
+  vr = vmax-vmin;
+  for (i=0; i<=NUMV; i++)
+  {
+    for (j=0; j<=NUMU; j++)
+    {
+      k = i*(NUMU+1)+j;
+      u = -ur*j/NUMU+umin;
+      v = vr*i/NUMV+vmin;
+      if (colors == COLORS_DEPTH)
+        color((sin(u)*cos(0.5*v)+1.0)*M_PI*2.0/3.0,kb->col[k]);
+      else
+        color(v,kb->col[k]);
+      kb->tex[k][0] = -32*u/(2.0*M_PI);
+      kb->tex[k][1] = 32*v/(2.0*M_PI);
+      cu = cos(u);
+      su = sin(u);
+      cv = cos(v);
+      sv = sin(v);
+      cv2 = cos(0.5*v);
+      sv2 = sin(0.5*v);
+      kb->x[k][0] = cu*cv;
+      kb->x[k][1] = cu*sv;
+      kb->x[k][2] = su*sv2;
+      kb->x[k][3] = su*cv2;
+      kb->xu[k][0] = -su*cv;
+      kb->xu[k][1] = -su*sv;
+      kb->xu[k][2] = cu*sv2;
+      kb->xu[k][3] = cu*cv2;
+      kb->xv[k][0] = -cu*sv;
+      kb->xv[k][1] = cu*cv;
+      kb->xv[k][2] = su*cv2*0.5;
+      kb->xv[k][3] = -su*sv2*0.5;
+    }
+  }
+}
+
+
+/* Draw a figure-8 Klein bottle projected into 3D. */
+static int figure8(ModeInfo *mi, double umin, double umax, double vmin,
+                   double vmax)
+{
+  int polys = 0;
+  static const GLfloat mat_diff_red[]         = { 1.0, 0.0, 0.0, 1.0 };
+  static const GLfloat mat_diff_green[]       = { 0.0, 1.0, 0.0, 1.0 };
+  static const GLfloat mat_diff_trans_red[]   = { 1.0, 0.0, 0.0, 0.7 };
+  static const GLfloat mat_diff_trans_green[] = { 0.0, 1.0, 0.0, 0.7 };
+  float p[3], pu[3], pv[3], pm[3], n[3], b[3], mat[4][4];
+  int i, j, k, l, m, o;
+  double u, v;
+  double xx[4], xxu[4], xxv[4], y[4], yu[4], yv[4];
+  double q, r, s, t;
+  double cu, su, cv, sv, cv2, sv2, c2u, s2u;
+  float q1[4], q2[4], r1[4][4], r2[4][4];
+  kleinstruct *kb = &klein[MI_SCREEN(mi)];
+
+  if (view == VIEW_WALK || view == VIEW_WALKTURN)
+  {
+    /* Compute the rotation that rotates the Klein bottle in 4D without the
+       trackball rotations. */
+    rotateall4d(kb->zeta,kb->eta,kb->theta,mat);
+
+    u = kb->umove;
+    v = kb->vmove;
+    cu = cos(u);
+    su = sin(u);
+    cv = cos(v);
+    sv = sin(v);
+    cv2 = cos(0.5*v);
+    sv2 = sin(0.5*v);
+    c2u = cos(2.0*u);
+    s2u = sin(2.0*u);
+    xx[0] = (su*cv2-s2u*sv2+FIGURE_8_RADIUS)*cv;
+    xx[1] = (su*cv2-s2u*sv2+FIGURE_8_RADIUS)*sv;
+    xx[2] = su*sv2+s2u*cv2;
+    xx[3] = cu;
+    xxu[0] = (cu*cv2-2.0*c2u*sv2)*cv;
+    xxu[1] = (cu*cv2-2.0*c2u*sv2)*sv;
+    xxu[2] = cu*sv2+2.0*c2u*cv2;
+    xxu[3] = -su;
+    xxv[0] = ((-0.5*su*sv2-0.5*s2u*cv2)*cv-
+              (su*cv2-s2u*sv2+FIGURE_8_RADIUS)*sv);
+    xxv[1] = ((-0.5*su*sv2-0.5*s2u*cv2)*sv+
+              (su*cv2-s2u*sv2+FIGURE_8_RADIUS)*cv);
+    xxv[2] = 0.5*su*cv2-0.5*s2u*sv2;
+    xxv[3] = 0.0;
+    for (l=0; l<4; l++)
+    {
+      xx[l] /= FIGURE_8_RADIUS+1.25;
+      xxu[l] /= FIGURE_8_RADIUS+1.25;
+      xxv[l] /= FIGURE_8_RADIUS+1.25;
+    }
+    for (l=0; l<4; l++)
+    {
+      y[l] = (mat[l][0]*xx[0]+mat[l][1]*xx[1]+
+              mat[l][2]*xx[2]+mat[l][3]*xx[3]);
+      yu[l] = (mat[l][0]*xxu[0]+mat[l][1]*xxu[1]+
+               mat[l][2]*xxu[2]+mat[l][3]*xxu[3]);
+      yv[l] = (mat[l][0]*xxv[0]+mat[l][1]*xxv[1]+
+               mat[l][2]*xxv[2]+mat[l][3]*xxv[3]);
+    }
+    if (projection_4d == DISP_4D_ORTHOGRAPHIC)
+    {
+      for (l=0; l<3; l++)
+      {
+        p[l] = y[l]+kb->offset4d[l];
+        pu[l] = yu[l];
+        pv[l] = yv[l];
+      }
+    }
+    else
+    {
+      s = y[3]+kb->offset4d[3];
+      q = 1.0/s;
+      t = q*q;
+      for (l=0; l<3; l++)
+      {
+        r = y[l]+kb->offset4d[l];
+        p[l] = r*q;
+        pu[l] = (yu[l]*s-r*yu[3])*t;
+        pv[l] = (yv[l]*s-r*yv[3])*t;
+      }
+    }
+    n[0] = pu[1]*pv[2]-pu[2]*pv[1];
+    n[1] = pu[2]*pv[0]-pu[0]*pv[2];
+    n[2] = pu[0]*pv[1]-pu[1]*pv[0];
+    t = 1.0/(kb->side*4.0*sqrt(n[0]*n[0]+n[1]*n[1]+n[2]*n[2]));
+    n[0] *= t;
+    n[1] *= t;
+    n[2] *= t;
+    pm[0] = pu[0]*kb->dumove+pv[0]*kb->dvmove;
+    pm[1] = pu[1]*kb->dumove+pv[1]*kb->dvmove;
+    pm[2] = pu[2]*kb->dumove+pv[2]*kb->dvmove;
+    t = 1.0/(4.0*sqrt(pm[0]*pm[0]+pm[1]*pm[1]+pm[2]*pm[2]));
+    pm[0] *= t;
+    pm[1] *= t;
+    pm[2] *= t;
+    b[0] = n[1]*pm[2]-n[2]*pm[1];
+    b[1] = n[2]*pm[0]-n[0]*pm[2];
+    b[2] = n[0]*pm[1]-n[1]*pm[0];
+    t = 1.0/(4.0*sqrt(b[0]*b[0]+b[1]*b[1]+b[2]*b[2]));
+    b[0] *= t;
+    b[1] *= t;
+    b[2] *= t;
+
+    /* Compute alpha, beta, delta from the three basis vectors.
+           |  -b[0]  -b[1]  -b[2] |
+       m = |   n[0]   n[1]   n[2] |
+           | -pm[0] -pm[1] -pm[2] |
+    */
+    kb->alpha = atan2(-n[2],-pm[2])*180/M_PI;
+    kb->beta = atan2( -b[2],sqrt(b[0]*b[0]+b[1]*b[1]))*180/M_PI;
+    kb->delta = atan2(b[1],-b[0])*180/M_PI;
+
+    /* Compute the rotation that rotates the Klein bottle in 4D. */
+    rotateall(kb->alpha,kb->beta,kb->delta,kb->zeta,kb->eta,kb->theta,mat);
+
+    u = kb->umove;
+    v = kb->vmove;
+    cu = cos(u);
+    su = sin(u);
+    cv = cos(v);
+    sv = sin(v);
+    cv2 = cos(0.5*v);
+    sv2 = sin(0.5*v);
+    c2u = cos(2.0*u);
+    s2u = sin(2.0*u);
+    xx[0] = (su*cv2-s2u*sv2+FIGURE_8_RADIUS)*cv;
+    xx[1] = (su*cv2-s2u*sv2+FIGURE_8_RADIUS)*sv;
+    xx[2] = su*sv2+s2u*cv2;
+    xx[3] = cu;
+    for (l=0; l<4; l++)
+      xx[l] /= FIGURE_8_RADIUS+1.25;
+    for (l=0; l<4; l++)
+    {
+      r = 0.0;
+      for (m=0; m<4; m++)
+        r += mat[l][m]*xx[m];
+      y[l] = r;
+    }
+    if (projection_4d == DISP_4D_ORTHOGRAPHIC)
+    {
+      for (l=0; l<3; l++)
+        p[l] = y[l]+kb->offset4d[l];
+    }
+    else
+    {
+      s = y[3]+kb->offset4d[3];
+      for (l=0; l<3; l++)
+        p[l] = (y[l]+kb->offset4d[l])/s;
+    }
+
+    kb->offset3d[0] = -p[0];
+    kb->offset3d[1] = -p[1]-DELTAY;
+    kb->offset3d[2] = -p[2];
+  }
+  else
+  {
+    /* Compute the rotation that rotates the Klein bottle in 4D, including
+       the trackball rotations. */
+    rotateall(kb->alpha,kb->beta,kb->delta,kb->zeta,kb->eta,kb->theta,r1);
+
+    gltrackball_get_quaternion(kb->trackballs[0],q1);
+    gltrackball_get_quaternion(kb->trackballs[1],q2);
+    quats_to_rotmat(q1,q2,r2);
+
+    mult_rotmat(r2,r1,mat);
+  }
+
+  /* Project the points from 4D to 3D. */
+  for (i=0; i<=NUMU; i++)
+  {
+    for (j=0; j<=NUMV; j++)
+    {
+      o = i*(NUMV+1)+j;
+      for (l=0; l<4; l++)
+      {
+        y[l] = (mat[l][0]*kb->x[o][0]+mat[l][1]*kb->x[o][1]+
+                mat[l][2]*kb->x[o][2]+mat[l][3]*kb->x[o][3]);
+        yu[l] = (mat[l][0]*kb->xu[o][0]+mat[l][1]*kb->xu[o][1]+
+                 mat[l][2]*kb->xu[o][2]+mat[l][3]*kb->xu[o][3]);
+        yv[l] = (mat[l][0]*kb->xv[o][0]+mat[l][1]*kb->xv[o][1]+
+                 mat[l][2]*kb->xv[o][2]+mat[l][3]*kb->xv[o][3]);
+      }
+      if (projection_4d == DISP_4D_ORTHOGRAPHIC)
+      {
+        for (l=0; l<3; l++)
+        {
+          kb->pp[o][l] = (y[l]+kb->offset4d[l])+kb->offset3d[l];
+          pu[l] = yu[l];
+          pv[l] = yv[l];
+        }
+      }
+      else
+      {
+        s = y[3]+kb->offset4d[3];
+        q = 1.0/s;
+        t = q*q;
+        for (l=0; l<3; l++)
+        {
+          r = y[l]+kb->offset4d[l];
+          kb->pp[o][l] = r*q+kb->offset3d[l];
+          pu[l] = (yu[l]*s-r*yu[3])*t;
+          pv[l] = (yv[l]*s-r*yv[3])*t;
+        }
+      }
+      kb->pn[o][0] = pu[1]*pv[2]-pu[2]*pv[1];
+      kb->pn[o][1] = pu[2]*pv[0]-pu[0]*pv[2];
+      kb->pn[o][2] = pu[0]*pv[1]-pu[1]*pv[0];
+      t = 1.0/sqrt(kb->pn[o][0]*kb->pn[o][0]+kb->pn[o][1]*kb->pn[o][1]+
+                   kb->pn[o][2]*kb->pn[o][2]);
+      kb->pn[o][0] *= t;
+      kb->pn[o][1] *= t;
+      kb->pn[o][2] *= t;
+    }
+  }
+
+  if (colors == COLORS_TWOSIDED)
+  {
+    glColor3fv(mat_diff_red);
+    if (display_mode == DISP_TRANSPARENT)
+    {
+      glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,mat_diff_trans_red);
+      glMaterialfv(GL_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_trans_green);
+    }
+    else
+    {
+      glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,mat_diff_red);
+      glMaterialfv(GL_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_green);
+    }
+  }
+  glBindTexture(GL_TEXTURE_2D,kb->tex_name);
+
+  for (i=0; i<NUMU; i++)
+  {
+    if (appearance == APPEARANCE_BANDS && ((i & (NUMB-1)) >= NUMB/2))
+      continue;
+    if (display_mode == DISP_WIREFRAME)
+      glBegin(GL_QUAD_STRIP);
+    else
+      glBegin(GL_TRIANGLE_STRIP);
+    for (j=0; j<=NUMV; j++)
+    {
+      for (k=0; k<=1; k++)
+      {
+        l = (i+k);
+        m = j;
+        o = l*(NUMV+1)+m;
+        glNormal3fv(kb->pn[o]);
+        glTexCoord2fv(kb->tex[o]);
+        if (colors != COLORS_TWOSIDED)
+        {
+          glColor3fv(kb->col[o]);
+          glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,kb->col[o]);
+        }
+        glVertex3fv(kb->pp[o]);
+        polys++;
+      }
+    }
+    glEnd();
+  }
+  polys /= 2;
+  return polys;
+}
+
+
+/* Draw a Lawson Klein bottle projected into 3D. */
+static int lawson(ModeInfo *mi, double umin, double umax, double vmin,
+                  double vmax)
+{
+  int polys = 0;
+  static const GLfloat mat_diff_red[]         = { 1.0, 0.0, 0.0, 1.0 };
+  static const GLfloat mat_diff_green[]       = { 0.0, 1.0, 0.0, 1.0 };
+  static const GLfloat mat_diff_trans_red[]   = { 1.0, 0.0, 0.0, 0.7 };
+  static const GLfloat mat_diff_trans_green[] = { 0.0, 1.0, 0.0, 0.7 };
+  float p[3], pu[3], pv[3], pm[3], n[3], b[3], mat[4][4];
+  int i, j, k, l, m, o;
+  double u, v;
+  double cu, su, cv, sv, cv2, sv2;
+  double xx[4], xxu[4], xxv[4], y[4], yu[4], yv[4];
+  double q, r, s, t;
+  float q1[4], q2[4], r1[4][4], r2[4][4];
+  kleinstruct *kb = &klein[MI_SCREEN(mi)];
+
+  if (view == VIEW_WALK || view == VIEW_WALKTURN)
+  {
+    /* Compute the rotation that rotates the Klein bottle in 4D without the
+       trackball rotations. */
+    rotateall4d(kb->zeta,kb->eta,kb->theta,mat);
+
+    u = kb->umove;
+    v = kb->vmove;
+    cu = cos(u);
+    su = sin(u);
+    cv = cos(v);
+    sv = sin(v);
+    cv2 = cos(0.5*v);
+    sv2 = sin(0.5*v);
+    xx[0] = cu*cv;
+    xx[1] = cu*sv;
+    xx[2] = su*sv2;
+    xx[3] = su*cv2;
+    xxu[0] = -su*cv;
+    xxu[1] = -su*sv;
+    xxu[2] = cu*sv2;
+    xxu[3] = cu*cv2;
+    xxv[0] = -cu*sv;
+    xxv[1] = cu*cv;
+    xxv[2] = su*cv2*0.5;
+    xxv[3] = -su*sv2*0.5;
+    for (l=0; l<4; l++)
+    {
+      y[l] = (mat[l][0]*xx[0]+mat[l][1]*xx[1]+
+              mat[l][2]*xx[2]+mat[l][3]*xx[3]);
+      yu[l] = (mat[l][0]*xxu[0]+mat[l][1]*xxu[1]+
+               mat[l][2]*xxu[2]+mat[l][3]*xxu[3]);
+      yv[l] = (mat[l][0]*xxv[0]+mat[l][1]*xxv[1]+
+               mat[l][2]*xxv[2]+mat[l][3]*xxv[3]);
+    }
+    if (projection_4d == DISP_4D_ORTHOGRAPHIC)
+    {
+      for (l=0; l<3; l++)
+      {
+        p[l] = y[l]+kb->offset4d[l];
+        pu[l] = yu[l];
+        pv[l] = yv[l];
+      }
+    }
+    else
+    {
+      s = y[3]+kb->offset4d[3];
+      q = 1.0/s;
+      t = q*q;
+      for (l=0; l<3; l++)
+      {
+        r = y[l]+kb->offset4d[l];
+        p[l] = r*q;
+        pu[l] = (yu[l]*s-r*yu[3])*t;
+        pv[l] = (yv[l]*s-r*yv[3])*t;
+      }
+    }
+    n[0] = pu[1]*pv[2]-pu[2]*pv[1];
+    n[1] = pu[2]*pv[0]-pu[0]*pv[2];
+    n[2] = pu[0]*pv[1]-pu[1]*pv[0];
+    t = 1.0/(kb->side*4.0*sqrt(n[0]*n[0]+n[1]*n[1]+n[2]*n[2]));
+    n[0] *= t;
+    n[1] *= t;
+    n[2] *= t;
+    pm[0] = pu[0]*kb->dumove+pv[0]*kb->dvmove;
+    pm[1] = pu[1]*kb->dumove+pv[1]*kb->dvmove;
+    pm[2] = pu[2]*kb->dumove+pv[2]*kb->dvmove;
+    t = 1.0/(4.0*sqrt(pm[0]*pm[0]+pm[1]*pm[1]+pm[2]*pm[2]));
+    pm[0] *= t;
+    pm[1] *= t;
+    pm[2] *= t;
+    b[0] = n[1]*pm[2]-n[2]*pm[1];
+    b[1] = n[2]*pm[0]-n[0]*pm[2];
+    b[2] = n[0]*pm[1]-n[1]*pm[0];
+    t = 1.0/(4.0*sqrt(b[0]*b[0]+b[1]*b[1]+b[2]*b[2]));
+    b[0] *= t;
+    b[1] *= t;
+    b[2] *= t;
+
+    /* Compute alpha, beta, delta from the three basis vectors.
+           |  -b[0]  -b[1]  -b[2] |
+       m = |   n[0]   n[1]   n[2] |
+           | -pm[0] -pm[1] -pm[2] |
+    */
+    kb->alpha = atan2(-n[2],-pm[2])*180/M_PI;
+    kb->beta = atan2( -b[2],sqrt(b[0]*b[0]+b[1]*b[1]))*180/M_PI;
+    kb->delta = atan2(b[1],-b[0])*180/M_PI;
+
+    /* Compute the rotation that rotates the Klein bottle in 4D. */
+    rotateall(kb->alpha,kb->beta,kb->delta,kb->zeta,kb->eta,kb->theta,mat);
+
+    u = kb->umove;
+    v = kb->vmove;
+    cu = cos(u);
+    su = sin(u);
+    cv = cos(v);
+    sv = sin(v);
+    cv2 = cos(0.5*v);
+    sv2 = sin(0.5*v);
+    xx[0] = cu*cv;
+    xx[1] = cu*sv;
+    xx[2] = su*sv2;
+    xx[3] = su*cv2;
+    for (l=0; l<4; l++)
+    {
+      r = 0.0;
+      for (m=0; m<4; m++)
+        r += mat[l][m]*xx[m];
+      y[l] = r;
+    }
+    if (projection_4d == DISP_4D_ORTHOGRAPHIC)
+    {
+      for (l=0; l<3; l++)
+        p[l] = y[l]+kb->offset4d[l];
+    }
+    else
+    {
+      s = y[3]+kb->offset4d[3];
+      for (l=0; l<3; l++)
+        p[l] = (y[l]+kb->offset4d[l])/s;
+    }
+
+    kb->offset3d[0] = -p[0];
+    kb->offset3d[1] = -p[1]-DELTAY;
+    kb->offset3d[2] = -p[2];
+  }
+  else
+  {
+    /* Compute the rotation that rotates the Klein bottle in 4D, including
+       the trackball rotations. */
+    rotateall(kb->alpha,kb->beta,kb->delta,kb->zeta,kb->eta,kb->theta,r1);
+
+    gltrackball_get_quaternion(kb->trackballs[0],q1);
+    gltrackball_get_quaternion(kb->trackballs[1],q2);
+    quats_to_rotmat(q1,q2,r2);
+
+    mult_rotmat(r2,r1,mat);
+  }
+
+  /* Project the points from 4D to 3D. */
+  for (i=0; i<=NUMV; i++)
+  {
+    for (j=0; j<=NUMU; j++)
+    {
+      o = i*(NUMU+1)+j;
+      for (l=0; l<4; l++)
+      {
+        y[l] = (mat[l][0]*kb->x[o][0]+mat[l][1]*kb->x[o][1]+
+                mat[l][2]*kb->x[o][2]+mat[l][3]*kb->x[o][3]);
+        yu[l] = (mat[l][0]*kb->xu[o][0]+mat[l][1]*kb->xu[o][1]+
+                 mat[l][2]*kb->xu[o][2]+mat[l][3]*kb->xu[o][3]);
+        yv[l] = (mat[l][0]*kb->xv[o][0]+mat[l][1]*kb->xv[o][1]+
+                 mat[l][2]*kb->xv[o][2]+mat[l][3]*kb->xv[o][3]);
+      }
+      if (projection_4d == DISP_4D_ORTHOGRAPHIC)
+      {
+        for (l=0; l<3; l++)
+        {
+          kb->pp[o][l] = (y[l]+kb->offset4d[l])+kb->offset3d[l];
+          pu[l] = yu[l];
+          pv[l] = yv[l];
+        }
+      }
+      else
+      {
+        s = y[3]+kb->offset4d[3];
+        q = 1.0/s;
+        t = q*q;
+        for (l=0; l<3; l++)
+        {
+          r = y[l]+kb->offset4d[l];
+          kb->pp[o][l] = r*q+kb->offset3d[l];
+          pu[l] = (yu[l]*s-r*yu[3])*t;
+          pv[l] = (yv[l]*s-r*yv[3])*t;
+        }
+      }
+      kb->pn[o][0] = pu[1]*pv[2]-pu[2]*pv[1];
+      kb->pn[o][1] = pu[2]*pv[0]-pu[0]*pv[2];
+      kb->pn[o][2] = pu[0]*pv[1]-pu[1]*pv[0];
+      t = 1.0/sqrt(kb->pn[o][0]*kb->pn[o][0]+kb->pn[o][1]*kb->pn[o][1]+
+                   kb->pn[o][2]*kb->pn[o][2]);
+      kb->pn[o][0] *= t;
+      kb->pn[o][1] *= t;
+      kb->pn[o][2] *= t;
+    }
+  }
+
+  if (colors == COLORS_TWOSIDED)
+  {
+    glColor3fv(mat_diff_red);
+    if (display_mode == DISP_TRANSPARENT)
+    {
+      glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,mat_diff_trans_red);
+      glMaterialfv(GL_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_trans_green);
+    }
+    else
+    {
+      glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,mat_diff_red);
+      glMaterialfv(GL_BACK,GL_AMBIENT_AND_DIFFUSE,mat_diff_green);
+    }
+  }
+  glBindTexture(GL_TEXTURE_2D,kb->tex_name);
+
+  for (i=0; i<NUMV; i++)
+  {
+    if (appearance == APPEARANCE_BANDS && ((i & (NUMB-1)) >= NUMB/2))
+      continue;
+    if (display_mode == DISP_WIREFRAME)
+      glBegin(GL_QUAD_STRIP);
+    else
+      glBegin(GL_TRIANGLE_STRIP);
+    for (j=0; j<=NUMU; j++)
+    {
+      for (k=0; k<=1; k++)
+      {
+        l = (i+k);
+        m = j;
+        o = l*(NUMU+1)+m;
+        glNormal3fv(kb->pn[o]);
+        glTexCoord2fv(kb->tex[o]);
+        if (colors != COLORS_TWOSIDED)
+        {
+          glColor3fv(kb->col[o]);
+          glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE,kb->col[o]);
+        }
+        glVertex3fv(kb->pp[o]);
+        polys++;
+      }
+    }
+    glEnd();
+  }
+  polys /= 2;
+  return polys;
+}
+
+
+/* Generate a texture image that shows the orientation reversal. */
+static void gen_texture(ModeInfo *mi)
+{
+  kleinstruct *kb = &klein[MI_SCREEN(mi)];
+
+  glGenTextures(1,&kb->tex_name);
+  glBindTexture(GL_TEXTURE_2D,kb->tex_name);
+  glPixelStorei(GL_UNPACK_ALIGNMENT,1);
+  glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
+  glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
+  glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
+  glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
+  glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
+  glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,TEX_DIMENSION,TEX_DIMENSION,0,
+               GL_LUMINANCE,GL_UNSIGNED_BYTE,texture);
+}
+
+
+static void init(ModeInfo *mi)
+{
+  static const GLfloat light_ambient[]  = { 0.0, 0.0, 0.0, 1.0 };
+  static const GLfloat light_diffuse[]  = { 1.0, 1.0, 1.0, 1.0 };
+  static const GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 };
+  static const GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 };
+  static const GLfloat mat_specular[]   = { 1.0, 1.0, 1.0, 1.0 };
+  kleinstruct *kb = &klein[MI_SCREEN(mi)];
+
+  if (walk_speed == 0.0)
+    walk_speed = 20.0;
+
+  if (view == VIEW_TURN)
+  {
+    kb->alpha = frand(360.0);
+    kb->beta = frand(360.0);
+    kb->delta = frand(360.0);
+  }
+  else
+  {
+    kb->alpha = 0.0;
+    kb->beta = 0.0;
+    kb->delta = 0.0;
+  }
+  kb->zeta = 0.0;
+  if (bottle_type == KLEIN_BOTTLE_FIGURE_8)
+    kb->eta = 0.0;
+  else
+    kb->eta = 45.0;
+  kb->theta = 0.0;
+  kb->umove = frand(2.0*M_PI);
+  kb->vmove = frand(2.0*M_PI);
+  kb->dumove = 0.0;
+  kb->dvmove = 0.0;
+  kb->side = 1;
+
+  if (bottle_type == KLEIN_BOTTLE_FIGURE_8)
+  {
+    kb->offset4d[0] = 0.0;
+    kb->offset4d[1] = 0.0;
+    kb->offset4d[2] = 0.0;
+    kb->offset4d[3] = 1.5;
+    kb->offset3d[0] = 0.0;
+    kb->offset3d[1] = 0.0;
+    if (projection_4d == DISP_4D_ORTHOGRAPHIC)
+      kb->offset3d[2] = -2.1;
+    else
+      kb->offset3d[2] = -1.9;
+    kb->offset3d[3] = 0.0;
+  }
+  else
+  {
+    kb->offset4d[0] = 0.0;
+    kb->offset4d[1] = 0.0;
+    kb->offset4d[2] = 0.0;
+    if (projection_4d == DISP_4D_PERSPECTIVE &&
+        projection_3d == DISP_3D_ORTHOGRAPHIC)
+      kb->offset4d[3] = 1.5;
+    else
+      kb->offset4d[3] = 1.1;
+    kb->offset3d[0] = 0.0;
+    kb->offset3d[1] = 0.0;
+    if (projection_4d == DISP_4D_ORTHOGRAPHIC)
+      kb->offset3d[2] = -2.0;
+    else
+      kb->offset3d[2] = -5.0;
+    kb->offset3d[3] = 0.0;
+  }
+
+  gen_texture(mi);
+  if (bottle_type == KLEIN_BOTTLE_FIGURE_8)
+    setup_figure8(mi,0.0,2.0*M_PI,0.0,2.0*M_PI);
+  else
+    setup_lawson(mi,0.0,2.0*M_PI,0.0,2.0*M_PI);
+
+  if (marks)
+    glEnable(GL_TEXTURE_2D);
+  else
+    glDisable(GL_TEXTURE_2D);
+
+  glMatrixMode(GL_PROJECTION);
+  glLoadIdentity();
+  if (projection_3d == DISP_3D_PERSPECTIVE ||
+      view == VIEW_WALK || view == VIEW_WALKTURN)
+  {
+    if (view == VIEW_WALK || view == VIEW_WALKTURN)
+      gluPerspective(60.0,1.0,0.01,10.0);
+    else
+      gluPerspective(60.0,1.0,0.1,10.0);
+  }
+  else
+  {
+    glOrtho(-1.0,1.0,-1.0,1.0,0.1,10.0);
+  }
+  glMatrixMode(GL_MODELVIEW);
+  glLoadIdentity();
+
+  if (display_mode == DISP_WIREFRAME)
+  {
+    glDisable(GL_DEPTH_TEST);
+    glShadeModel(GL_FLAT);
+    glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
+    glDisable(GL_LIGHTING);
+    glDisable(GL_LIGHT0);
+    glDisable(GL_BLEND);
+  }
+  else if (display_mode == DISP_SURFACE)
+  {
+    glEnable(GL_DEPTH_TEST);
+    glDepthFunc(GL_LESS);
+    glShadeModel(GL_SMOOTH);
+    glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
+    glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,GL_TRUE);
+    glEnable(GL_LIGHTING);
+    glEnable(GL_LIGHT0);
+    glLightfv(GL_LIGHT0,GL_AMBIENT,light_ambient);
+    glLightfv(GL_LIGHT0,GL_DIFFUSE,light_diffuse);
+    glLightfv(GL_LIGHT0,GL_SPECULAR,light_specular);
+    glLightfv(GL_LIGHT0,GL_POSITION,light_position);
+    glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,mat_specular);
+    glMaterialf(GL_FRONT_AND_BACK,GL_SHININESS,50.0);
+    glDepthMask(GL_TRUE);
+    glDisable(GL_BLEND);
+  }
+  else if (display_mode == DISP_TRANSPARENT)
+  {
+    glDisable(GL_DEPTH_TEST);
+    glShadeModel(GL_SMOOTH);
+    glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
+    glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,GL_TRUE);
+    glEnable(GL_LIGHTING);
+    glEnable(GL_LIGHT0);
+    glLightfv(GL_LIGHT0,GL_AMBIENT,light_ambient);
+    glLightfv(GL_LIGHT0,GL_DIFFUSE,light_diffuse);
+    glLightfv(GL_LIGHT0,GL_SPECULAR,light_specular);
+    glLightfv(GL_LIGHT0,GL_POSITION,light_position);
+    glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,mat_specular);
+    glMaterialf(GL_FRONT_AND_BACK,GL_SHININESS,50.0);
+    glDepthMask(GL_FALSE);
+    glEnable(GL_BLEND);
+    glBlendFunc(GL_SRC_ALPHA,GL_ONE);
+  }
+  else
+  {
+    glDisable(GL_DEPTH_TEST);
+    glShadeModel(GL_FLAT);
+    glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
+    glDisable(GL_LIGHTING);
+    glDisable(GL_LIGHT0);
+    glDisable(GL_BLEND);
+  }
+}
+
+
+/* Redisplay the Klein bottle. */
+static void display_klein(ModeInfo *mi)
+{
+  kleinstruct *kb = &klein[MI_SCREEN(mi)];
+
+  if (!kb->button_pressed)
+  {
+    if (view == VIEW_TURN)
+    {
+      kb->alpha += speed_wx * kb->speed_scale;
+      if (kb->alpha >= 360.0)
+        kb->alpha -= 360.0;
+      kb->beta += speed_wy * kb->speed_scale;
+      if (kb->beta >= 360.0)
+        kb->beta -= 360.0;
+      kb->delta += speed_wz * kb->speed_scale;
+      if (kb->delta >= 360.0)
+        kb->delta -= 360.0;
+      kb->zeta += speed_xy * kb->speed_scale;
+      if (kb->zeta >= 360.0)
+        kb->zeta -= 360.0;
+      kb->eta += speed_xz * kb->speed_scale;
+      if (kb->eta >= 360.0)
+        kb->eta -= 360.0;
+      kb->theta += speed_yz * kb->speed_scale;
+      if (kb->theta >= 360.0)
+        kb->theta -= 360.0;
+    }
+    if (view == VIEW_WALKTURN)
+    {
+      kb->zeta += speed_xy * kb->speed_scale;
+      if (kb->zeta >= 360.0)
+        kb->zeta -= 360.0;
+      kb->eta += speed_xz * kb->speed_scale;
+      if (kb->eta >= 360.0)
+        kb->eta -= 360.0;
+      kb->theta += speed_yz * kb->speed_scale;
+      if (kb->theta >= 360.0)
+        kb->theta -= 360.0;
+    }
+    if (view == VIEW_WALK || view == VIEW_WALKTURN)
+    {
+      kb->dvmove = cos(walk_direction*M_PI/180.0)*walk_speed*M_PI/4096.0;
+      kb->vmove += kb->dvmove;
+      if (kb->vmove >= 2.0*M_PI)
+      {
+        kb->vmove -= 2.0*M_PI;
+        kb->umove = 2.0*M_PI-kb->umove;
+        kb->side = -kb->side;
+      }
+      kb->dumove = (kb->side*sin(walk_direction*M_PI/180.0)*
+                    walk_speed*M_PI/4096.0);
+      kb->umove += kb->dumove;
+      if (kb->umove >= 2.0*M_PI)
+        kb->umove -= 2.0*M_PI;
+      if (kb->umove < 0.0)
+        kb->umove += 2.0*M_PI;
+    }
+  }
+
+  glMatrixMode(GL_PROJECTION);
+  glLoadIdentity();
+  if (projection_3d == DISP_3D_PERSPECTIVE ||
+      view == VIEW_WALK || view == VIEW_WALKTURN)
+  {
+    if (view == VIEW_WALK || view == VIEW_WALKTURN)
+      gluPerspective(60.0,kb->aspect,0.01,10.0);
+    else
+      gluPerspective(60.0,kb->aspect,0.1,10.0);
+  }
+  else
+  {
+    if (kb->aspect >= 1.0)
+      glOrtho(-kb->aspect,kb->aspect,-1.0,1.0,0.1,10.0);
+    else
+      glOrtho(-1.0,1.0,-1.0/kb->aspect,1.0/kb->aspect,0.1,10.0);
+  }
+  glMatrixMode(GL_MODELVIEW);
+  glLoadIdentity();
+
+  if (bottle_type == KLEIN_BOTTLE_FIGURE_8)
+    mi->polygon_count = figure8(mi,0.0,2.0*M_PI,0.0,2.0*M_PI);
+  else
+    mi->polygon_count = lawson(mi,0.0,2.0*M_PI,0.0,2.0*M_PI);
+}
+
+
+ENTRYPOINT void reshape_klein(ModeInfo *mi, int width, int height)
+{
+  kleinstruct *kb = &klein[MI_SCREEN(mi)];
+
+  kb->WindW = (GLint)width;
+  kb->WindH = (GLint)height;
+  glViewport(0,0,width,height);
+  kb->aspect = (GLfloat)width/(GLfloat)height;
+}
+
+
+ENTRYPOINT Bool klein_handle_event(ModeInfo *mi, XEvent *event)
+{
+  Display *display = MI_DISPLAY(mi);
+  kleinstruct *kb = &klein[MI_SCREEN(mi)];
+  KeySym  sym;
+
+  if (event->xany.type == ButtonPress &&
+      event->xbutton.button == Button1)
+  {
+    kb->button_pressed = True;
+    gltrackball_start(kb->trackballs[kb->current_trackball],
+                      event->xbutton.x, event->xbutton.y,
+                      MI_WIDTH(mi), MI_HEIGHT(mi));
+    return True;
+  }
+  else if (event->xany.type == ButtonRelease &&
+           event->xbutton.button == Button1)
+  {
+    kb->button_pressed = False;
+    return True;
+  }
+  else if (event->xany.type == KeyPress)
+  {
+    sym = XKeycodeToKeysym(display,event->xkey.keycode,0);
+    if (sym == XK_Shift_L || sym == XK_Shift_R)
+    {
+      kb->current_trackball = 1;
+      if (kb->button_pressed)
+        gltrackball_start(kb->trackballs[kb->current_trackball],
+                          event->xbutton.x, event->xbutton.y,
+                          MI_WIDTH(mi), MI_HEIGHT(mi));
+      return True;
+    }
+  }
+  else if (event->xany.type == KeyRelease)
+  {
+    sym = XKeycodeToKeysym(display,event->xkey.keycode,0);
+    if (sym == XK_Shift_L || sym == XK_Shift_R)
+    {
+      kb->current_trackball = 0;
+      if (kb->button_pressed)
+        gltrackball_start(kb->trackballs[kb->current_trackball],
+                          event->xbutton.x, event->xbutton.y,
+                          MI_WIDTH(mi), MI_HEIGHT(mi));
+      return True;
+    }
+  }
+  else if (event->xany.type == MotionNotify && kb->button_pressed)
+  {
+    gltrackball_track(kb->trackballs[kb->current_trackball],
+                      event->xmotion.x, event->xmotion.y,
+                      MI_WIDTH(mi), MI_HEIGHT(mi));
+    return True;
+  }
+
+  return False;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *-----------------------------------------------------------------------------
+ *    Xlock hooks.
+ *-----------------------------------------------------------------------------
+ *-----------------------------------------------------------------------------
+ */
+
+/*
+ *-----------------------------------------------------------------------------
+ *    Initialize klein.  Called each time the window changes.
+ *-----------------------------------------------------------------------------
+ */
+
+ENTRYPOINT void init_klein(ModeInfo *mi)
+{
+  kleinstruct *kb;
+
+  if (klein == NULL)
+  {
+    klein = (kleinstruct *)calloc(MI_NUM_SCREENS(mi),
+                                              sizeof(kleinstruct));
+    if (klein == NULL)
+      return;
+  }
+  kb = &klein[MI_SCREEN(mi)];
+
+  
+  kb->trackballs[0] = gltrackball_init();
+  kb->trackballs[1] = gltrackball_init();
+  kb->current_trackball = 0;
+  kb->button_pressed = False;
+
+  /* Set the Klein bottle. */
+  if (!strcasecmp(klein_bottle,"random"))
+  {
+    bottle_type = random() % NUM_KLEIN_BOTTLES;
+  }
+  else if (!strcasecmp(klein_bottle,"figure-8"))
+  {
+    bottle_type = KLEIN_BOTTLE_FIGURE_8;
+  }
+  else if (!strcasecmp(klein_bottle,"lawson"))
+  {
+    bottle_type = KLEIN_BOTTLE_LAWSON;
+  }
+  else
+  {
+    bottle_type = random() % NUM_KLEIN_BOTTLES;
+  }
+
+  /* Set the display mode. */
+  if (!strcasecmp(mode,"random"))
+  {
+    display_mode = random() % NUM_DISPLAY_MODES;
+  }
+  else if (!strcasecmp(mode,"wireframe"))
+  {
+    display_mode = DISP_WIREFRAME;
+  }
+  else if (!strcasecmp(mode,"surface"))
+  {
+    display_mode = DISP_SURFACE;
+  }
+  else if (!strcasecmp(mode,"transparent"))
+  {
+    display_mode = DISP_TRANSPARENT;
+  }
+  else
+  {
+    display_mode = random() % NUM_DISPLAY_MODES;
+  }
+
+  /* Orientation marks don't make sense in wireframe mode. */
+  if (display_mode == DISP_WIREFRAME)
+    marks = False;
+
+  /* Set the appearance. */
+  if (!strcasecmp(appear,"random"))
+  {
+    appearance = random() % NUM_APPEARANCES;
+  }
+  else if (!strcasecmp(appear,"solid"))
+  {
+    appearance = APPEARANCE_SOLID;
+  }
+  else if (!strcasecmp(appear,"bands"))
+  {
+    appearance = APPEARANCE_BANDS;
+  }
+  else
+  {
+    appearance = random() % NUM_APPEARANCES;
+  }
+
+  /* Set the color mode. */
+  if (!strcasecmp(color_mode,"random"))
+  {
+    colors = random() % NUM_COLORS;
+  }
+  else if (!strcasecmp(color_mode,"two-sided"))
+  {
+    colors = COLORS_TWOSIDED;
+  }
+  else if (!strcasecmp(color_mode,"rainbow"))
+  {
+    colors = COLORS_RAINBOW;
+  }
+  else if (!strcasecmp(color_mode,"depth"))
+  {
+    colors = COLORS_DEPTH;
+  }
+  else
+  {
+    colors = random() % NUM_COLORS;
+  }
+
+  /* Set the view mode. */
+  if (!strcasecmp(view_mode,"random"))
+  {
+    view = random() % NUM_VIEW_MODES;
+  }
+  else if (!strcasecmp(view_mode,"walk"))
+  {
+    view = VIEW_WALK;
+  }
+  else if (!strcasecmp(view_mode,"turn"))
+  {
+    view = VIEW_TURN;
+  }
+  else if (!strcasecmp(view_mode,"walk-turn"))
+  {
+    view = VIEW_WALKTURN;
+  }
+  else
+  {
+    view = random() % NUM_VIEW_MODES;
+  }
+
+  /* Set the 3d projection mode. */
+  if (!strcasecmp(proj_3d,"random"))
+  {
+    /* Orthographic projection only makes sense in turn mode. */
+    if (view == VIEW_TURN)
+      projection_3d = random() % NUM_DISP_3D_MODES;
+    else
+      projection_3d = DISP_3D_PERSPECTIVE;
+  }
+  else if (!strcasecmp(proj_3d,"perspective"))
+  {
+    projection_3d = DISP_3D_PERSPECTIVE;
+  }
+  else if (!strcasecmp(proj_3d,"orthographic"))
+  {
+    projection_3d = DISP_3D_ORTHOGRAPHIC;
+  }
+  else
+  {
+    /* Orthographic projection only makes sense in turn mode. */
+    if (view == VIEW_TURN)
+      projection_3d = random() % NUM_DISP_3D_MODES;
+    else
+      projection_3d = DISP_3D_PERSPECTIVE;
+  }
+
+  /* Set the 4d projection mode. */
+  if (!strcasecmp(proj_4d,"random"))
+  {
+    projection_4d = random() % NUM_DISP_4D_MODES;
+  }
+  else if (!strcasecmp(proj_4d,"perspective"))
+  {
+    projection_4d = DISP_4D_PERSPECTIVE;
+  }
+  else if (!strcasecmp(proj_4d,"orthographic"))
+  {
+    projection_4d = DISP_4D_ORTHOGRAPHIC;
+  }
+  else
+  {
+    projection_4d = random() % NUM_DISP_4D_MODES;
+  }
+
+  /* Modify the speeds to a useful range in walk-and-turn mode. */
+  if (view == VIEW_WALKTURN)
+  {
+    speed_wx *= 0.2;
+    speed_wy *= 0.2;
+    speed_wz *= 0.2;
+    speed_xy *= 0.2;
+    speed_xz *= 0.2;
+    speed_yz *= 0.2;
+  }
+
+  /* make multiple screens rotate at slightly different rates. */
+  kb->speed_scale = 0.9 + frand(0.3);
+
+  if ((kb->glx_context = init_GL(mi)) != NULL)
+  {
+    reshape_klein(mi,MI_WIDTH(mi),MI_HEIGHT(mi));
+    glDrawBuffer(GL_BACK);
+    init(mi);
+  }
+  else
+  {
+    MI_CLEARWINDOW(mi);
+  }
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ *    Called by the mainline code periodically to update the display.
+ *-----------------------------------------------------------------------------
+ */
+ENTRYPOINT void draw_klein(ModeInfo *mi)
+{
+  Display          *display = MI_DISPLAY(mi);
+  Window           window = MI_WINDOW(mi);
+  kleinstruct *kb;
+
+  if (klein == NULL)
+    return;
+  kb = &klein[MI_SCREEN(mi)];
+
+  MI_IS_DRAWN(mi) = True;
+  if (!kb->glx_context)
+    return;
+
+  glXMakeCurrent(display,window,*(kb->glx_context));
+
+  glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
+  glLoadIdentity();
+
+  display_klein(mi);
+
+  if (MI_IS_FPS(mi))
+    do_fps (mi);
+
+  glFlush();
+
+  glXSwapBuffers(display,window);
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *    The display is being taken away from us.  Free up malloc'ed 
+ *      memory and X resources that we've alloc'ed.  Only called
+ *      once, we must zap everything for every screen.
+ *-----------------------------------------------------------------------------
+ */
+
+ENTRYPOINT void release_klein(ModeInfo *mi)
+{
+  if (klein != NULL)
+  {
+    int screen;
+
+    for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
+    {
+      kleinstruct *kb = &klein[screen];
+
+      if (kb->glx_context)
+        kb->glx_context = (GLXContext *)NULL;
+    }
+    (void) free((void *)klein);
+    klein = (kleinstruct *)NULL;
+  }
+  FreeAllGL(mi);
+}
+
+#ifndef STANDALONE
+ENTRYPOINT void change_klein(ModeInfo *mi)
+{
+  kleinstruct *kb = &klein[MI_SCREEN(mi)];
+
+  if (!kb->glx_context)
+    return;
+
+  glXMakeCurrent(MI_DISPLAY(mi),MI_WINDOW(mi),*(kb->glx_context));
+  init(mi);
+}
+#endif /* !STANDALONE */
+
+XSCREENSAVER_MODULE ("Klein", klein)
+
+#endif /* USE_GL */
index c5c52d6c51f7c2712c86856fb129d08a69409c75..de4fd4807a4ddbc05852c89a636fe22b38ebb786 100644 (file)
@@ -1,25 +1,98 @@
 .TH XScreenSaver 1 "" "X Version 11"
 .SH NAME
-klein - A Klein Bottle (and other parametric surfaces) visualization.
+kleinbottle - Draws a 4d Klein bottle.
 .SH SYNOPSIS
-.B klein
+.B kleinbottle
 [\-display \fIhost:display.screen\fP]
+[\-install]
 [\-visual \fIvisual\fP]
 [\-window]
 [\-root]
-[\-speed \fInumber\fP]
-[\-rand]
-[\-spin]
-[\-wander]
+[\-delay \fIusecs\fP]
 [\-fps]
+[\-klein-bottle \fIbottle-name\fP]
+[-figure-8]
+[-lawson]
+[\-mode \fIdisplay-mode\fP]
+[\-wireframe]
+[\-surface]
+[\-transparent]
+[\-appearance \fIappearance\fP]
+[\-solid]
+[\-bands]
+[\-colors \fIcolor-scheme\fP]
+[\-twosided]
+[\-rainbow]
+[\-depth]
+[\-view-mode \fIview-mode\fP]
+[\-walk]
+[\-turn]
+[\-walk-turn]
+[\-orientation-marks]
+[\-projection-3d \fImode\fP]
+[\-perspective-3d]
+[\-orthographic-3d]
+[\-projection-4d \fImode\fP]
+[\-perspective-4d]
+[\-orthographic-4d]
+[\-speed-wx \fIfloat\fP]
+[\-speed-wy \fIfloat\fP]
+[\-speed-wz \fIfloat\fP]
+[\-speed-xy \fIfloat\fP]
+[\-speed-xz \fIfloat\fP]
+[\-speed-yz \fIfloat\fP]
+[\-walk-direction \fIfloat\fP]
+[\-walk-speed \fIfloat\fP]
 .SH DESCRIPTION
-This draws a three dimensional visualization of a Klein Bottle parametric 
-surface (the three dimensional equivalent of the Moebious strip).
+The \fIkleinbottle\fP program shows two different Klein bottles in 4d:
+the figure-8 Klein bottle or the Lawson Klein bottle.  You can walk on
+the Klein bottle, see it turn in 4d, or walk on it while it turns in
+4d.  The figure-8 Klein bottle is well known in its 3d form.  The 4d
+form used in this program is an extension of the 3d form to 4d that
+does not intersect itself in 4d (which can be seen in the depth colors
+mode).  The Lawson Klein bottle, on the other hand, does intersect
+itself in 4d.  Its primary use is that it has a nice appearance for
+walking and for turning in 3d.  The Klein bottle is a non-orientable
+surface.  To make this apparent, the two-sided color mode can be used.
+Alternatively, orientation markers (curling arrows) can be drawn as a
+texture map on the surface of the Klein bottle.  While walking on the
+Klein bottle, you will notice that the orientation of the curling
+arrows changes (which it must because the Klein bottle is
+non-orientable).  The program projects the 4d Klein bottle to 3d using
+either a perspective or an orthographic projection.  Which of the two
+alternatives looks more appealing depends on the viewing mode and the
+Klein bottle.  For example, the Lawson Klein bottle looks nicest when
+projected perspectively.  The figure-8 Klein bottle, on the other
+hand, looks nicer while walking when projected orthographically from
+4d.  The projected Klein bottle can then be projected to the screen
+either perspectively or orthographically.  When using the walking
+modes, perspective projection to the screen should be used.  There are
+three display modes for the Klein bottle: mesh (wireframe), solid, or
+transparent.  Furthermore, the appearance of the Klein bottle can be
+as a solid object or as a set of see-through bands.  Finally, the
+colors with with the Klein bottle is drawn can be set to two-sided,
+rainbow, or depth.  In the first case, the Klein bottle is drawn with
+red on one "side" and green on the "other side".  Of course, the Klein
+bottle only has one side, so the color jumps from red to green along a
+curve on the surface of the Klein bottle.  This mode enables you to
+see that the Klein bottle is non-orientable.  The second mode draws
+the Klein bottle with fully saturated rainbow colors.  This gives a
+very nice effect when combined with the see-through bands mode or with
+the orientation markers drawn.  The third mode draws the Klein bottle
+with colors that are chosen according to the 4d "depth" of the points.
+This mode enables you to see that the figure-8 Klein bottle does not
+intersect itself in 4d, while the Lawson Klein bottle does intersect
+itself.  The rotation speed for each of the six planes around which
+the Klein bottle rotates can be chosen.  For the walk-and-turn more,
+only the rotation speeds around the true 4d planes are used (the xy,
+xz, and yz planes).  Furthermore, in the walking modes the walking
+direction in the 2d base square of the Klein bottle and the walking
+speed can be chosen.  This program is somewhat inspired by Thomas
+Banchoff's book "Beyond the Third Dimension: Geometry, Computer
+Graphics, and Higher Dimensions", Scientific American Library, 1990.
 .SH OPTIONS
-.TP 8
-.B \-visual \fIvisual\fP
-Specify which visual to use.  Legal values are the name of a visual class,
-or the id number (decimal or hex) of a specific visual.
+.I kleinbottle
+accepts the following options:
 .TP 8
 .B \-window
 Draw on a newly-created window.  This is the default.
@@ -27,22 +100,180 @@ Draw on a newly-created window.  This is the default.
 .B \-root
 Draw on the root window.
 .TP 8
-.B \-delay \fInumber\fP
-Per-frame delay, in microseconds.  Default: 20000 (0.02 seconds.).
+.B \-install
+Install a private colormap for the window.
 .TP 8
-.B \-speed \fInumber\fP
-Number of frames before changing shape.  Default: 150.
+.B \-visual \fIvisual\fP
+Specify which visual to use.  Legal values are the name of a visual
+class, or the id number (decimal or hex) of a specific visual.
 .TP 8
-.B \-rand
-Randomize the parametric surfaces displayed. Use random OpenGL primitives
-too.
-.B \-wander | \-no-wander
-Whether to wander around the screen.
-.B \-spin | \no-spin
-Whether to rotate around the centre of the figure.
+.B \-delay \fImicroseconds\fP
+How much of a delay should be introduced between steps of the
+animation.  Default 10000, or 1/100th second.
 .TP 8
 .B \-fps
 Display the current frame rate, CPU load, and polygon count.
+.PP
+The following three options are mutually exclusive.  They determine
+which Klein bottle is displayed.
+.TP 8
+.B \-klein-bottle random
+Display a random Klein bottle (default).
+.TP 8
+.B \-klein-bottle figure-8 \fP(Shortcut: \fB\-figure-8\fP)
+Display the figure-8 Klein bottle.
+.TP 8
+.B \-klein-bottle lawson \fP(Shortcut: \fB\-lawson\fP)
+Display the Lawson Klein bottle.
+.PP
+The following four options are mutually exclusive.  They determine
+how the Klein bottle is displayed.
+.TP 8
+.B \-mode random
+Display the Klein bottle in a random display mode (default).
+.TP 8
+.B \-mode wireframe \fP(Shortcut: \fB\-wireframe\fP)
+Display the Klein bottle as a wireframe mesh.
+.TP 8
+.B \-mode surface \fP(Shortcut: \fB\-surface\fP)
+Display the Klein bottle as a solid surface.
+.TP 8
+.B \-mode transparent \fP(Shortcut: \fB\-transparent\fP)
+Display the Klein bottle as a transparent surface.
+.PP
+The following three options are mutually exclusive.  They determine the
+appearance of the Klein bottle.
+.TP 8
+.B \-appearance random
+Display the Klein bottle with a random appearance (default).
+.TP 8
+.B \-appearance solid \fP(Shortcut: \fB\-solid\fP)
+Display the Klein bottle as a solid object.
+.TP 8
+.B \-appearance bands \fP(Shortcut: \fB\-bands\fP)
+Display the Klein bottle as see-through bands.
+.PP
+The following four options are mutually exclusive.  They determine
+how to color the Klein bottle.
+.TP 8
+.B \-colors random
+Display the Klein bottle with a random color scheme (default).
+.TP 8
+.B \-colors twosided \fP(Shortcut: \fB\-twosided\fP)
+Display the Klein bottle with two colors: red on one "side" and green
+on the "other side".
+.TP 8
+.B \-colors rainbow \fP(Shortcut: \fB\-rainbow\fP)
+Display the Klein bottle with fully saturated rainbow colors.  If the
+Klein bottle is displayed as see-through bands, each band will be
+displayed with a different color.
+.TP 8
+.B \-colors depth \fP(Shortcut: \fB\-depth\fP)
+Display the Klein bottle with colors chosen depending on the 4d
+"depth" of the points.
+.PP
+The following four options are mutually exclusive.  They determine
+how to view the Klein bottle.
+.TP 8
+.B \-view-mode random
+View the Klein bottle in a random view mode (default).
+.TP 8
+.B \-view-mode walk \fP(Shortcut: \fB\-walk\fP)
+View the Klein bottle as if walking on its surface.
+.TP 8
+.B \-view-mode turn \fP(Shortcut: \fB\-turn\fP)
+View the Klein bottle while it turns in 4d.
+.TP 8
+.B \-view-mode walk-turn \fP(Shortcut: \fB\-walk-turn\fP)
+View the Klein bottle as if walking on its surface.  Additionally, the
+Klein bottle turns around the true 4d planes (the xy, xz, and yz
+planes).
+.PP
+The following options determine whether orientation marks are shown on
+the Klein bottle.
+.TP 8
+.B \-orientation-marks
+Display orientation marks on the Klein bottle.
+.TP 8
+.B \-no-orientation-marks
+Don't display orientation marks on the Klein bottle (default).
+.PP
+The following three options are mutually exclusive.  They determine
+how the Klein bottle is projected from 3d to 2d (i.e., to the screen).
+.TP 8
+.B \-projection-3d random
+Project the Klein bottle from 3d to 2d using a random projection mode
+(default).
+.TP 8
+.B \-projection-3d perspective \fP(Shortcut: \fB\-perspective-3d\fP)
+Project the Klein bottle from 3d to 2d using a perspective projection.
+.TP 8
+.B \-projection-3d orthographic \fP(Shortcut: \fB\-orthographic-3d\fP)
+Project the Klein bottle from 3d to 2d using an orthographic
+projection.
+.PP
+The following three options are mutually exclusive.  They determine
+how the Klein bottle is projected from 4d to 3d.
+.TP 8
+.B \-projection-4d random
+Project the Klein bottle from 4d to 3d using a random projection mode
+(default).
+.TP 8
+.B \-projection-4d perspective \fP(Shortcut: \fB\-perspective-4d\fP)
+Project the Klein bottle from 4d to 3d using a perspective projection.
+.TP 8
+.B \-projection-4d orthographic \fP(Shortcut: \fB\-orthographic-4d\fP)
+Project the Klein bottle from 4d to 3d using an orthographic
+projection.
+.PP
+The following six options determine the rotation speed of the Klein
+bottle around the six possible hyperplanes.  The rotation speed is
+measured in degrees per frame.  The speeds should be set to relatively
+small values, e.g., less than 4 in magnitude.  In walk mode, all
+speeds are ignored.  In walk-and-turn mode, the 3d rotation speeds are
+ignored (i.e., the wx, wy, and wz speeds).  In walk-and-turn mode,
+smaller speeds must be used than in the turn mode to achieve a nice
+visualization.  Therefore, in walk-and-turn mode the speeds you have
+selected are divided by 5 internally.
+.TP 8
+.B \-speed-wx \fIfloat\fP
+Rotation speed around the wx plane (default: 1.1).
+.TP 8
+.B \-speed-wy \fIfloat\fP
+Rotation speed around the wy plane (default: 1.3).
+.TP 8
+.B \-speed-wz \fIfloat\fP
+Rotation speed around the wz plane (default: 1.5).
+.TP 8
+.B \-speed-xy \fIfloat\fP
+Rotation speed around the xy plane (default: 1.7).
+.TP 8
+.B \-speed-xz \fIfloat\fP
+Rotation speed around the xz plane (default: 1.9).
+.TP 8
+.B \-speed-yz \fIfloat\fP
+Rotation speed around the yz plane (default: 2.1).
+.PP
+The following two options determine the walking speed and direction.
+.TP 8
+.B \-walk-direction \fIfloat\fP
+The walking direction is measured as an angle in degrees in the 2d
+square that forms the coordinate system of the surface of the Klein
+bottle (default: 7.0).
+.TP 8
+.B \-walk-speed \fIfloat\fP
+The walking speed is measured in percent of some sensible maximum
+speed (default: 20.0).
+.SH INTERACTION
+If you run this program in standalone mode in its turn mode, you can
+rotate the Klein bottle by dragging the mouse while pressing the left
+mouse button.  This rotates the Klein bottle in 3D, i.e., around the
+wx, wy, and wz planes.  If you press the shift key while dragging the
+mouse with the left button pressed the Klein bottle is rotated in 4D,
+i.e., around the xy, xz, and yz planes.  To examine the Klein bottle
+at your leisure, it is best to set all speeds to 0.  Otherwise, the
+Klein bottle will rotate while the left mouse button is not pressed.
+This kind of interaction is not available in the two walk modes.
 .SH ENVIRONMENT
 .PP
 .TP 8
@@ -55,5 +286,14 @@ stored in the RESOURCE_MANAGER property.
 .SH SEE ALSO
 .BR X (1),
 .BR xscreensaver (1)
+.SH COPYRIGHT
+Copyright \(co 2005-2009 by Carsten Steger.  Permission to use, copy,
+modify, distribute, and sell this software and its documentation for
+any purpose is hereby granted without fee, provided that the above
+copyright notice appear in all copies and that both that copyright
+notice and this permission notice appear in supporting documentation.
+No representations are made about the suitability of this software for
+any purpose.  It is provided "as is" without express or implied
+warranty.
 .SH AUTHOR
-Andrey Mirtchovski.
+Carsten Steger <carsten@mirsanmir.org>, 03-aug-2009.
index 039e635140fedd88161c1a60b8a82596c915af51..00ba44e17946ed8a63cbf62acf48312381a02cfc 100644 (file)
@@ -18,6 +18,7 @@
  * 21-Oct-2003:                           Renamed to mirrorblob
  * 10-Feb-2004:  jon.dowdall@bigpond.com  Added motion blur
  * 28-Jan-2006:  jon.dowdall@bigpond.com  Big clean up and bug fixes
+ * 13-Apr-2009:  jon.dowdall@gmail.com    Fixed Mac version
  *
  * The mirrorblob screensaver draws a pulsing blob on the screen.  Options
  * include adding a background (via screen_to_texture), texturing the blob,
 #include <math.h>
 
 #ifdef STANDALONE
-#define DEFAULTS \
-    "*delay:             " DEF_DELAY "\n" \
-    "*showFPS:           " DEF_FPS   "\n" \
-    "*useSHM:              True      \n"
+#define DEFAULTS "*delay:             " DEF_DELAY "\n"                      \
+                 "*showFPS:           " DEF_FPS   "\n"                      \
+                 "*useSHM:              True       \n"                      \
+                 "*desktopGrabber:  xscreensaver-getimage -no-desktop %s\n" \
+                 "*grabDesktopImages:   True  \n"                           \
+                 "*chooseRandomImages:  True  \n"
 
 # define refresh_mirrorblob 0
 /*
 # define mirrorblob_handle_event 0
 */
-# include "xlockmore.h"    /* from the xmirrorblob distribution */
+# include "xlockmore.h"
 #else /* !STANDALONE */
 # include "xlock.h"        /* from the xlockmore distribution */
 #endif /* !STANDALONE */
@@ -123,10 +126,10 @@ static XrmOptionDescRec opts[] = {
     {"+texture",          ".blob.texture",          XrmoptionNoArg, "false" },
     {"-colour",           ".blob.colour",           XrmoptionNoArg, "true" },
     {"+colour",           ".blob.colour",           XrmoptionNoArg, "false" },
-    {"-offset-texture",   ".blob.offsetTexture",   XrmoptionNoArg, "true" },
-    {"+offset-texture",   ".blob.offsetTexture",   XrmoptionNoArg, "false" },
-    {"-paint-background", ".blob.paintBackground", XrmoptionNoArg, "true" },
-    {"+paint-background", ".blob.paintBackground", XrmoptionNoArg, "false" },
+    {"-offset-texture",   ".blob.offsetTexture",    XrmoptionNoArg, "true" },
+    {"+offset-texture",   ".blob.offsetTexture",    XrmoptionNoArg, "false" },
+    {"-paint-background", ".blob.paintBackground",  XrmoptionNoArg, "true" },
+    {"+paint-background", ".blob.paintBackground",  XrmoptionNoArg, "false" },
     {"-resolution",       ".blob.resolution",       XrmoptionSepArg, NULL },
     {"-bumps",            ".blob.bumps",            XrmoptionSepArg, NULL },
     {"-motion-blur",      ".blob.motionBlur",       XrmoptionSepArg, 0 },
@@ -182,56 +185,55 @@ ModStruct   mirrorblob_description =
  "OpenGL mirrorblob", 0, NULL};
 #endif
 
-
 /*****************************************************************************
  * Types used in blob code
  *****************************************************************************/
 
 typedef struct
 {
-    GLdouble x, y;
+  GLdouble x, y;
 } Vector2D;
 
 typedef struct
 {
-    GLdouble x, y, z;
+  GLdouble x, y, z;
 } Vector3D;
 
 typedef struct
 {
-    GLdouble w;
-    GLdouble x;
-    GLdouble y;
-    GLdouble z;
+  GLdouble w;
+  GLdouble x;
+  GLdouble y;
+  GLdouble z;
 } Quaternion;
 
 typedef struct
 {
-    GLubyte red, green, blue, alpha;
+  GLubyte red, green, blue, alpha;
 } Colour;
 
 typedef struct
 {
-    Vector3D initial_position;
-    Vector3D position;
-    Vector3D normal;
+  Vector3D initial_position;
+  Vector3D position;
+  Vector3D normal;
 } Node_Data;
 
 typedef struct
 {
-    int node1, node2, node3;
-    Vector3D normal;
-    double length1, length2, length3;
+  int node1, node2, node3;
+  Vector3D normal;
+  double length1, length2, length3;
 } Face_Data;
 
 /* Structure to hold data about bumps used to distortion sphere */
 typedef struct
 {
-    double cx, cy, cpower, csize;
-    double ax, ay, power, size;
-    double mx, my, mpower, msize;
-    double vx, vy, vpower, vsize;
-    Vector3D pos;
+  double cx, cy, cpower, csize;
+  double ax, ay, power, size;
+  double mx, my, mpower, msize;
+  double vx, vy, vpower, vsize;
+  Vector3D pos;
 } Bump_Data;
 
 /* Vertices of a tetrahedron */
@@ -263,6 +265,7 @@ const Vector3D zero_vector = { 0.0, 0.0, 0.0 };
 
 typedef enum
 {
+  INITIALISING,
   HOLDING,
   LOADING,
   TRANSITIONING
@@ -349,11 +352,11 @@ double_time (void)
 static void
 reset_projection(int width, int height)
 {
-    glMatrixMode (GL_PROJECTION);
-    glLoadIdentity ();
-    gluPerspective (60.0, 1.0, 1.0, 1024.0 );
-    glMatrixMode (GL_MODELVIEW);
-    glLoadIdentity ();
+  glMatrixMode (GL_PROJECTION);
+  glLoadIdentity ();
+  gluPerspective (60.0, 1.0, 1.0, 1024.0 );
+  glMatrixMode (GL_MODELVIEW);
+  glLoadIdentity ();
 }
 
 /******************************************************************************
@@ -365,7 +368,7 @@ reset_projection(int width, int height)
 static inline double
 dot (const Vector3D u, const Vector3D v)
 {
-    return (u.x * v.x) + (u.y * v.y) + (u.z * v.z);
+  return (u.x * v.x) + (u.y * v.y) + (u.z * v.z);
 }
 
 /******************************************************************************
@@ -377,13 +380,13 @@ dot (const Vector3D u, const Vector3D v)
 static inline Vector3D
 cross (const Vector3D u, const Vector3D v)
 {
-    Vector3D result;
+  Vector3D result;
 
-    result.x = (u.y * v.z - u.z * v.y);
-    result.y = (u.z * v.x - u.x * v.z);
-    result.z = (u.x * v.y - u.y * v.x);
+  result.x = (u.y * v.z - u.z * v.y);
+  result.y = (u.z * v.x - u.x * v.z);
+  result.z = (u.x * v.y - u.y * v.x);
 
-    return result;
+  return result;
 }
 
 /******************************************************************************
@@ -393,9 +396,9 @@ cross (const Vector3D u, const Vector3D v)
 static inline void
 add (Vector3D *u, const Vector3D v)
 {
-    u->x = u->x + v.x;
-    u->y = u->y + v.y;
-    u->z = u->z + v.z;
+  u->x = u->x + v.x;
+  u->y = u->y + v.y;
+  u->z = u->z + v.z;
 }
 
 /******************************************************************************
@@ -405,13 +408,13 @@ add (Vector3D *u, const Vector3D v)
 static inline Vector3D
 subtract (const Vector3D u, const Vector3D v)
 {
-    Vector3D result;
+  Vector3D result;
 
-    result.x = u.x - v.x;
-    result.y = u.y - v.y;
-    result.z = u.z - v.z;
+  result.x = u.x - v.x;
+  result.y = u.y - v.y;
+  result.z = u.z - v.z;
 
-    return result;
+  return result;
 }
 
 /******************************************************************************
@@ -421,12 +424,12 @@ subtract (const Vector3D u, const Vector3D v)
 static inline Vector3D
 scale (const Vector3D v, const double s)
 {
-    Vector3D result;
+  Vector3D result;
     
-    result.x = v.x * s;
-    result.y = v.y * s;
-    result.z = v.z * s;
-    return result;
+  result.x = v.x * s;
+  result.y = v.y * s;
+  result.z = v.z * s;
+  return result;
 }
 
 /******************************************************************************
@@ -436,21 +439,21 @@ scale (const Vector3D v, const double s)
 static inline Vector3D
 normalise (const Vector3D v)
 {
-    Vector3D result;
-    double magnitude;
+  Vector3D result;
+  double magnitude;
 
-    magnitude = sqrt (dot(v, v));
+  magnitude = sqrt (dot(v, v));
 
-    if (magnitude > 1e-300)
+  if (magnitude > 1e-300)
     {
-        result = scale (v, 1.0 / magnitude);
+      result = scale (v, 1.0 / magnitude);
     }
-    else
+  else
     {
-        printf("zero\n");
-        result = zero_vector;
+      printf("zero\n");
+      result = zero_vector;
     }
-    return result;
+  return result;
 }
 
 /******************************************************************************
@@ -460,31 +463,31 @@ normalise (const Vector3D v)
 static void
 quaternion_transform (Quaternion q, GLdouble * transform)
 {
-    GLdouble x, y, z, w;
-    x = q.x;
-    y = q.y;
-    z = q.z;
-    w = q.w;
-
-    transform[0] = (w * w) + (x * x) - (y * y) - (z * z);
-    transform[1] = (2.0 * x * y) + (2.0 * w * z);
-    transform[2] = (2.0 * x * z) - (2.0 * w * y);
-    transform[3] = 0.0;
-
-    transform[4] = (2.0 * x * y) - (2.0 * w * z);
-    transform[5] = (w * w) - (x * x) + (y * y) - (z * z);
-    transform[6] = (2.0 * y * z) + (2.0 * w * x);
-    transform[7] = 0.0;
-
-    transform[8] = (2.0 * x * z) + (2.0 * w * y);
-    transform[9] = (2.0 * y * z) - (2.0 * w * x);
-    transform[10] = (w * w) - (x * x) - (y * y) + (z * z);
-    transform[11] = 0.0;
-
-    transform[12] = 0.0;
-    transform[13] = 0.0;
-    transform[14] = 0.0;
-    transform[15] = (w * w) + (x * x) + (y * y) + (z * z);
+  GLdouble x, y, z, w;
+  x = q.x;
+  y = q.y;
+  z = q.z;
+  w = q.w;
+
+  transform[0] = (w * w) + (x * x) - (y * y) - (z * z);
+  transform[1] = (2.0 * x * y) + (2.0 * w * z);
+  transform[2] = (2.0 * x * z) - (2.0 * w * y);
+  transform[3] = 0.0;
+
+  transform[4] = (2.0 * x * y) - (2.0 * w * z);
+  transform[5] = (w * w) - (x * x) + (y * y) - (z * z);
+  transform[6] = (2.0 * y * z) + (2.0 * w * x);
+  transform[7] = 0.0;
+
+  transform[8] = (2.0 * x * z) + (2.0 * w * y);
+  transform[9] = (2.0 * y * z) - (2.0 * w * x);
+  transform[10] = (w * w) - (x * x) - (y * y) + (z * z);
+  transform[11] = 0.0;
+
+  transform[12] = 0.0;
+  transform[13] = 0.0;
+  transform[14] = 0.0;
+  transform[15] = (w * w) + (x * x) + (y * y) + (z * z);
 }
 
 /******************************************************************************
@@ -494,13 +497,13 @@ quaternion_transform (Quaternion q, GLdouble * transform)
 static inline Vector3D
 vector_transform (Vector3D u, GLdouble * t)
 {
-    Vector3D result;
+  Vector3D result;
 
-    result.x = (u.x * t[0] + u.y * t[4] + u.z * t[8] + 1.0 * t[12]);
-    result.y = (u.x * t[1] + u.y * t[5] + u.z * t[9] + 1.0 * t[13]);
-    result.z = (u.x * t[2] + u.y * t[6] + u.z * t[10] + 1.0 * t[14]);
+  result.x = (u.x * t[0] + u.y * t[4] + u.z * t[8] + 1.0 * t[12]);
+  result.y = (u.x * t[1] + u.y * t[5] + u.z * t[9] + 1.0 * t[13]);
+  result.z = (u.x * t[2] + u.y * t[6] + u.z * t[10] + 1.0 * t[14]);
 
-    return result;
+  return result;
 }
 
 /******************************************************************************
@@ -511,32 +514,31 @@ vector_transform (Vector3D u, GLdouble * t)
 static Vector3D
 partial (Vector3D node1, Vector3D node2, double distance)
 {
-    Vector3D result;
-    Vector3D rotation_axis;
-    GLdouble transformation[16];
-    double angle;
-    Quaternion rotation;
+  Vector3D result;
+  Vector3D rotation_axis;
+  GLdouble transformation[16];
+  double angle;
+  Quaternion rotation;
 
-    rotation_axis = normalise (cross (node1, node2));
-    angle = acos (dot (node1, node2)) * distance;
+  rotation_axis = normalise (cross (node1, node2));
+  angle = acos (dot (node1, node2)) * distance;
 
-    rotation.x = rotation_axis.x * sin (angle / 2.0);
-    rotation.y = rotation_axis.y * sin (angle / 2.0);
-    rotation.z = rotation_axis.z * sin (angle / 2.0);
-    rotation.w = cos (angle / 2.0);
+  rotation.x = rotation_axis.x * sin (angle / 2.0);
+  rotation.y = rotation_axis.y * sin (angle / 2.0);
+  rotation.z = rotation_axis.z * sin (angle / 2.0);
+  rotation.w = cos (angle / 2.0);
 
-    quaternion_transform (rotation, transformation);
+  quaternion_transform (rotation, transformation);
 
-    result = vector_transform (node1, transformation);
+  result = vector_transform (node1, transformation);
 
-    return result;
+  return result;
 }
 
 /****************************************************************************
  *
- * Load a texture.
+ * Callback indicating a texture has loaded
  */
-
 static void
 image_loaded_cb (const char *filename, XRectangle *geometry,
                  int image_width, int image_height, 
@@ -573,18 +575,26 @@ image_loaded_cb (const char *filename, XRectangle *geometry,
   mp->first_image_p = True;
 }
 
-
+/* Load a new file into a texture
+ */
 static void
 grab_texture(ModeInfo *mi, int texture_index)
 {
   mirrorblobstruct *mp = &Mirrorblob[MI_SCREEN(mi)];
-
-  mp->waiting_for_image_p = True;
-  mp->mipmap_p = True;
-  load_texture_async (mi->xgwa.screen, mi->window,
-                      *mp->glx_context, 0, 0, mp->mipmap_p, 
-                      mp->textures[texture_index],
-                      image_loaded_cb, mp);
+       
+  {
+    int w = (MI_WIDTH(mi)  / 2) - 1;
+    int h = (MI_HEIGHT(mi) / 2) - 1;
+    if (w <= 10) w = 10;
+    if (h <= 10) h = 10;
+       
+    mp->waiting_for_image_p = True;
+    mp->mipmap_p = True;
+    load_texture_async (mi->xgwa.screen, mi->window,
+                        *mp->glx_context, w, h, mp->mipmap_p, 
+                        mp->textures[texture_index],
+                        image_loaded_cb, mp);
+  }
 }
 
 /******************************************************************************
@@ -595,30 +605,30 @@ grab_texture(ModeInfo *mi, int texture_index)
 static void
 set_parameters(void)
 {
-    /* In wire frame mode do not draw a texture */
-    if (wireframe)
+  /* In wire frame mode do not draw a texture */
+  if (wireframe)
     {
-        do_texture = False;
-        blend = 1.0;
+      do_texture = False;
+      blend = 1.0;
     }
     
-    /* Need to load textures if either the blob or the backgound has an image */
-    if (do_texture || do_paint_background)
+  /* Need to load textures if either the blob or the backgound has an image */
+  if (do_texture || do_paint_background)
     {
-        load_textures = True;
+      load_textures = True;
     }
-    else
+  else
     {
-        load_textures = False;
+      load_textures = False;
     }
     
-    /* If theres no texture don't calculate co-ordinates. */
-    if (!do_texture)
+  /* If theres no texture don't calculate co-ordinates. */
+  if (!do_texture)
     {
-        offset_texture = False;
+      offset_texture = False;
     }
     
-    culling = True;
+  culling = True;
 }
 
 /******************************************************************************
@@ -628,112 +638,101 @@ set_parameters(void)
 static void
 initialize_gl(ModeInfo *mi, GLsizei width, GLsizei height)
 {
-    mirrorblobstruct *gp = &Mirrorblob[MI_SCREEN(mi)];
+  mirrorblobstruct *gp = &Mirrorblob[MI_SCREEN(mi)];
     
-    /* Lighting values */
-    GLfloat ambientLight[] = { 0.2f, 0.2f, 0.2f, 1.0f };
+  /* Lighting values */
+  GLfloat ambientLight[] = { 0.2f, 0.2f, 0.2f, 1.0f };
 
-    GLfloat lightPos0[] = {500.0f, 100.0f, 200.0f, 1.0f };
-    GLfloat whiteLight0[] = { 0.0f, 0.0f, 0.0f, 1.0f };
-    GLfloat sourceLight0[] = { 0.6f, 0.6f, 0.6f, 1.0f };
-    GLfloat specularLight0[] = { 0.8f, 0.8f, 0.9f, 1.0f };
+  GLfloat lightPos0[] = {500.0f, 100.0f, 200.0f, 1.0f };
+  GLfloat whiteLight0[] = { 0.0f, 0.0f, 0.0f, 1.0f };
+  GLfloat sourceLight0[] = { 0.6f, 0.6f, 0.6f, 1.0f };
+  GLfloat specularLight0[] = { 0.8f, 0.8f, 0.9f, 1.0f };
 
-    GLfloat lightPos1[] = {0.0f, -500.0f, 500.0f, 1.0f };
-    GLfloat whiteLight1[] = { 0.0f, 0.0f, 0.0f, 1.0f };
-    GLfloat sourceLight1[] = { 0.6f, 0.6f, 0.6f, 1.0f };
-    GLfloat specularLight1[] = { 0.7f, 0.7f, 0.7f, 1.0f };
+  GLfloat lightPos1[] = {-50.0f, -100.0f, 2500.0f, 1.0f };
+  GLfloat whiteLight1[] = { 0.0f, 0.0f, 0.0f, 1.0f };
+  GLfloat sourceLight1[] = { 0.6f, 0.6f, 0.6f, 1.0f };
+  GLfloat specularLight1[] = { 0.7f, 0.7f, 0.7f, 1.0f };
 
-    GLfloat specref[] = { 1.0f, 1.0f, 1.0f, 1.0f };
+  GLfloat specref[] = { 1.0f, 1.0f, 1.0f, 1.0f };
 
-    GLfloat fogColor[4] = { 0.4, 0.4, 0.5, 0.1 };
+  GLfloat fogColor[4] = { 0.4, 0.4, 0.5, 0.1 };
 
-    /* Set the internal parameters based on the configuration settings */
-    set_parameters();
+  /* Set the internal parameters based on the configuration settings */
+  set_parameters();
 
-    /* Set the viewport to the width and heigh of the window */
-    glViewport (0, 0, width, height ); 
+  /* Set the viewport to the width and heigh of the window */
+  glViewport (0, 0, width, height ); 
 
-    if (do_antialias)
+  if (do_antialias)
     {
-        blend = 1.0;
-        glEnable(GL_LINE_SMOOTH);
-        glEnable(GL_POLYGON_SMOOTH);
+      blend = 1.0;
+      glEnable(GL_LINE_SMOOTH);
+      glEnable(GL_POLYGON_SMOOTH);
     }
 
-    /* The blend function is used for trasitioning between two images even when
-     * blend is not selected.
-     */
-    glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+  /* The blend function is used for trasitioning between two images even when
+   * blend is not selected.
+   */
+  glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  
-    if (do_fog)
+  if (do_fog)
     {
-        glEnable(GL_FOG);
-        glFogfv(GL_FOG_COLOR, fogColor);
-        glFogf(GL_FOG_DENSITY, 0.50);
-        glFogf(GL_FOG_START, 15.0);
-        glFogf(GL_FOG_END, 30.0);
+      glEnable(GL_FOG);
+      glFogfv(GL_FOG_COLOR, fogColor);
+      glFogf(GL_FOG_DENSITY, 0.50);
+      glFogf(GL_FOG_START, 15.0);
+      glFogf(GL_FOG_END, 30.0);
     }
 
-    /* Set the shading model to smooth (Gouraud shading). */
-    glShadeModel (GL_SMOOTH);
+  /* Set the shading model to smooth (Gouraud shading). */
+  glShadeModel (GL_SMOOTH);
 
-    /* Set the clear color. */
-    glClearColor( 0, 0, 0, 0 );
+  /* Set the clear color. */
+  glClearColor( 0, 0, 0, 0 );
 
-    glLightModelfv (GL_LIGHT_MODEL_AMBIENT, ambientLight);
-    glLightfv (GL_LIGHT0, GL_AMBIENT, whiteLight0);
-    glLightfv (GL_LIGHT0, GL_DIFFUSE, sourceLight0);
-    glLightfv (GL_LIGHT0, GL_SPECULAR, specularLight0);
-    glLightfv (GL_LIGHT0, GL_POSITION, lightPos0);
-    glEnable (GL_LIGHT0);
-    glLightfv (GL_LIGHT1, GL_AMBIENT, whiteLight1);
-    glLightfv (GL_LIGHT1, GL_DIFFUSE, sourceLight1);
-    glLightfv (GL_LIGHT1, GL_SPECULAR, specularLight1);
-    glLightfv (GL_LIGHT1, GL_POSITION, lightPos1);
-    glEnable (GL_LIGHT1);
-    glEnable (GL_LIGHTING);
+  glLightModelfv (GL_LIGHT_MODEL_AMBIENT, ambientLight);
+  glLightfv (GL_LIGHT0, GL_AMBIENT, whiteLight0);
+  glLightfv (GL_LIGHT0, GL_DIFFUSE, sourceLight0);
+  glLightfv (GL_LIGHT0, GL_SPECULAR, specularLight0);
+  glLightfv (GL_LIGHT0, GL_POSITION, lightPos0);
+  glEnable (GL_LIGHT0);
+  glLightfv (GL_LIGHT1, GL_AMBIENT, whiteLight1);
+  glLightfv (GL_LIGHT1, GL_DIFFUSE, sourceLight1);
+  glLightfv (GL_LIGHT1, GL_SPECULAR, specularLight1);
+  glLightfv (GL_LIGHT1, GL_POSITION, lightPos1);
+  glEnable (GL_LIGHT1);
+  glEnable (GL_LIGHTING);
 
-    /* Enable color tracking */
-    glEnable (GL_COLOR_MATERIAL);
+  /* Enable color tracking */
+  glEnable (GL_COLOR_MATERIAL);
 
-    /* Set Material properties to follow glColor values */
-    glColorMaterial (GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
+  /* Set Material properties to follow glColor values */
+  glColorMaterial (GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
 
-    /* Set all materials to have specular reflectivity */
-    glMaterialfv (GL_FRONT, GL_SPECULAR, specref);
-    glMateriali (GL_FRONT, GL_SHININESS, 32);
+  /* Set all materials to have specular reflectivity */
+  glMaterialfv (GL_FRONT, GL_SPECULAR, specref);
+  glMateriali (GL_FRONT, GL_SHININESS, 32);
 
-    /* Let GL implementation scale normal vectors. */
-    glEnable (GL_NORMALIZE);
+  /* Let GL implementation scale normal vectors. */
+  glEnable (GL_NORMALIZE);
 
-    /* Enable Arrays */
-    if (load_textures)
+  /* Enable Arrays */
+  if (load_textures)
     {
-        glLightModeli (GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
-        glEnable (GL_TEXTURE_2D);
+      glLightModeli (GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
+      glEnable (GL_TEXTURE_2D);
 
-        gp->current_texture = 0;
-        glGenTextures (NUM_TEXTURES, gp->textures);
-        grab_texture (mi, gp->current_texture);
+      gp->current_texture = 0;
+      glGenTextures(NUM_TEXTURES, gp->textures);
+      grab_texture(mi, gp->current_texture);
 
-        if (do_texture)
-        {
-            glEnableClientState (GL_TEXTURE_COORD_ARRAY);
-        }
-        glMatrixMode (GL_TEXTURE);
-        glRotated (180.0, 1.0, 0.0, 0.0);
-        glMatrixMode (GL_MODELVIEW);
-    }
-
-    if (do_colour)
-    {
-        glEnableClientState (GL_COLOR_ARRAY);
+      glMatrixMode (GL_TEXTURE);
+      glRotated (180.0, 1.0, 0.0, 0.0);
+      glMatrixMode (GL_MODELVIEW);
     }
-    glEnableClientState (GL_NORMAL_ARRAY);
-    glEnableClientState (GL_VERTEX_ARRAY);
 
-    /* Clear the buffer since this is not done during a draw with motion blur */
-    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+  /* Clear the buffer since this is not done during a draw with motion blur */
+  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 }
 
 /******************************************************************************
@@ -743,53 +742,53 @@ initialize_gl(ModeInfo *mi, GLsizei width, GLsizei height)
 static void
 set_blob_gl_state(GLdouble alpha)
 {
-    if (do_antialias)
+  if (do_antialias)
     {
-        glEnable(GL_LINE_SMOOTH);
-        glEnable(GL_POLYGON_SMOOTH);
+      glEnable(GL_LINE_SMOOTH);
+      glEnable(GL_POLYGON_SMOOTH);
     }
 
-    if (wireframe)
+  if (wireframe)
     {
-        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+      glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
     }
-    else
+  else
     {
-        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+      glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
     }
 
-    /* The blend function is used for trasitioning between two images even when
-     * blend is not selected.
-     */
-    glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+  /* The blend function is used for trasitioning between two images even when
+   * blend is not selected.
+   */
+  glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  
-    /* Culling. */
-    if (culling)
+  /* Culling. */
+  if (culling)
     {
-        glCullFace (GL_BACK);
-        glEnable (GL_CULL_FACE);
-        glFrontFace (GL_CCW);
+      glCullFace (GL_BACK);
+      glEnable (GL_CULL_FACE);
+      glFrontFace (GL_CCW);
     }
-    else
+  else
     {
-        glDisable (GL_CULL_FACE);
+      glDisable (GL_CULL_FACE);
     }
     
-    if (blend < 1.0)
+  if (blend < 1.0)
     {
-        glEnable (GL_BLEND);
-        glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-        /* Set the default blob colour to off-white. */
-        glColor4d (0.9, 0.9, 1.0, alpha);
+      glEnable (GL_BLEND);
+      glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+      /* Set the default blob colour to off-white. */
+      glColor4d (0.9, 0.9, 1.0, alpha);
     }
-    else
+  else
     {
-        glDisable(GL_BLEND);
-        glColor4d (0.9, 0.9, 1.0, 1.0);
+      glDisable(GL_BLEND);
+      glColor4d (0.9, 0.9, 1.0, 1.0);
     }
     
-    glEnable(GL_DEPTH_TEST);
-    glEnable(GL_LIGHTING);
+  glEnable(GL_DEPTH_TEST);
+  glEnable(GL_LIGHTING);
 }
 
 /******************************************************************************
@@ -805,326 +804,318 @@ initialise_blob(mirrorblobstruct *gp,
                 int height,
                 int bump_array_size)
 {
-     /* Loop variables */    
-    int i, u, v, node, side, face, base, base2 = 0;
-    int nodes_on_edge = resolution;
-    Vector3D node1, node2, result;
+  /* Loop variables */    
+  int i, u, v, node, side, face, base, base2 = 0;
+  int nodes_on_edge = resolution;
+  Vector3D node1, node2, result;
 
-    if (nodes_on_edge < 2)
-        return -1;
+  if (nodes_on_edge < 2)
+    return -1;
 
-    gp->num_nodes = 2 * nodes_on_edge * nodes_on_edge - 4 * nodes_on_edge + 4;
-    gp->num_faces = 4 * (nodes_on_edge - 1) * (nodes_on_edge - 1);
+  gp->num_nodes = 2 * nodes_on_edge * nodes_on_edge - 4 * nodes_on_edge + 4;
+  gp->num_faces = 4 * (nodes_on_edge - 1) * (nodes_on_edge - 1);
  
-    gp->nodes = (Node_Data *) malloc (gp->num_nodes * sizeof (Node_Data));
-    if (!gp->nodes)
+  gp->nodes = (Node_Data *) malloc (gp->num_nodes * sizeof (Node_Data));
+  if (!gp->nodes)
     {
-        fprintf (stderr, "Couldn't allocate gp->nodes buffer\n");
-        return -1;
+      fprintf (stderr, "Couldn't allocate gp->nodes buffer\n");
+      return -1;
     }
 
-    gp->faces = (Face_Data *) malloc (gp->num_faces * sizeof (Face_Data));
-    if (!gp->faces)
+  gp->faces = (Face_Data *) malloc (gp->num_faces * sizeof (Face_Data));
+  if (!gp->faces)
     {
-        fprintf (stderr, "Couldn't allocate faces data buffer\n");
-        return -1;
+      fprintf (stderr, "Couldn't allocate faces data buffer\n");
+      return -1;
     }
 
-    gp->bump_data = (Bump_Data *) malloc (bumps * sizeof (Bump_Data));
-    if (!gp->bump_data)
+  gp->bump_data = (Bump_Data *) malloc (bumps * sizeof (Bump_Data));
+  if (!gp->bump_data)
     {
-        fprintf(stderr, "Couldn't allocate bump data buffer\n");
-        return -1;
+      fprintf(stderr, "Couldn't allocate bump data buffer\n");
+      return -1;
     }
 
-    gp->bump_shape = (double *)malloc(bump_array_size * sizeof(double));
-    if (!gp->bump_shape)
+  gp->bump_shape = (double *)malloc(bump_array_size * sizeof(double));
+  if (!gp->bump_shape)
     {
-        fprintf(stderr, "Couldn't allocate bump buffer\n");
-        return -1;
+      fprintf(stderr, "Couldn't allocate bump buffer\n");
+      return -1;
     }
 
-    gp->wall_shape = (double *)malloc(bump_array_size * sizeof(double));
-    if (!gp->wall_shape)
+  gp->wall_shape = (double *)malloc(bump_array_size * sizeof(double));
+  if (!gp->wall_shape)
     {
-        fprintf(stderr, "Couldn't allocate wall bump buffer\n");
-        return -1;
+      fprintf(stderr, "Couldn't allocate wall bump buffer\n");
+      return -1;
     }
 
-    gp->dots = (Vector3D *)malloc(gp->num_nodes * sizeof(Vector3D));
-    if (!gp->dots)
+       
+  gp->dots = (Vector3D *)malloc(gp->num_nodes * sizeof(Vector3D));
+  if (!gp->dots)
     {
-        fprintf(stderr, "Couldn't allocate nodes buffer\n");
-        return -1;
+      fprintf(stderr, "Couldn't allocate nodes buffer\n");
+      return -1;
     }
-    glVertexPointer (3, GL_DOUBLE, 0, (GLvoid *) gp->dots);
 
-    gp->normals = (Vector3D *)malloc(gp->num_nodes * sizeof(Vector3D));
-    if (!gp->normals)
+  gp->normals = (Vector3D *)malloc(gp->num_nodes * sizeof(Vector3D));
+  if (!gp->normals)
     {
-        fprintf(stderr, "Couldn't allocate normals buffer\n");
-        return -1;
+      fprintf(stderr, "Couldn't allocate normals buffer\n");
+      return -1;
     }
-    glNormalPointer (GL_DOUBLE, 0, (GLvoid *) gp->normals);
 
-    if (do_colour)
+  gp->colours = (Colour *)malloc(gp->num_nodes * sizeof(Colour));
+  if (!gp->colours)
     {
-        gp->colours = (Colour *)malloc(gp->num_nodes * sizeof(Colour));
-        if (!gp->colours)
-        {
-            fprintf(stderr, "Couldn't allocate colours buffer\n");
-            return -1;
-        }
-        glColorPointer (4, GL_UNSIGNED_BYTE, 0, (GLvoid *) gp->colours);
+      fprintf(stderr, "Couldn't allocate colours buffer\n");
+      return -1;
     }
 
-    if (do_texture)
+  gp->tex_coords = (Vector2D *)malloc(gp->num_nodes * sizeof(Vector2D));
+  if (!gp->tex_coords)
     {
-        gp->tex_coords = (Vector2D *)malloc(gp->num_nodes * sizeof(Vector2D));
-        if (!gp->tex_coords)
-        {
-            fprintf(stderr, "Couldn't allocate gp->tex_coords buffer\n");
-            return -1;
-        }
-        glTexCoordPointer (2, GL_DOUBLE, 0, (GLvoid *) gp->tex_coords);
+      fprintf(stderr, "Couldn't allocate gp->tex_coords buffer\n");
+      return -1;
     }
 
-    /* Initialise bump data */
-    for (i = 0; i < bumps; i++)
+       
+  /* Initialise bump data */
+  for (i = 0; i < bumps; i++)
     {
-        gp->bump_data[i].ax = 2.0 * (((double)random() / (double)RAND_MAX) - 0.5);
-        gp->bump_data[i].ay = 2.0 * (((double)random() / (double)RAND_MAX) - 0.5);
-        gp->bump_data[i].power = (5.0 / pow(bumps, 0.75)) * (((double)random() / (double)RAND_MAX) - 0.5);
-        gp->bump_data[i].size = 0.1 + 0.5 * (((double)random() / (double)RAND_MAX));
-
-        gp->bump_data[i].pos.x = 1.5 * sin(PI * gp->bump_data[i].ay)
-            * cos(PI *  gp->bump_data[i].ax);
-        gp->bump_data[i].pos.y = 1.5 * cos(PI * gp->bump_data[i].ay);
-        gp->bump_data[i].pos.z = 1.5 * sin(PI * gp->bump_data[i].ay)
-            * sin(PI *  gp->bump_data[i].ax);
-
-        gp->bump_data[i].cx = 2.0 * (((double)random() / (double)RAND_MAX) - 0.5);
-        gp->bump_data[i].cy = 2.0 * (((double)random() / (double)RAND_MAX) - 0.5);
-        gp->bump_data[i].cpower = (5.0 / pow(bumps, 0.75)) * (((double)random() / (double)RAND_MAX) - 0.5);
-        gp->bump_data[i].csize = 0.35; /*0.1 + 0.25 * (((double)random() / (double)RAND_MAX));*/
-
-        gp->bump_data[i].vx = 0.0;
-        gp->bump_data[i].vy = 0.0;
-        gp->bump_data[i].vpower = 0.0;
-        gp->bump_data[i].vsize = 0.0;
-
-        gp->bump_data[i].mx = 0.003 * ((double)random() / (double)RAND_MAX);
-        gp->bump_data[i].my = 0.003 * ((double)random() / (double)RAND_MAX);
-        gp->bump_data[i].mpower = 0.003 * ((double)random() / (double)RAND_MAX);
-        gp->bump_data[i].msize = 0.003 * ((double)random() / (double)RAND_MAX);
+      gp->bump_data[i].ax = 2.0 * (((double)random() / (double)RAND_MAX) - 0.5);
+      gp->bump_data[i].ay = 2.0 * (((double)random() / (double)RAND_MAX) - 0.5);
+      gp->bump_data[i].power = (5.0 / pow(bumps, 0.75)) * (((double)random() / (double)RAND_MAX) - 0.5);
+      gp->bump_data[i].size = 0.1 + 0.5 * (((double)random() / (double)RAND_MAX));
+
+      gp->bump_data[i].pos.x = 1.5 * sin(PI * gp->bump_data[i].ay)
+        * cos(PI *  gp->bump_data[i].ax);
+      gp->bump_data[i].pos.y = 1.5 * cos(PI * gp->bump_data[i].ay);
+      gp->bump_data[i].pos.z = 1.5 * sin(PI * gp->bump_data[i].ay)
+        * sin(PI *  gp->bump_data[i].ax);
+
+      gp->bump_data[i].cx = 2.0 * (((double)random() / (double)RAND_MAX) - 0.5);
+      gp->bump_data[i].cy = 2.0 * (((double)random() / (double)RAND_MAX) - 0.5);
+      gp->bump_data[i].cpower = (5.0 / pow(bumps, 0.75)) * (((double)random() / (double)RAND_MAX) - 0.5);
+      gp->bump_data[i].csize = 0.35; /*0.1 + 0.25 * (((double)random() / (double)RAND_MAX));*/
+
+      gp->bump_data[i].vx = 0.0;
+      gp->bump_data[i].vy = 0.0;
+      gp->bump_data[i].vpower = 0.0;
+      gp->bump_data[i].vsize = 0.0;
+
+      gp->bump_data[i].mx = 0.003 * ((double)random() / (double)RAND_MAX);
+      gp->bump_data[i].my = 0.003 * ((double)random() / (double)RAND_MAX);
+      gp->bump_data[i].mpower = 0.003 * ((double)random() / (double)RAND_MAX);
+      gp->bump_data[i].msize = 0.003 * ((double)random() / (double)RAND_MAX);
     }
 
-    /* Initialise lookup table of bump strength */
-    for (i = 0; i < bump_array_size; i++)
+  /* Initialise lookup table of bump strength */
+  for (i = 0; i < bump_array_size; i++)
     {
-        double xd, xd2;
-        xd = i / (double)bump_array_size;
+      double xd, xd2;
+      xd = i / (double)bump_array_size;
 
-        xd2 = 48.0 * xd * xd;
-        gp->bump_shape[i] = 0.1 / (xd2 + 0.1);
+      xd2 = 48.0 * xd * xd;
+      gp->bump_shape[i] = 0.1 / (xd2 + 0.1);
 
-        xd2 = 40.0 * xd * xd * xd * xd;
-        gp->wall_shape[i] = 0.4 / (xd2 + 0.1);
+      xd2 = 40.0 * xd * xd * xd * xd;
+      gp->wall_shape[i] = 0.4 / (xd2 + 0.1);
     }
 
-    node = 0;
-    face = 0;
-    for (side = 0; side < 4; side++)
+  node = 0;
+  face = 0;
+  for (side = 0; side < 4; side++)
     {
-        base = node;
-        if (side == 2) 
+      base = node;
+      if (side == 2) 
         {
-            base2 = node;
+          base2 = node;
         }
-        /*
-         * The start and end of the for loops below are modified based on the 
-         * side of the tetrahedron that is being calculated to avoid duplication
-         * of the gp->nodes that are on the edges of the tetrahedron. 
-         */
-        for (u = (side > 1); u < (nodes_on_edge - (side > 0)); u++)
+      /*
+       * The start and end of the for loops below are modified based on the 
+       * side of the tetrahedron that is being calculated to avoid duplication
+       * of the gp->nodes that are on the edges of the tetrahedron. 
+       */
+      for (u = (side > 1); u < (nodes_on_edge - (side > 0)); u++)
         {
-            node1 = partial (normalise (tetrahedron[side][0]),
-                              normalise (tetrahedron[side][1]),
-                              u / (double) (nodes_on_edge - 1));
-            node2 = partial (normalise (tetrahedron[side][0]),
-                              normalise (tetrahedron[side][2]),
-                              u / (double) (nodes_on_edge - 1));
-
-            for (v = (side > 1); v <= (u - (side > 2)); v++)
+          node1 = partial (normalise (tetrahedron[side][0]),
+                           normalise (tetrahedron[side][1]),
+                           u / (double) (nodes_on_edge - 1));
+          node2 = partial (normalise (tetrahedron[side][0]),
+                           normalise (tetrahedron[side][2]),
+                           u / (double) (nodes_on_edge - 1));
+
+          for (v = (side > 1); v <= (u - (side > 2)); v++)
             {
-                if (u > 0)
-                    result = partial (node1, node2, v / (double) u);
-                else
-                    result = node1;
-
-                gp->nodes[node].position = normalise (result);
-                gp->nodes[node].initial_position = gp->nodes[node].position;
-                gp->nodes[node].normal = zero_vector;
-                node++;
+              if (u > 0)
+                result = partial (node1, node2, v / (double) u);
+              else
+                result = node1;
+
+              gp->nodes[node].position = normalise (result);
+              gp->nodes[node].initial_position = gp->nodes[node].position;
+              gp->nodes[node].normal = zero_vector;
+              node++;
             }
         }
  
-        /*
-         * Determine which nodes make up each face.  The complexity is caused 
-         * by having to determine the correct nodes for the edges of the
-         * tetrahedron since the common nodes on the edges are only calculated
-         * once (see above).
-         */
-        for (u = 0; u < (nodes_on_edge - 1); u++)
+      /*
+       * Determine which nodes make up each face.  The complexity is caused 
+       * by having to determine the correct nodes for the edges of the
+       * tetrahedron since the common nodes on the edges are only calculated
+       * once (see above).
+       */
+      for (u = 0; u < (nodes_on_edge - 1); u++)
         {
-            for (v = 0; v <= u; v++)
+          for (v = 0; v <= u; v++)
             {
-                {
-                    if (side < 2)
-                    {
-                        gp->faces[face].node1 = base + ((u * (u + 1)) / 2) + v;
+              {
+                if (side < 2)
+                  {
+                    gp->faces[face].node1 = base + ((u * (u + 1)) / 2) + v;
+                    gp->faces[face].node2 =
+                      base + ((u + 1) * (u + 2)) / 2 + v + 1;
+                    gp->faces[face].node3 =
+                      base + ((u + 1) * (u + 2)) / 2 + v;
+
+                    if ((side == 1) && (u == (nodes_on_edge - 2)))
+                      {
+                        gp->faces[face].node3 =
+                          ((u + 1) * (u + 2)) / 2 +
+                          nodes_on_edge - v - 1;
+                        gp->faces[face].node2 =
+                          ((u + 1) * (u + 2)) / 2 +
+                          nodes_on_edge - v - 2;
+                      }
+                  }
+                else if (side < 3)
+                  {
+                    gp->faces[face].node1 =
+                      base + (((u - 1) * u) / 2) + v - 1;
+                    gp->faces[face].node2 = base + ((u) * (u + 1)) / 2 + v;
+                    gp->faces[face].node3 =
+                      base + ((u) * (u + 1)) / 2 + v - 1;
+
+                    if (u == (nodes_on_edge - 2))
+                      {
+                        int n = nodes_on_edge - v - 1;
                         gp->faces[face].node2 =
-                            base + ((u + 1) * (u + 2)) / 2 + v + 1;
+                          ((nodes_on_edge *
+                            (nodes_on_edge + 1)) / 2) +
+                          ((n - 1) * (n + 0)) / 2;
                         gp->faces[face].node3 =
-                            base + ((u + 1) * (u + 2)) / 2 + v;
-
-                        if ((side == 1) && (u == (nodes_on_edge - 2)))
-                        {
-                            gp->faces[face].node3 =
-                                ((u + 1) * (u + 2)) / 2 +
-                                nodes_on_edge - v - 1;
-                            gp->faces[face].node2 =
-                                ((u + 1) * (u + 2)) / 2 +
-                                nodes_on_edge - v - 2;
-                        }
-                    }
-                    else if (side < 3)
-                    {
+                          ((nodes_on_edge *
+                            (nodes_on_edge + 1)) / 2) +
+                          ((n + 0) * (n + 1)) / 2;
+                      }
+                    if (v == 0)
+                      {
+                        gp->faces[face].node1 = (((u + 1) * (u + 2)) / 2) - 1;
+                        gp->faces[face].node3 = (((u + 2) * (u + 3)) / 2) - 1;
+                      }
+                  }
+                else
+                  {
+                    gp->faces[face].node1 =
+                      base + (((u - 2) * (u - 1)) / 2) + v - 1;
+                    gp->faces[face].node2 = base + ((u - 1) * u) / 2 + v;
+                    gp->faces[face].node3 = base + ((u - 1) * u) / 2 + v - 1;
+
+                    if (v == 0)
+                      {
                         gp->faces[face].node1 =
-                            base + (((u - 1) * u) / 2) + v - 1;
-                        gp->faces[face].node2 = base + ((u) * (u + 1)) / 2 + v;
+                          base2 + ((u * (u + 1)) / 2) - 1;
                         gp->faces[face].node3 =
-                            base + ((u) * (u + 1)) / 2 + v - 1;
-
-                        if (u == (nodes_on_edge - 2))
-                        {
-                            int n = nodes_on_edge - v - 1;
-                            gp->faces[face].node2 =
-                                ((nodes_on_edge *
-                                  (nodes_on_edge + 1)) / 2) +
-                                ((n - 1) * (n + 0)) / 2;
-                            gp->faces[face].node3 =
-                                ((nodes_on_edge *
-                                  (nodes_on_edge + 1)) / 2) +
-                                ((n + 0) * (n + 1)) / 2;
-                        }
-                        if (v == 0)
-                        {
-                            gp->faces[face].node1 = (((u + 1) * (u + 2)) / 2) - 1;
-                            gp->faces[face].node3 = (((u + 2) * (u + 3)) / 2) - 1;
-                        }
-                    }
-                    else
-                    {
-                        gp->faces[face].node1 =
-                            base + (((u - 2) * (u - 1)) / 2) + v - 1;
-                        gp->faces[face].node2 = base + ((u - 1) * u) / 2 + v;
-                        gp->faces[face].node3 = base + ((u - 1) * u) / 2 + v - 1;
-
-                        if (v == 0)
-                        {
-                            gp->faces[face].node1 =
-                                base2 + ((u * (u + 1)) / 2) - 1;
-                            gp->faces[face].node3 =
-                                base2 + ((u + 1) * (u + 2)) / 2 - 1;
-                        }
-                        if (u == (nodes_on_edge - 2))
-                        {
-                            gp->faces[face].node3 =
-                                ((nodes_on_edge *
-                                  (nodes_on_edge + 1)) / 2) +
-                                ((v + 1) * (v + 2)) / 2 - 1;
-                            gp->faces[face].node2 =
-                                ((nodes_on_edge *
-                                  (nodes_on_edge + 1)) / 2) +
-                                ((v + 2) * (v + 3)) / 2 - 1;
-                        }
-                        if (v == u)
-                        {
-                            gp->faces[face].node1 = (u * (u + 1)) / 2;
-                            gp->faces[face].node2 = ((u + 1) * (u + 2)) / 2;
-                        }
-                    }
-                    face++;
-                }
-
-                if (v < u)
+                          base2 + ((u + 1) * (u + 2)) / 2 - 1;
+                      }
+                    if (u == (nodes_on_edge - 2))
+                      {
+                        gp->faces[face].node3 =
+                          ((nodes_on_edge *
+                            (nodes_on_edge + 1)) / 2) +
+                          ((v + 1) * (v + 2)) / 2 - 1;
+                        gp->faces[face].node2 =
+                          ((nodes_on_edge *
+                            (nodes_on_edge + 1)) / 2) +
+                          ((v + 2) * (v + 3)) / 2 - 1;
+                      }
+                    if (v == u)
+                      {
+                        gp->faces[face].node1 = (u * (u + 1)) / 2;
+                        gp->faces[face].node2 = ((u + 1) * (u + 2)) / 2;
+                      }
+                  }
+                face++;
+              }
+
+              if (v < u)
                 {
-                    if (side < 2)
+                  if (side < 2)
                     {
-                        gp->faces[face].node1 = base + ((u * (u + 1)) / 2) + v;
-                        gp->faces[face].node2 =
-                            base + ((u * (u + 1)) / 2) + v + 1;
-                        gp->faces[face].node3 =
-                            base + (((u + 1) * (u + 2)) / 2) + v + 1;
+                      gp->faces[face].node1 = base + ((u * (u + 1)) / 2) + v;
+                      gp->faces[face].node2 =
+                        base + ((u * (u + 1)) / 2) + v + 1;
+                      gp->faces[face].node3 =
+                        base + (((u + 1) * (u + 2)) / 2) + v + 1;
 
-                        if ((side == 1) && (u == (nodes_on_edge - 2)))
+                      if ((side == 1) && (u == (nodes_on_edge - 2)))
                         {
-                            gp->faces[face].node3 =
-                                ((u + 1) * (u + 2)) / 2 +
-                                nodes_on_edge - v - 2;
+                          gp->faces[face].node3 =
+                            ((u + 1) * (u + 2)) / 2 +
+                            nodes_on_edge - v - 2;
                         }
                     }
-                    else if (side < 3)
+                  else if (side < 3)
                     {
-                        gp->faces[face].node1 =
-                            base + ((u * (u - 1)) / 2) + v - 1;
-                        gp->faces[face].node2 = base + ((u * (u - 1)) / 2) + v;
-                        gp->faces[face].node3 = base + ((u * (u + 1)) / 2) + v;
+                      gp->faces[face].node1 =
+                        base + ((u * (u - 1)) / 2) + v - 1;
+                      gp->faces[face].node2 = base + ((u * (u - 1)) / 2) + v;
+                      gp->faces[face].node3 = base + ((u * (u + 1)) / 2) + v;
 
-                        if (u == (nodes_on_edge - 2))
+                      if (u == (nodes_on_edge - 2))
                         {
-                            int n = nodes_on_edge - v - 1;
-                            gp->faces[face].node3 =
-                                ((nodes_on_edge *
-                                  (nodes_on_edge + 1)) / 2) +
-                                ((n + 0) * (n - 1)) / 2;
+                          int n = nodes_on_edge - v - 1;
+                          gp->faces[face].node3 =
+                            ((nodes_on_edge *
+                              (nodes_on_edge + 1)) / 2) +
+                            ((n + 0) * (n - 1)) / 2;
                         }
-                        if (v == 0)
+                      if (v == 0)
                         {
-                            gp->faces[face].node1 = (((u + 1) * (u + 2)) / 2) - 1;
+                          gp->faces[face].node1 = (((u + 1) * (u + 2)) / 2) - 1;
                         }
                     }
-                    else
+                  else
                     {
-                        gp->faces[face].node1 =
-                            base + (((u - 2) * (u - 1)) / 2) + v - 1;
-                        gp->faces[face].node2 =
-                            base + (((u - 2) * (u - 1)) / 2) + v;
-                        gp->faces[face].node3 = base + (((u - 1) * u) / 2) + v;
+                      gp->faces[face].node1 =
+                        base + (((u - 2) * (u - 1)) / 2) + v - 1;
+                      gp->faces[face].node2 =
+                        base + (((u - 2) * (u - 1)) / 2) + v;
+                      gp->faces[face].node3 = base + (((u - 1) * u) / 2) + v;
 
-                        if (v == 0)
+                      if (v == 0)
                         {
-                            gp->faces[face].node1 = base2 + (u * (u + 1)) / 2 - 1;
+                          gp->faces[face].node1 = base2 + (u * (u + 1)) / 2 - 1;
                         }
-                        if (u == (nodes_on_edge - 2))
+                      if (u == (nodes_on_edge - 2))
                         {
-                            gp->faces[face].node3 =
-                                ((nodes_on_edge * (nodes_on_edge + 1)) / 2) +
-                                ((v + 2) * (v + 3)) / 2 - 1;
+                          gp->faces[face].node3 =
+                            ((nodes_on_edge * (nodes_on_edge + 1)) / 2) +
+                            ((v + 2) * (v + 3)) / 2 - 1;
                         }
-                        if (v == (u - 1))
+                      if (v == (u - 1))
                         {
-                            gp->faces[face].node2 = (u * (u + 1)) / 2;
+                          gp->faces[face].node2 = (u * (u + 1)) / 2;
                         }
                     }
-                    face++;
+                  face++;
                 }
             }
         }
     }
 
-    return 0;
+  return 0;
 }
 
 /******************************************************************************
@@ -1134,7 +1125,7 @@ initialise_blob(mirrorblobstruct *gp,
 static inline double
 length (Vector3D u)
 {
-    return sqrt (u.x * u.x + u.y * u.y + u.z * u.z);
+  return sqrt (u.x * u.x + u.y * u.y + u.z * u.z);
 }
 
 /******************************************************************************
@@ -1149,198 +1140,267 @@ calc_blob(mirrorblobstruct *gp,
           float limit,
           double fade)
 {
-    /* Loop variables */
-    int i, index, face;
-    /* position of a node */
-    Vector3D node;
-    Vector3D offset;
-    Vector3D bump_vector;
-    int dist;
-
-    /* Update position and strength of bumps used to distort the blob */
-    for (i = 0; i < bumps; i++)
+  /* Loop variables */
+  int i, index, face;
+  /* position of a node */
+  Vector3D node;
+  Vector3D offset;
+  Vector3D bump_vector;
+  int dist;
+
+  /* Update position and strength of bumps used to distort the blob */
+  for (i = 0; i < bumps; i++)
     {
-        gp->bump_data[i].vx += gp->bump_data[i].mx*(gp->bump_data[i].cx - gp->bump_data[i].ax);
-        gp->bump_data[i].vy += gp->bump_data[i].my*(gp->bump_data[i].cy - gp->bump_data[i].ay);
-        gp->bump_data[i].vpower += gp->bump_data[i].mpower
-            * (gp->bump_data[i].cpower - gp->bump_data[i].power);
-        gp->bump_data[i].vsize += gp->bump_data[i].msize
-            * (gp->bump_data[i].csize - gp->bump_data[i].size);
-
-        gp->bump_data[i].ax += 0.1 * gp->bump_data[i].vx;
-        gp->bump_data[i].ay += 0.1 * gp->bump_data[i].vy;
-        gp->bump_data[i].power += 0.1 * gp->bump_data[i].vpower;
-        gp->bump_data[i].size += 0.1 * gp->bump_data[i].vsize;
-
-        gp->bump_data[i].pos.x = 1.0 * sin(PI * gp->bump_data[i].ay)
-            * cos(PI * gp->bump_data[i].ax);
-        gp->bump_data[i].pos.y = 1.0 * cos(PI * gp->bump_data[i].ay);
-        gp->bump_data[i].pos.z = 1.0 * sin(PI * gp->bump_data[i].ay)
-            * sin(PI * gp->bump_data[i].ax);
+      gp->bump_data[i].vx += gp->bump_data[i].mx*(gp->bump_data[i].cx - gp->bump_data[i].ax);
+      gp->bump_data[i].vy += gp->bump_data[i].my*(gp->bump_data[i].cy - gp->bump_data[i].ay);
+      gp->bump_data[i].vpower += gp->bump_data[i].mpower
+        * (gp->bump_data[i].cpower - gp->bump_data[i].power);
+      gp->bump_data[i].vsize += gp->bump_data[i].msize
+        * (gp->bump_data[i].csize - gp->bump_data[i].size);
+
+      gp->bump_data[i].ax += 0.1 * gp->bump_data[i].vx;
+      gp->bump_data[i].ay += 0.1 * gp->bump_data[i].vy;
+      gp->bump_data[i].power += 0.1 * gp->bump_data[i].vpower;
+      gp->bump_data[i].size += 0.1 * gp->bump_data[i].vsize;
+
+      gp->bump_data[i].pos.x = 1.0 * sin(PI * gp->bump_data[i].ay)
+        * cos(PI * gp->bump_data[i].ax);
+      gp->bump_data[i].pos.y = 1.0 * cos(PI * gp->bump_data[i].ay);
+      gp->bump_data[i].pos.z = 1.0 * sin(PI * gp->bump_data[i].ay)
+        * sin(PI * gp->bump_data[i].ax);
     }
 
-    /* Update calculate new position for each vertex based on an offset from
-     * the initial position
-     */
-    gp->blob_force = zero_vector;
-    for (index = 0; index < gp->num_nodes; ++index)
+  /* Update calculate new position for each vertex based on an offset from
+   * the initial position
+   */
+  gp->blob_force = zero_vector;
+  for (index = 0; index < gp->num_nodes; ++index)
     {
-        node = gp->nodes[index].initial_position;
-        gp->nodes[index].normal = zero_vector;
+      node = gp->nodes[index].initial_position;
+      gp->nodes[index].normal = node;
 
-        offset = zero_vector;
-        for ( i = 0; i < bumps; i++)
+      offset = zero_vector;
+      for ( i = 0; i < bumps; i++)
         {
-            bump_vector = subtract(gp->bump_data[i].pos, node);
+          bump_vector = subtract(gp->bump_data[i].pos, node);
 
-            dist = bump_array_size * dot(bump_vector, bump_vector) * gp->bump_data[i].size;
+          dist = bump_array_size * dot(bump_vector, bump_vector) * gp->bump_data[i].size;
 
-            if (dist < bump_array_size)
+          if (dist < bump_array_size)
             {
-                add(&offset, scale(node, gp->bump_data[i].power * gp->bump_shape[dist]));
-                add(&gp->blob_force, scale(node, gp->bump_data[i].power * gp->bump_shape[dist]));
+              add(&offset, scale(node, gp->bump_data[i].power * gp->bump_shape[dist]));
+              add(&gp->blob_force, scale(node, gp->bump_data[i].power * gp->bump_shape[dist]));
             }
         }
 
-        add(&node, offset);
-        node = scale(node, zoom);
-        add(&node, gp->blob_center);
+      add(&node, offset);
+      node = scale(node, zoom);
+      add(&node, gp->blob_center);
 
-        if (do_walls)
+      if (do_walls)
         {
-            if (node.z < -limit) node.z = -limit;
-            if (node.z > limit) node.z = limit;
+          if (node.z < -limit) node.z = -limit;
+          if (node.z > limit) node.z = limit;
 
-            dist = bump_array_size * (node.z + limit) * (node.z + limit) * 0.5;
-            if (dist < bump_array_size)
+          dist = bump_array_size * (node.z + limit) * (node.z + limit) * 0.5;
+          if (dist < bump_array_size)
             {
-                node.x += (node.x - gp->blob_center.x) * gp->wall_shape[dist];
-                node.y += (node.y - gp->blob_center.y) * gp->wall_shape[dist];
-                gp->blob_force.z += (node.z + limit);
+              node.x += (node.x - gp->blob_center.x) * gp->wall_shape[dist];
+              node.y += (node.y - gp->blob_center.y) * gp->wall_shape[dist];
+              gp->blob_force.z += (node.z + limit);
             }
-            else
+          else
             {
-                dist = bump_array_size * (node.z - limit) * (node.z - limit) * 0.5;
-                if (dist < bump_array_size)
+              dist = bump_array_size * (node.z - limit) * (node.z - limit) * 0.5;
+              if (dist < bump_array_size)
                 {
-                    node.x += (node.x - gp->blob_center.x) * gp->wall_shape[dist];
-                    node.y += (node.y - gp->blob_center.y) * gp->wall_shape[dist];
-                    gp->blob_force.z -= (node.z - limit);
+                  node.x += (node.x - gp->blob_center.x) * gp->wall_shape[dist];
+                  node.y += (node.y - gp->blob_center.y) * gp->wall_shape[dist];
+                  gp->blob_force.z -= (node.z - limit);
                 }
 
-                if (node.y < -limit) node.y = -limit;
-                if (node.y > limit) node.y = limit;
+              if (node.y < -limit) node.y = -limit;
+              if (node.y > limit) node.y = limit;
 
-                dist = bump_array_size * (node.y + limit) * (node.y + limit) * 0.5;
-                if (dist < bump_array_size)
+              dist = bump_array_size * (node.y + limit) * (node.y + limit) * 0.5;
+              if (dist < bump_array_size)
                 {
-                    node.x += (node.x - gp->blob_center.x) * gp->wall_shape[dist];
-                    node.z += (node.z - gp->blob_center.z) * gp->wall_shape[dist];
-                    gp->blob_force.y += (node.y + limit);
+                  node.x += (node.x - gp->blob_center.x) * gp->wall_shape[dist];
+                  node.z += (node.z - gp->blob_center.z) * gp->wall_shape[dist];
+                  gp->blob_force.y += (node.y + limit);
                 }
-                else
+              else
                 {
-                    dist = bump_array_size * (node.y - limit) * (node.y - limit) * 0.5;
-                    if (dist < bump_array_size)
+                  dist = bump_array_size * (node.y - limit) * (node.y - limit) * 0.5;
+                  if (dist < bump_array_size)
                     {
-                        node.x += (node.x - gp->blob_center.x) * gp->wall_shape[dist];
-                        node.z += (node.z - gp->blob_center.z) * gp->wall_shape[dist];
-                        gp->blob_force.y -= (node.y - limit);
+                      node.x += (node.x - gp->blob_center.x) * gp->wall_shape[dist];
+                      node.z += (node.z - gp->blob_center.z) * gp->wall_shape[dist];
+                      gp->blob_force.y -= (node.y - limit);
                     }
                 }
 
-                if (node.x < -limit) node.x = -limit;
-                if (node.x > limit) node.x = limit;
+              if (node.x < -limit) node.x = -limit;
+              if (node.x > limit) node.x = limit;
 
-                dist = bump_array_size * (node.x + limit) * (node.x + limit) * 0.5;
-                if (dist < bump_array_size)
+              dist = bump_array_size * (node.x + limit) * (node.x + limit) * 0.5;
+              if (dist < bump_array_size)
                 {
-                    node.y += (node.y - gp->blob_center.y) * gp->wall_shape[dist];
-                    node.z += (node.z - gp->blob_center.z) * gp->wall_shape[dist];
-                    gp->blob_force.x += (node.x + limit);
+                  node.y += (node.y - gp->blob_center.y) * gp->wall_shape[dist];
+                  node.z += (node.z - gp->blob_center.z) * gp->wall_shape[dist];
+                  gp->blob_force.x += (node.x + limit);
                 }
-                else
+              else
                 {
-                    dist = bump_array_size * (node.x - limit) * (node.x - limit) * 0.5;
-                    if (dist < bump_array_size)
+                  dist = bump_array_size * (node.x - limit) * (node.x - limit) * 0.5;
+                  if (dist < bump_array_size)
                     {
-                        node.y += (node.y - gp->blob_center.y) * gp->wall_shape[dist];
-                        node.z += (node.z - gp->blob_center.z) * gp->wall_shape[dist];
-                        gp->blob_force.x -= (node.x - limit);
+                      node.y += (node.y - gp->blob_center.y) * gp->wall_shape[dist];
+                      node.z += (node.z - gp->blob_center.z) * gp->wall_shape[dist];
+                      gp->blob_force.x -= (node.x - limit);
                     }
                 }
 
-                if (node.y < -limit) node.y = -limit;
-                if (node.y > limit) node.y = limit;
+              if (node.y < -limit) node.y = -limit;
+              if (node.y > limit) node.y = limit;
             }
         }
-        gp->dots[index] = node;
+      gp->dots[index] = node;
     }
 
-    /* Determine the normal for each face */
-    for (face = 0; face < gp->num_faces; face++)
+  /* Determine the normal for each face */
+  for (face = 0; face < gp->num_faces; face++)
     {
-        /* Use nodeers to indexed nodes to help readability */
-        Node_Data *node1 = &gp->nodes[gp->faces[face].node1];
-        Node_Data *node2 = &gp->nodes[gp->faces[face].node2];
-        Node_Data *node3 = &gp->nodes[gp->faces[face].node3];
+      /* Use pointers to indexed nodes to help readability */
+      int index1 = gp->faces[face].node1;
+      int index2 = gp->faces[face].node2;
+      int index3 = gp->faces[face].node3;
 
-        gp->faces[face].normal = cross(subtract(node2->position, node1->position),
-                                       subtract(node3->position, node1->position));
+      gp->faces[face].normal = cross(subtract(gp->dots[index2], gp->dots[index1]),
+                                     subtract(gp->dots[index3], gp->dots[index1]));
             
-        /* Add the normal for the face onto the normal for the verticies of
-           the face */
-        add(&node1->normal, gp->faces[face].normal);
-        add(&node2->normal, gp->faces[face].normal);
-        add(&node3->normal, gp->faces[face].normal);
+      /* Add the normal for the face onto the normal for the verticies of
+         the face */
+      add(&gp->nodes[index1].normal, gp->faces[face].normal);
+      add(&gp->nodes[index2].normal, gp->faces[face].normal);
+      add(&gp->nodes[index3].normal, gp->faces[face].normal);
     }
 
-    /* Use the normal to set the colour and texture */
-    if (do_colour || do_texture)
+  /* Use the normal to set the colour and texture */
+  if (do_colour || do_texture)
     {
-        for (index = 0; index < gp->num_nodes; ++index)
+      for (index = 0; index < gp->num_nodes; ++index)
         {
-            gp->normals[index] = normalise(gp->nodes[index].normal);
+          gp->normals[index] = normalise(gp->nodes[index].normal);
    
-            if (do_colour)
+          if (do_colour)
             {
-                gp->colours[index].red = (int)(255.0 * fabs(gp->normals[index].x));
-                gp->colours[index].green = (int)(255.0 * fabs(gp->normals[index].y));
-                gp->colours[index].blue = (int)(255.0 * fabs(gp->normals[index].z));
-                gp->colours[index].alpha = (int)(255.0 * fade);
+              gp->colours[index].red = (int)(255.0 * fabs(gp->normals[index].x));
+              gp->colours[index].green = (int)(255.0 * fabs(gp->normals[index].y));
+              gp->colours[index].blue = (int)(255.0 * fabs(gp->normals[index].z));
+              gp->colours[index].alpha = (int)(255.0 * fade);
             }
-            if (do_texture)
+          if (do_texture)
             {
-                if (offset_texture)
+              if (offset_texture)
                 {
-                    gp->tex_coords[index].x = gp->dots[index].x * 0.125 + 0.5
-                        * (1.0 + 0.25 * asin(gp->normals[index].x) / (0.5 * PI));
-                    gp->tex_coords[index].y = -gp->dots[index].y * 0.125 - 0.5
-                        * (1.0 + 0.25 * asin(gp->normals[index].y) / (0.5 * PI));
+                  const float cube_size = 100.0;
+                  Vector3D eye = {0.0, 0.0, 50.0};
+                  Vector3D eye_r = normalise(subtract(gp->dots[index], eye));
+                  Vector3D reference = subtract(eye_r, scale(gp->normals[index], 2.0 * dot(eye_r, gp->normals[index])));
+                  double x = 0.0;
+                  double y = 0.0;
+                  double n, n_min = 10000.0, sign = 1.0;
+                  if (fabs(reference.z) > 1e-9)
+                    {
+                      n = (cube_size - gp->dots[index].z) / reference.z;
+                      if (n < 0.0)
+                        {
+                          n = (-cube_size - gp->dots[index].z) / reference.z;
+                          sign = 3.0;
+                        }
+                      if (n > 0.0)
+                        {
+                          x = sign * (gp->dots[index].x + n * reference.x);
+                          y = sign * (gp->dots[index].y + n * reference.y);
+                          n_min = n;
+                        }
+                    }
+                  if (fabs(reference.x) > 1e-9)
+                    {
+                      n = (cube_size - gp->dots[index].x) / reference.x;
+                      sign = 1.0;
+                      if (n < 0.0)
+                        {
+                          n = (-cube_size - gp->dots[index].x) / reference.x;
+                          sign = -1.0;
+                        }
+                      if ((n > 0.0) && (n < n_min))
+                        {
+                          x = sign * (2.0 * cube_size - (gp->dots[index].z + n * reference.z));
+                          y = sign * x * (gp->dots[index].y + n * reference.y) / cube_size;
+                          n_min = n;
+                        }
+                    }
+                  if (fabs(reference.y) > 1e-9)
+                    {
+                      n = (cube_size - gp->dots[index].y) / reference.y;
+                      sign = 1.0;
+                      if (n < 0.0)
+                        {
+                          n = (-cube_size - gp->dots[index].y) / reference.y;
+                          sign = -1.0;
+                        }
+                      if ((n > 0.0) && (n < n_min))
+                        {
+                          y = sign * (2.0 * cube_size -( gp->dots[index].z + n * reference.z));
+                          x = sign * y * (gp->dots[index].x + n * reference.x) / cube_size;
+                        }
+                    }
+                                       
+                  gp->tex_coords[index].x = 0.5 + x / (cube_size * 6.0);
+                  gp->tex_coords[index].y = 0.5 - y / (cube_size * 6.0);
                 }
-                else
+              else
                 {
-                    gp->tex_coords[index].x = 0.5
-                        * (1.0 + asin(gp->normals[index].x) / (0.5 * PI));
-                    gp->tex_coords[index].y = -0.5
-                        * (1.0 + asin(gp->normals[index].y) / (0.5 * PI));
+                  gp->tex_coords[index].x = 0.5
+                    * (1.0 + asin(gp->normals[index].x) / (0.5 * PI));
+                  gp->tex_coords[index].y = -0.5
+                    * (1.0 + asin(gp->normals[index].y) / (0.5 * PI));
                 }
-                /* Adjust the texture co-ordinates to from range 0..1 to
-                 * 0..width or 0..height as appropriate
-                 */
-                gp->tex_coords[index].x *= gp->tex_width[gp->current_texture];
-                gp->tex_coords[index].y *= gp->tex_height[gp->current_texture];
+              /* Adjust the texture co-ordinates to from range 0..1 to
+               * 0..width or 0..height as appropriate
+               */
+              gp->tex_coords[index].x *= gp->tex_width[gp->current_texture];
+              gp->tex_coords[index].y *= gp->tex_height[gp->current_texture];
             }
         }
     }
     
-    /* Update the center of the whole blob */
-    add(&gp->blob_velocity, scale (subtract (gp->blob_anchor, gp->blob_center), 1.0 / 80.0));
-    add(&gp->blob_velocity, scale (gp->blob_force, 0.01 / gp->num_nodes));
+  /* Update the center of the whole blob */
+  add(&gp->blob_velocity, scale (subtract (gp->blob_anchor, gp->blob_center), 1.0 / 80.0));
+  add(&gp->blob_velocity, scale (gp->blob_force, 0.01 / gp->num_nodes));
+
+  add(&gp->blob_center, scale(gp->blob_velocity, 0.5));
 
-    add(&gp->blob_center, scale(gp->blob_velocity, 0.5));
+  gp->blob_velocity = scale(gp->blob_velocity, 0.999);
+}
 
-    gp->blob_velocity = scale(gp->blob_velocity, 0.999);
+static void
+draw_vertex(mirrorblobstruct *gp, int index)
+{
+  if (do_colour)
+    {
+      glColor3ub(gp->colours[index].red,
+                 gp->colours[index].green,
+                 gp->colours[index].blue);
+    }
+  if (load_textures)
+    {
+      glTexCoord3dv((GLdouble *) &gp->tex_coords[index]);
+    }
+  glNormal3dv((GLdouble *) &gp->normals[index]);
+  glVertex3dv((GLdouble *) &gp->dots[index]);
 }
 
 /******************************************************************************
@@ -1351,26 +1411,42 @@ calc_blob(mirrorblobstruct *gp,
 static void
 draw_blob (mirrorblobstruct *gp)
 {
-    int face;
+  int face;
 
-    glMatrixMode (GL_MODELVIEW);
-    glLoadIdentity ();
+  glMatrixMode(GL_MODELVIEW);
+  glLoadIdentity();
 
-    /* Move down the z-axis. */
-    glTranslatef (0.0, 0.0, -4.0);
+  /* Move down the z-axis. */
+  glTranslatef (0.0, 0.0, -4.0);
 
-    gltrackball_rotate (gp->trackball);
+  gltrackball_rotate (gp->trackball);
 
-    /* glColor4ub (255, 0, 0, 128); */
-    glBegin (GL_TRIANGLES);
-    for (face = 0; face < gp->num_faces; face++)
+  /* glColor4ub (255, 0, 0, 128); */
+  glBegin(GL_TRIANGLES);
+  for (face = 0; face < gp->num_faces; face++)
     {
-        glArrayElement (gp->faces[face].node1);
-        glArrayElement (gp->faces[face].node2);
-        glArrayElement (gp->faces[face].node3);
+      draw_vertex(gp, gp->faces[face].node1);
+      draw_vertex(gp, gp->faces[face].node2);
+      draw_vertex(gp, gp->faces[face].node3);
     }
-    glEnd ();
-    glLoadIdentity ();
+  glEnd();
+
+#if 0
+  glBegin(GL_LINES);
+  for (face = 0; face < gp->num_faces; face++)
+    {
+      if (gp->normals[gp->faces[face].node1].z > 0.0)
+        {
+          Vector3D end = gp->dots[gp->faces[face].node1];
+          glVertex3dv((GLdouble *) &end);
+          add(&end, scale(gp->normals[gp->faces[face].node1], 0.25));
+          glVertex3dv((GLdouble *) &end);
+        }
+    }
+  glEnd();
+#endif
+       
+  glLoadIdentity();
 }
 
 /******************************************************************************
@@ -1380,40 +1456,40 @@ draw_blob (mirrorblobstruct *gp)
 static void
 draw_background (ModeInfo *mi)
 {
-    mirrorblobstruct *gp = &Mirrorblob[MI_SCREEN(mi)];
+  mirrorblobstruct *gp = &Mirrorblob[MI_SCREEN(mi)];
     
-    glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
-    glEnable (GL_TEXTURE_2D);
-    glDisable(GL_LIGHTING);
-    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+  glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
+  glEnable (GL_TEXTURE_2D);
+  glDisable(GL_LIGHTING);
+  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
 
-    /* Reset the projection matrix to make it easier to get the size of the quad
-     * correct
-     */
-    glMatrixMode(GL_PROJECTION);
-    glPushMatrix();
-    glLoadIdentity();
+  /* Reset the projection matrix to make it easier to get the size of the quad
+   * correct
+   */
+  glMatrixMode(GL_PROJECTION);
+  glPushMatrix();
+  glLoadIdentity();
 
-    glOrtho(0.0, MI_WIDTH(mi), MI_HEIGHT(mi), 0.0, -1000.0, 1000.0);
+  glOrtho(0.0, MI_WIDTH(mi), MI_HEIGHT(mi), 0.0, -1000.0, 1000.0);
 
-    glBegin (GL_QUADS);
+  glBegin (GL_QUADS);
     
-    glTexCoord2f (0.0, 0.0);
-    glVertex2i (0, 0);
+  glTexCoord2f (0.0, 0.0);
+  glVertex2i (0, 0);
     
-    glTexCoord2f (0.0, gp->tex_height[gp->current_texture]);
-    glVertex2i (0, MI_HEIGHT(mi));
+  glTexCoord2f (0.0, gp->tex_height[gp->current_texture]);
+  glVertex2i (0, MI_HEIGHT(mi));
 
-    glTexCoord2f (gp->tex_width[gp->current_texture], gp->tex_height[gp->current_texture]);
-    glVertex2i (MI_WIDTH(mi), MI_HEIGHT(mi));
+  glTexCoord2f (gp->tex_width[gp->current_texture], gp->tex_height[gp->current_texture]);
+  glVertex2i (MI_WIDTH(mi), MI_HEIGHT(mi));
 
-    glTexCoord2f (gp->tex_width[gp->current_texture], 0.0);
-    glVertex2i (MI_WIDTH(mi), 0);
-    glEnd();
+  glTexCoord2f (gp->tex_width[gp->current_texture], 0.0);
+  glVertex2i (MI_WIDTH(mi), 0);
+  glEnd();
 
-    glPopMatrix ();
-    glMatrixMode (GL_MODELVIEW);
-    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+  glPopMatrix ();
+  glMatrixMode (GL_MODELVIEW);
+  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
 }
 
 /******************************************************************************
@@ -1423,187 +1499,199 @@ draw_background (ModeInfo *mi)
 static GLvoid
 draw_scene(ModeInfo * mi)
 {
-    mirrorblobstruct *gp = &Mirrorblob[MI_SCREEN(mi)];
+  mirrorblobstruct *gp = &Mirrorblob[MI_SCREEN(mi)];
     
-    double fade = 0.0;
-    double current_time;
-    check_gl_error ("draw_scene");
+  double fade = 0.0;
+  double current_time;
+  check_gl_error ("draw_scene");
 
-    mi->polygon_count = 0;
-    glColor4d(1.0, 1.0, 1.0, 1.0);
+  mi->polygon_count = 0;
+  glColor4d(1.0, 1.0, 1.0, 1.0);
 
-    current_time = double_time();
-    switch (gp->state)
+  current_time = double_time();
+  switch (gp->state)
     {
+    case INITIALISING:
+      glColor4d(0.0, 0.0, 0.0, 1.0);
+      fade = 1.0;
+      break;
+
     case TRANSITIONING:
-        fade = 1.0 - (current_time - gp->state_start_time) / fade_time;
-        break;
+      fade = 1.0 - (current_time - gp->state_start_time) / fade_time;
+      break;
 
     case LOADING: /* FALL-THROUGH */
     case HOLDING:
-        fade = 1.0;
-        break;
+      fade = 1.0;
+      break;
     }
 
-    /* Set the correct texture, when transitioning this ensures that the first draw
-     * is the original texture (which has the new texture drawn over it with decreasing
-     * transparency)
-     */
-    if (load_textures)
+  /* Set the correct texture, when transitioning this ensures that the first draw
+   * is the original texture (which has the new texture drawn over it with decreasing
+   * transparency)
+   */
+  if (load_textures)
     {
-        glBindTexture (GL_TEXTURE_2D, gp->textures[gp->current_texture]);
+      glBindTexture(GL_TEXTURE_2D, gp->textures[gp->current_texture]);
     }
 
-    glDisable (GL_DEPTH_TEST);
-    if (do_paint_background)
+  glDisable (GL_DEPTH_TEST);
+  if (do_paint_background)
     {
-        glEnable (GL_TEXTURE_2D);
-        if (motion_blur > 0.0)
+      glEnable (GL_TEXTURE_2D);
+      if (motion_blur > 0.0)
         {
-            glClear(GL_DEPTH_BUFFER_BIT);
-            glEnable (GL_BLEND);
-            glColor4d (1.0, 1.0, 1.0, motion_blur);
+          glClear(GL_DEPTH_BUFFER_BIT);
+          glEnable (GL_BLEND);
+          glColor4d (1.0, 1.0, 1.0, motion_blur);
         }
-        else
+      else
         {
-            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+          glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
         }
-        draw_background (mi);
-        mi->polygon_count++;
+      draw_background (mi);
+      mi->polygon_count++;
 
-        /* When transitioning between two images paint the new image over the old
-         * image with a varying alpha value to get a smooth fade.
-         */
-        if (gp->state == TRANSITIONING)
+      /* When transitioning between two images paint the new image over the old
+       * image with a varying alpha value to get a smooth fade.
+       */
+      if (gp->state == TRANSITIONING)
         {
-            glEnable (GL_BLEND);
-            /* Select the texture to transition to */
-            glBindTexture (GL_TEXTURE_2D, gp->textures[1 - gp->current_texture]);
-            glColor4d (1.0, 1.0, 1.0, 1.0 - fade);
+          glEnable (GL_BLEND);
+          /* Select the texture to transition to */
+          glBindTexture (GL_TEXTURE_2D, gp->textures[1 - gp->current_texture]);
+          glColor4d (1.0, 1.0, 1.0, 1.0 - fade);
 
-            draw_background (mi);
-            mi->polygon_count++;
+          draw_background (mi);
+          mi->polygon_count++;
 
-            /* Select the original texture to draw the blob */
-            glBindTexture (GL_TEXTURE_2D, gp->textures[gp->current_texture]);
+          /* Select the original texture to draw the blob */
+          glBindTexture (GL_TEXTURE_2D, gp->textures[gp->current_texture]);
         }
-        /* Clear the depth buffer bit so the backgound is behind the blob */
-        glClear(GL_DEPTH_BUFFER_BIT);
+      /* Clear the depth buffer bit so the backgound is behind the blob */
+      glClear(GL_DEPTH_BUFFER_BIT);
     }
-    else if (motion_blur > 0.0)
+  else if (motion_blur > 0.0)
     {
-        glEnable (GL_BLEND);
-        glColor4d (0.0, 0.0, 0.0, motion_blur);
-        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
-        glTranslatef (0.0, 0.0, -4.0);
-        glRectd (-10.0, -10.0, 10.0, 10.0);
-        if (wireframe)
+      glEnable (GL_BLEND);
+      glColor4d (0.0, 0.0, 0.0, motion_blur);
+      glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+      glTranslatef (0.0, 0.0, -4.0);
+      glRectd (-10.0, -10.0, 10.0, 10.0);
+      if (wireframe)
         {
-            glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+          glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
         }
-        glClear (GL_DEPTH_BUFFER_BIT);
+      glClear(GL_DEPTH_BUFFER_BIT);
     }
-    else
+  else
     {
-        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
     }
 
-    if (!do_texture)
+  if (!do_texture)
     {
-        fade = 1.0;
-        glDisable (GL_TEXTURE_2D);
+      fade = 1.0;
+      glDisable (GL_TEXTURE_2D);
     }
 
-    calc_blob(gp, MI_WIDTH(mi), MI_HEIGHT(mi), BUMP_ARRAY_SIZE, 2.5, fade * blend);
+  calc_blob(gp, MI_WIDTH(mi), MI_HEIGHT(mi), BUMP_ARRAY_SIZE, 2.5, fade * blend);
 
-    set_blob_gl_state(fade * blend);
+  set_blob_gl_state(fade * blend);
 
-    if (blend < 1.0)
+  if (blend < 1.0)
     {
-        /* Disable the three colour chanels so that only the depth buffer is updated */
-        glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
-        draw_blob(gp);
-        mi->polygon_count += gp->num_faces;
-        glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
-        glDepthFunc(GL_LEQUAL);
+      /* Disable the colour chanels so that only the depth buffer is updated */
+      glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+      draw_blob(gp);
+      mi->polygon_count += gp->num_faces;
+      glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
     }
-    glDepthFunc(GL_LEQUAL);
-    draw_blob(gp);
-    mi->polygon_count += gp->num_faces;
-
-    /* While transitioning between images draw a second blob with a modified
-     * alpha value.
-     */
-    if (load_textures && (hold_time > 0))
+       
+  glDepthFunc(GL_LEQUAL);
+  draw_blob(gp);
+  mi->polygon_count += gp->num_faces;
+
+  /* While transitioning between images draw a second blob with a modified
+   * alpha value.
+   */
+  if (load_textures && (hold_time > 0))
     {
-        switch (gp->state)
+      switch (gp->state)
         {
+        case INITIALISING:
+          if (!gp->waiting_for_image_p)
+            {
+              gp->state = HOLDING;
+            }
+          break;
+               
         case HOLDING:
-            if ((current_time - gp->state_start_time) > hold_time)
+          if ((current_time - gp->state_start_time) > hold_time)
             {
-                grab_texture(mi, 1 - gp->current_texture);
-                gp->state = LOADING;
+              grab_texture(mi, 1 - gp->current_texture);
+              gp->state = LOADING;
             }
-            break;
+          break;
 
         case LOADING:
-            /* Once the image has loaded move to the TRANSITIONING STATE */
-            if (!gp->waiting_for_image_p)
+          /* Once the image has loaded move to the TRANSITIONING STATE */
+          if (!gp->waiting_for_image_p)
             {
-                gp->state = TRANSITIONING;
-                /* Get the time again rather than using the current time so
-                 * that the time taken by the grab_texture function is not part
-                 * of the fade time
-                 */
-                gp->state_start_time = double_time();
+              gp->state = TRANSITIONING;
+              /* Get the time again rather than using the current time so
+               * that the time taken by the grab_texture function is not part
+               * of the fade time
+               */
+              gp->state_start_time = double_time();
             }
-            break;        
+          break;        
 
         case TRANSITIONING:
 
-            /* If the blob is textured draw over existing blob to fade between
-             * images
-             */
-            if (do_texture)
+          /* If the blob is textured draw over existing blob to fade between
+           * images
+           */
+          if (do_texture)
             {
-                /* Select the texture to transition to */
-                glBindTexture (GL_TEXTURE_2D, gp->textures[1 - gp->current_texture]);
-                glEnable (GL_BLEND);
+              /* Select the texture to transition to */
+              glBindTexture (GL_TEXTURE_2D, gp->textures[1 - gp->current_texture]);
+              glEnable (GL_BLEND);
                 
-                /* If colour is enabled update the alpha data in the buffer and
-                 * use that in the blending since the alpha of the incomming
-                 * verticies will not be correct
-                 */
-                if (do_colour)
+              /* If colour is enabled update the alpha data in the buffer and
+               * use that in the blending since the alpha of the incomming
+               * verticies will not be correct
+               */
+              if (do_colour)
                 {
-                    glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
-                    glClearColor(0.0, 0.0, 0.0, (1.0 - fade) * blend);
-                    glClear(GL_COLOR_BUFFER_BIT);
-                    glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);                    
-                    glBlendFunc(GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA);
+                  glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
+                  glClearColor(0.0, 0.0, 0.0, (1.0 - fade) * blend);
+                  glClear(GL_COLOR_BUFFER_BIT);
+                  glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);                    
+                  glBlendFunc(GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA);
                 }
-                else
+              else
                 {
-                    glColor4d(0.9, 0.9, 1.0, (1.0 - fade) * blend);
+                  glColor4d(0.9, 0.9, 1.0, (1.0 - fade) * blend);
                 }
 
-                draw_blob (gp);
-                mi->polygon_count += gp->num_faces;
+              draw_blob (gp);
+              mi->polygon_count += gp->num_faces;
 
-                if (do_colour)
+              if (do_colour)
                 {
-                    /* Restore the 'standard' blend functions. */
-                    glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+                  /* Restore the 'standard' blend functions. */
+                  glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
                 }
             }
             
-            if ((current_time - gp->state_start_time) > fade_time)
+          if ((current_time - gp->state_start_time) > fade_time)
             {
-                gp->state = HOLDING;
-                gp->state_start_time = current_time;
-                gp->current_texture = 1 - gp->current_texture;
+              gp->state = HOLDING;
+              gp->state_start_time = current_time;
+              gp->current_texture = 1 - gp->current_texture;
             }
-            break;
+          break;
 
         }
     }
@@ -1616,22 +1704,23 @@ draw_scene(ModeInfo * mi)
 ENTRYPOINT void
 draw_mirrorblob(ModeInfo * mi)
 {
-    mirrorblobstruct *gp = &Mirrorblob[MI_SCREEN(mi)];
-    Display    *display = MI_DISPLAY(mi);
-    Window      window = MI_WINDOW(mi);
-
-    if (!gp->glx_context)
-        return;
-
-    /* Wait for the first image; for subsequent images, load them in the
-       background while animating. */
-    if (gp->waiting_for_image_p && gp->first_image_p)
-      return;
-
-    glXMakeCurrent(display, window, *(gp->glx_context));
-    draw_scene(mi);
-    if (mi->fps_p) do_fps (mi);
-    glXSwapBuffers(display, window);
+  mirrorblobstruct *gp = &Mirrorblob[MI_SCREEN(mi)];
+  Display    *display = MI_DISPLAY(mi);
+  Window      window = MI_WINDOW(mi);
+
+  if (!gp->glx_context)
+    return;
+
+  /* Wait for the first image; for subsequent images, load them in the
+     background while animating. */
+  if (gp->waiting_for_image_p && gp->first_image_p)
+    return;
+
+  glXMakeCurrent(display, window, *(gp->glx_context));
+  draw_scene(mi);
+  if (mi->fps_p) do_fps (mi);
+  glFinish();
+  glXSwapBuffers(display, window);
 }
 
 /******************************************************************************
@@ -1641,8 +1730,8 @@ draw_mirrorblob(ModeInfo * mi)
 ENTRYPOINT void
 reshape_mirrorblob(ModeInfo *mi, int width, int height)
 {
-    glViewport( 0, 0, MI_WIDTH(mi), MI_HEIGHT(mi) );
-    reset_projection(width, height);
+  glViewport( 0, 0, MI_WIDTH(mi), MI_HEIGHT(mi) );
+  reset_projection(width, height);
 }
 
 /****************************************************************************
@@ -1652,42 +1741,42 @@ reshape_mirrorblob(ModeInfo *mi, int width, int height)
 ENTRYPOINT Bool
 mirrorblob_handle_event (ModeInfo * mi, XEvent * event)
 {
-    mirrorblobstruct *gp = &Mirrorblob[MI_SCREEN (mi)];
+  mirrorblobstruct *gp = &Mirrorblob[MI_SCREEN (mi)];
 
-    if (event->xany.type == ButtonPress &&
-        event->xbutton.button == Button1)
+  if (event->xany.type == ButtonPress &&
+      event->xbutton.button == Button1)
     {
-        gp->button_down = 1;
-        gltrackball_start (gp->trackball, event->xbutton.x,
-                           event->xbutton.y, MI_WIDTH (mi), MI_HEIGHT (mi));
-        return True;
+      gp->button_down = 1;
+      gltrackball_start (gp->trackball, event->xbutton.x,
+                         event->xbutton.y, MI_WIDTH (mi), MI_HEIGHT (mi));
+      return True;
     }
-    else if (event->xany.type == ButtonRelease &&
-             event->xbutton.button == Button1)
+  else if (event->xany.type == ButtonRelease &&
+           event->xbutton.button == Button1)
     {
-        gp->button_down = 0;
-        return True;
+      gp->button_down = 0;
+      return True;
     }
-    else if (event->xany.type == ButtonPress &&
-             event->xbutton.button == Button4)
+  else if (event->xany.type == ButtonPress &&
+           event->xbutton.button == Button4)
     {
-        zoom *= 1.1;
-        return True;
+      zoom *= 1.1;
+      return True;
     }
-    else if (event->xany.type == ButtonPress &&
-             event->xbutton.button == Button5)
+  else if (event->xany.type == ButtonPress &&
+           event->xbutton.button == Button5)
     {
 
-        zoom *= 0.9;
-        return True;
+      zoom *= 0.9;
+      return True;
     }
-    else if (event->xany.type == MotionNotify && gp->button_down)
+  else if (event->xany.type == MotionNotify && gp->button_down)
     {
-        gltrackball_track (gp->trackball, event->xmotion.x,
-                           event->xmotion.y, MI_WIDTH (mi), MI_HEIGHT (mi));
-        return True;
+      gltrackball_track (gp->trackball, event->xmotion.x,
+                         event->xmotion.y, MI_WIDTH (mi), MI_HEIGHT (mi));
+      return True;
     }
-    return False;
+  return False;
 }
 
 /******************************************************************************
@@ -1697,36 +1786,37 @@ mirrorblob_handle_event (ModeInfo * mi, XEvent * event)
 ENTRYPOINT void
 init_mirrorblob(ModeInfo * mi)
 {
-    int screen = MI_SCREEN(mi);
+  int screen = MI_SCREEN(mi);
 
-    mirrorblobstruct *gp;
+  mirrorblobstruct *gp;
 
-    if (Mirrorblob == NULL)
+  if (Mirrorblob == NULL)
     {
-        if ((Mirrorblob = (mirrorblobstruct *)
-             calloc(MI_NUM_SCREENS(mi), sizeof (mirrorblobstruct))) == NULL)
+      if ((Mirrorblob = (mirrorblobstruct *)
+           calloc(MI_NUM_SCREENS(mi), sizeof (mirrorblobstruct))) == NULL)
         {
-            return;
+          return;
         }
     }
-    gp = &Mirrorblob[screen];
+  gp = &Mirrorblob[screen];
 
-    gp->window = MI_WINDOW(mi);
-    if ((gp->glx_context = init_GL(mi)) != NULL)
+  gp->window = MI_WINDOW(mi);
+  if ((gp->glx_context = init_GL(mi)) != NULL)
     {
-        reshape_mirrorblob(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
-        initialize_gl(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
+      reshape_mirrorblob(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
+      initialize_gl(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
     }
-    else
+  else
     {
-        MI_CLEARWINDOW(mi);
+      MI_CLEARWINDOW(mi);
     }
-    gp->trackball = gltrackball_init ();
+  gp->trackball = gltrackball_init();
     
-    initialise_blob(gp, MI_WIDTH(mi), MI_HEIGHT(mi), BUMP_ARRAY_SIZE);
-    gp->state_start_time = double_time();
+  initialise_blob(gp, MI_WIDTH(mi), MI_HEIGHT(mi), BUMP_ARRAY_SIZE);
+  gp->state = INITIALISING;
+  gp->state_start_time = double_time();
 
-    gp->first_image_p = True;
+  gp->first_image_p = True;
 }
 
 /******************************************************************************
index 25841d71b09db279ae549cad61e8ca42a605c1a8..f8078b2c4534257319f0db0d53b30b392c4f73f5 100644 (file)
@@ -14,6 +14,8 @@
 /* Documentation on the PDB file format:
    http://en.wikipedia.org/wiki/Protein_Data_Bank_%28file_format%29
    http://www.wwpdb.org/docs.html
+   http://www.wwpdb.org/documentation/format32/v3.2.html
+   http://www.wwpdb.org/documentation/format32/sect9.html
    http://www.rcsb.org/pdb/file_formats/pdb/pdbguide2.2/guide2.2_frame.html
 
    Good source of PDB files:
@@ -752,13 +754,26 @@ parse_pdb_data (molecule *m, const char *data, const char *filename, int line)
       else if (!strncmp (s, "ATOM   ", 7))
         {
           int id;
+          const char *end = strchr (s, '\n');
+          int L = end - s;
           char *name = (char *) calloc (1, 4);
           GLfloat x = -999, y = -999, z = -999;
 
           if (1 != sscanf (s+7, " %d ", &id))
             parse_error (filename, line, s);
 
+          /* Use the "atom name" field if that is all that is available. */
           strncpy (name, s+12, 3);
+
+          /* But prefer the "element" field. */
+          if (L > 77 && !isspace(s[77])) {
+            /* fprintf(stderr, "  \"%s\" -> ", name); */
+            name[0] = s[76];
+            name[1] = s[77];
+            name[2] = 0;
+            /* fprintf(stderr, "\"%s\"\n", name); */
+          }
+
           while (isspace(*name)) name++;
           ss = name + strlen(name)-1;
           while (isspace(*ss) && ss > name)
index 7e6faef93b381234995c1bf03f6f5a8acd6def92..b4c98d0eb8d932f73bb1150f7c75b75c37e3ae71 100644 (file)
@@ -296,11 +296,12 @@ load_image (ModeInfo *mi)
     image_loaded_cb (0, 0, 0, 0, 0, 0, ss);
   else
     {
-      int w = (int)(MI_WIDTH(mi)  * scale) - 1;
-      int h = (int)(MI_HEIGHT(mi) * scale) - 1;
-      if (w <= 10) w = 10;
-      if (h <= 10) h = 10;
-      load_texture_async (mi->xgwa.screen, mi->window, *ss->glx_context, w, h,
+      int w = MI_WIDTH(mi);
+      int h = MI_HEIGHT(mi);
+      int size = (int)((w > h ? w : h) * scale);
+      if (size <= 10) size = 10;
+      load_texture_async (mi->xgwa.screen, mi->window, *ss->glx_context,
+                          size, size,
                           mipmap_p, frame->texid, 
                           image_loaded_cb, ss);
     }
diff --git a/hacks/glx/rubikblocks.c b/hacks/glx/rubikblocks.c
new file mode 100644 (file)
index 0000000..1228277
--- /dev/null
@@ -0,0 +1,653 @@
+/* rubikblocks, Copyright (c) 2009 Vasek Potocek <vasek.potocek@post.cz>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation.  No representations are made about the suitability of this
+ * software for any purpose.  It is provided "as is" without express or 
+ * implied warranty.
+ */
+
+/* RubikBlocks - a Rubik's Mirror Blocks puzzle introduced in 2008.
+ * No mirrors in this version, though, hence the altered name.
+ */
+
+/* TODO:
+ * add reflection to the faces
+ */
+
+#define DEFAULTS   "*delay:         20000         \n" \
+                   "*showFPS:       False         \n" \
+                   "*wireframe:     False         \n"
+
+# define refresh_rubikblocks 0
+#include "xlockmore.h"
+#include "rotator.h"
+#include "gltrackball.h"
+
+#ifdef USE_GL
+
+#define DEF_SPIN        "True"
+#define DEF_WANDER      "True"
+#define DEF_TEXTURE     "True"
+#define DEF_RANDOMIZE   "False"
+#define DEF_SPINSPEED   "0.1"
+#define DEF_ROTSPEED    "3.0"
+#define DEF_WANDERSPEED "0.005"
+#define DEF_WAIT        "40.0"
+#define DEF_CUBESIZE    "1.0"
+
+#define SHUFFLE 100
+
+#define TEX_WIDTH  64
+#define TEX_HEIGHT 64
+#define BORDER     5
+#define BORDER2    (BORDER*BORDER)
+
+#undef countof
+#define countof(x) (sizeof((x))/sizeof((*x)))
+
+#define rnd01() ((int)(random()%2))
+
+/*************************************************************************/
+
+static Bool spin, wander, rndstart, tex;
+static float spinspeed, tspeed, wspeed, twait, size;
+
+static argtype vars[] = {
+  { &spin,      "spin",        "Spin",        DEF_SPIN,        t_Bool},
+  { &wander,    "wander",      "Wander",      DEF_WANDER,      t_Bool},
+  { &rndstart,  "randomize",   "Randomize",   DEF_RANDOMIZE,   t_Bool},
+  { &tex,       "texture",     "Texture",     DEF_TEXTURE,     t_Bool},
+  { &spinspeed, "spinspeed",   "SpinSpeed",   DEF_SPINSPEED,   t_Float},
+  { &tspeed,    "rotspeed",    "RotSpeed",    DEF_ROTSPEED,    t_Float},
+  { &wspeed,    "wanderspeed", "WanderSpeed", DEF_WANDERSPEED, t_Float},
+  { &twait,     "wait",        "Wait",        DEF_WAIT,        t_Float},
+  { &size,      "cubesize",    "CubeSize",    DEF_CUBESIZE,    t_Float},
+};
+
+static XrmOptionDescRec opts[] = {
+  { "-spin",        ".spin",        XrmoptionNoArg,  "True" },
+  { "+spin",        ".spin",        XrmoptionNoArg,  "False" },
+  { "-wander",      ".wander",      XrmoptionNoArg,  "True" },
+  { "+wander",      ".wander",      XrmoptionNoArg,  "False" },
+  { "-randomize",   ".randomize",   XrmoptionNoArg,  "True" },
+  { "+randomize",   ".randomize",   XrmoptionNoArg,  "False" },
+  { "-texture",     ".texture",     XrmoptionNoArg,  "True" },
+  { "+texture",     ".texture",     XrmoptionNoArg,  "False" },
+  { "-spinspeed",   ".spinspeed",   XrmoptionSepArg, 0 },
+  { "-wanderspeed", ".wanderspeed", XrmoptionSepArg, 0 },
+  { "-rotspeed",    ".rotspeed",    XrmoptionSepArg, 0 },
+  { "-wait",        ".wait",        XrmoptionSepArg, 0 },
+  { "-cubesize",    ".cubesize",    XrmoptionSepArg, 0 },
+};
+
+ENTRYPOINT ModeSpecOpt rubikblocks_opts = {countof(opts), opts, countof(vars), vars, NULL};
+
+#ifdef USE_MODULES
+ModStruct   rubikblocks_description =
+{ "rubikblocks", "init_rubikblocks", "draw_rubikblocks", "release_rubikblocks",
+  "draw_rubikblocks", "change_rubikblocks", NULL, &rubikblocks_opts,
+  25000, 1, 1, 1, 1.0, 4, "",
+  "Shows randomly shuffling Rubik's Mirror Blocks puzzle", 0, NULL
+};
+#endif
+
+typedef struct {
+  float         pos[3]; /* _original_ position */
+  float         qr[4];  /* quaternion of rotation */
+  Bool          act;    /* flag if it is undergoing the current rotation */
+} piece_t;
+
+typedef struct {
+  GLXContext    *glx_context;
+  rotator       *rot;
+  trackball_state *trackball;
+  GLfloat       ratio;
+  Bool          button_down;
+
+  Bool          pause;          /* pause between two rotations */
+  float         qfram[4];       /* quaternion describing the rotation in one anim. frame */
+  GLfloat       t, tmax;        /* rotation clock */
+  piece_t       pieces[27];     /* type and tilt of all the pieces */
+
+  unsigned char texture[TEX_HEIGHT][TEX_WIDTH];
+  GLuint        list_base;
+  Bool          wire;
+} rubikblocks_conf;
+
+static rubikblocks_conf *rubikblocks = NULL;
+
+static const GLfloat shininess = 20.0;
+static const GLfloat ambient[] = {0.0, 0.0, 0.0, 1.0};
+static const GLfloat diffuse[] = {1.0, 1.0, 1.0, 1.0};
+static const GLfloat position0[] = {1.0, 1.0, 1.0, 0.0};
+static const GLfloat position1[] = {-1.0, -1.0, 1.0, 0.0};
+static const GLfloat lmodel_ambient[] = {0.1, 0.1, 0.1, 1.0};
+static const GLfloat material_ambient[] = {0.7, 0.7, 0.7, 1.0};
+static const GLfloat material_diffuse[] = {0.7, 0.7, 0.7, 1.0};
+static const GLfloat material_specular[] = {0.2, 0.2, 0.2, 1.0};
+static const GLfloat zpos = -18.0;
+
+/*************************************************************************/
+
+/* Multiplies two quaternions, src*dest, and stores the result in dest. */
+static void
+mult_quat(float src[4], float dest[4])
+{
+  float r, i, j, k;
+  r = src[0]*dest[0] - src[1]*dest[1] - src[2]*dest[2] - src[3]*dest[3];
+  i = src[0]*dest[1] + src[1]*dest[0] + src[2]*dest[3] - src[3]*dest[2];
+  j = src[0]*dest[2] + src[2]*dest[0] + src[3]*dest[1] - src[1]*dest[3];
+  k = src[0]*dest[3] + src[3]*dest[0] + src[1]*dest[2] - src[2]*dest[1];
+  dest[0] = r;
+  dest[1] = i;
+  dest[2] = j;
+  dest[3] = k;
+}
+
+/* Sets the 'act' flag for pieces which will undergo the rotation. */
+static void
+flag_pieces(piece_t pieces[27], int axis, int side)
+{
+  int i, j;
+  float q[4];
+  for(i = 0; i < 27; i++)
+  {
+    q[0] = 0;
+    q[1] = pieces[i].pos[0];
+    q[2] = pieces[i].pos[1];
+    q[3] = pieces[i].pos[2];
+    mult_quat(pieces[i].qr, q);
+    for(j = 1; j < 4; j++)
+      q[j] = -q[j];
+    mult_quat(pieces[i].qr, q);
+    for(j = 1; j < 4; j++)
+      q[j] = -q[j];
+    if(fabs(q[axis] - side) < 0.1)
+      pieces[i].act = True;
+    else
+      pieces[i].act = False;
+  }
+}
+
+/* "Rounds" the value to the nearest from the set {0, +-1/2, +-1/sqrt(2), +-1}.
+ * It is guaranteed to be pretty close to one when this function is called. */
+static float 
+settle_value(float v) 
+{
+  if(v > 0.9) return 1;
+  else if(v < -0.9) return -1;
+  else if(v > 0.6) return M_SQRT1_2;
+  else if(v < -0.6) return -M_SQRT1_2;
+  else if(v > 0.4) return 0.5;
+  else if(v < -0.4) return -0.5;
+  else return 0;
+}
+
+static void 
+randomize(rubikblocks_conf *cp) 
+{
+  int axis, side;
+  int i, j;
+  for(i = 0; i < SHUFFLE; i++)
+  {
+    axis = (random()%3)+1;
+    side = rnd01()*2-1;
+    flag_pieces(cp->pieces, axis, side);
+    for(j = 1; j < 4; j++)
+      cp->qfram[j] = 0;
+    cp->qfram[0] = M_SQRT1_2;
+    cp->qfram[axis] = M_SQRT1_2;
+    for(j = 0; j < 27; j++)
+    {
+      if(cp->pieces[j].act)
+        mult_quat(cp->qfram, cp->pieces[j].qr);
+    }
+  }
+}
+
+static void 
+finish(rubikblocks_conf *cp) 
+{
+  static int axis = 1;
+  int side, angle;
+  int i, j;
+  if(cp->pause)
+  {
+    switch(axis) 
+    {
+      case 1:
+        axis = rnd01()+2;
+        break;
+      case 2:
+        axis = 2*rnd01()+1;
+        break;
+      default:
+        axis = rnd01()+1;
+    }
+    side = rnd01()*2-1;
+    angle = rnd01()+1;
+    flag_pieces(cp->pieces, axis, side);
+    cp->pause = False;
+    cp->tmax = 90.0*angle;
+    for(i = 1; i < 4; i++)
+      cp->qfram[i] = 0;
+    cp->qfram[0] = cos(tspeed*M_PI/360);
+    cp->qfram[axis] = sin((rnd01()*2-1)*tspeed*M_PI/360);
+  }
+  else
+  {
+    for(i = 0; i < 27; i++)
+    {
+      for(j = 0; j < 4; j++)
+      {
+        cp->pieces[i].qr[j] = settle_value(cp->pieces[i].qr[j]);
+      }
+    }
+    cp->pause = True;
+    cp->tmax = twait;
+  }
+  cp->t = 0;
+}
+
+static Bool 
+draw_main(ModeInfo *mi, rubikblocks_conf *cp) 
+{
+  int i;
+  double x, y, z;
+
+  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+  glLoadIdentity();
+  get_position(cp->rot, &x, &y, &z, !cp->button_down);
+  glTranslatef((x-0.5)*6, (y-0.5)*6, -20);
+  gltrackball_rotate(cp->trackball);
+  get_rotation(cp->rot, &x, &y, &z, !cp->button_down);
+  glRotatef(x*360, 1, 0, 0);
+  glRotatef(y*360, 0, 1, 0);
+  glRotatef(z*360, 0, 0, 1);
+  glScalef(size, size, size);
+
+  if(cp->wire) glColor3f(0.7, 0.7, 0.7);
+  if(!cp->pause)
+    for(i = 0; i < 27; i++)
+      if(cp->pieces[i].act)
+        mult_quat(cp->qfram, cp->pieces[i].qr);
+  for(i = 0; i < 27; i++) 
+  {
+    glPushMatrix();
+    if(fabs(cp->pieces[i].qr[0]) < 1)
+      glRotatef(360/M_PI*acos(cp->pieces[i].qr[0]),
+          cp->pieces[i].qr[1], cp->pieces[i].qr[2], cp->pieces[i].qr[3]);
+    glCallList(cp->list_base + i);
+    glPopMatrix();
+  }
+  if((cp->t += tspeed) > cp->tmax) finish(cp);
+  return True;
+}
+
+static void 
+draw_horz_line(rubikblocks_conf *cp, int x1, int x2, int y) 
+{
+  int x, y0 = y, w;
+  if(y < BORDER) y = -y;
+  else y = -BORDER;
+  for(; y < BORDER; y++) {
+    if(y0+y >= TEX_HEIGHT) break;
+    w = y*y*255/BORDER2;
+    for(x = x1; x <= x2; x++)
+      if(cp->texture[y0+y][x]>w) cp->texture[y0+y][x] = w;
+  }
+}
+
+static void 
+draw_vert_line(rubikblocks_conf *cp, int x, int y1, int y2) 
+{
+  int x0 = x, y, w;
+  if(x<BORDER) x = -x;
+  else x = -BORDER;
+  for(; x < BORDER; x++) {
+    if(x0+x >= TEX_WIDTH) break;
+    w = x*x*255/BORDER2;
+    for(y = y1; y <= y2; y++)
+      if(cp->texture[y][x0+x]>w) cp->texture[y][x0+x] = w;
+  }
+}
+
+static void 
+make_texture(rubikblocks_conf *cp) 
+{
+  int x, y;
+  for(y = 0; y < TEX_HEIGHT; y++)
+    for(x = 0; x < TEX_WIDTH; x++)
+      cp->texture[y][x] = 255;
+  draw_horz_line(cp, 0, TEX_WIDTH-1, 0);
+  draw_horz_line(cp, 0, TEX_WIDTH-1, TEX_HEIGHT-1);
+  draw_vert_line(cp, 0, 0, TEX_HEIGHT-1);
+  draw_vert_line(cp, TEX_WIDTH-1, 0, TEX_HEIGHT-1);
+}
+
+/* These simple transforms make the actual shape of the pieces. The parameters
+ * A, B and C affect the excentricity of the pieces in each direction. */
+static float 
+fx(float x)
+{
+  const float A = 0.5;
+  if(x > 1.4) return 1.5 - A;
+  else if(x < -1.4) return -1.5 - A;
+  else return x;
+}
+
+static float 
+fy(float y)
+{
+  const float B = 0.25;
+  if(y > 1.4) return 1.5 - B;
+  else if(y < -1.4) return -1.5 - B;
+  else return y;
+}
+
+static float 
+fz(float z)
+{
+  const float C = 0.0;
+  if(z > 1.4) return 1.5 - C;
+  else if(z < -1.4) return -1.5 - C;
+  else return z;
+}
+
+static void 
+init_lists(rubikblocks_conf *cp)
+{
+  GLuint base;
+  int i;
+  float x, y, z;
+  base = cp->list_base = glGenLists(27);
+  for(i = 0; i < 27; i++)
+  {
+    x = cp->pieces[i].pos[0];
+    y = cp->pieces[i].pos[1];
+    z = cp->pieces[i].pos[2];
+    glNewList(base+i, GL_COMPILE);
+    glBegin(GL_QUAD_STRIP);
+    glNormal3f(1, 0, 0);
+    glTexCoord2f(0, 0);
+    glVertex3f(fx(x+0.5), fy(y-0.5), fz(z-0.5));
+    glTexCoord2f(0, 1);
+    glVertex3f(fx(x+0.5), fy(y+0.5), fz(z-0.5));
+    glTexCoord2f(1, 0);
+    glVertex3f(fx(x+0.5), fy(y-0.5), fz(z+0.5));
+    glTexCoord2f(1, 1);
+    glVertex3f(fx(x+0.5), fy(y+0.5), fz(z+0.5));
+    glNormal3f(0, 0, 1);
+    glTexCoord2f(0, 0);
+    glVertex3f(fx(x-0.5), fy(y-0.5), fz(z+0.5));
+    glTexCoord2f(0, 1);
+    glVertex3f(fx(x-0.5), fy(y+0.5), fz(z+0.5));
+    glNormal3f(-1, 0, 0);
+    glTexCoord2f(1, 0);
+    glVertex3f(fx(x-0.5), fy(y-0.5), fz(z-0.5));
+    glTexCoord2f(1, 1);
+    glVertex3f(fx(x-0.5), fy(y+0.5), fz(z-0.5));
+    glNormal3f(0, 0, -1);
+    glTexCoord2f(0, 0);
+    glVertex3f(fx(x+0.5), fy(y-0.5), fz(z-0.5));
+    glTexCoord2f(0, 1);
+    glVertex3f(fx(x+0.5), fy(y+0.5), fz(z-0.5));
+    glEnd();
+    glBegin(GL_QUADS);
+    glNormal3f(0, 1, 0);
+    glTexCoord2f(0, 0);
+    glVertex3f(fx(x+0.5), fy(y+0.5), fz(z+0.5));
+    glTexCoord2f(0, 1);
+    glVertex3f(fx(x+0.5), fy(y+0.5), fz(z-0.5));
+    glTexCoord2f(1, 1);
+    glVertex3f(fx(x-0.5), fy(y+0.5), fz(z-0.5));
+    glTexCoord2f(1, 0);
+    glVertex3f(fx(x-0.5), fy(y+0.5), fz(z+0.5));
+    glNormal3f(0, -1, 0);
+    glTexCoord2f(0, 0);
+    glVertex3f(fx(x+0.5), fy(y-0.5), fz(z-0.5));
+    glTexCoord2f(0, 1);
+    glVertex3f(fx(x+0.5), fy(y-0.5), fz(z+0.5));
+    glTexCoord2f(1, 1);
+    glVertex3f(fx(x-0.5), fy(y-0.5), fz(z+0.5));
+    glTexCoord2f(1, 0);
+    glVertex3f(fx(x-0.5), fy(y-0.5), fz(z-0.5));
+    glEnd();
+    glEndList();
+  }
+}
+
+/* It looks terrible... FIXME: any other ideas, maybe some anisotropic filtering? */
+/*#define MIPMAP*/
+
+static void 
+init_gl(ModeInfo *mi) 
+{
+  rubikblocks_conf *cp = &rubikblocks[MI_SCREEN(mi)];
+#ifdef MIPMAP
+  int status;
+#endif
+  cp->wire = MI_IS_WIREFRAME(mi);
+  if(MI_IS_MONO(mi))
+    tex = False;
+  if(cp->wire) {
+    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+    return;
+  }
+
+  glClearDepth(1.0);
+  glClearColor(0.0, 0.0, 0.0, 1.0);
+  glDrawBuffer(GL_BACK);
+  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+  glShadeModel(GL_FLAT);
+  glDepthFunc(GL_LESS);
+  glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
+  glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
+  glLightfv(GL_LIGHT0, GL_POSITION, position0);
+  glLightfv(GL_LIGHT1, GL_AMBIENT, ambient);
+  glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse);
+  glLightfv(GL_LIGHT1, GL_POSITION, position1);
+  glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
+  glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
+  glEnable(GL_DEPTH_TEST);
+  glEnable(GL_LIGHT0);
+  glEnable(GL_LIGHT1);
+  glEnable(GL_LIGHTING);
+  glEnable(GL_NORMALIZE);
+  glEnable(GL_COLOR_MATERIAL);
+  glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, material_ambient);
+  glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, material_diffuse);
+  glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, material_specular);
+  glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shininess);
+  if(!tex) return;
+  glEnable(GL_TEXTURE_2D);
+#ifdef MIPMAP
+  clear_gl_error();
+  status = gluBuild2DMipmaps(GL_TEXTURE_2D, 1, TEX_WIDTH, TEX_HEIGHT,
+      GL_LUMINANCE, GL_UNSIGNED_BYTE, cp->texture);
+  if (status) {
+    const char *s = (char *)gluErrorString(status);
+    fprintf (stderr, "%s: error mipmapping texture: %s\n", progname, (s?s:"(unknown)"));
+    exit (1);
+  }
+  check_gl_error("mipmapping");
+#else    
+  glTexImage2D(GL_TEXTURE_2D, 0, 1, TEX_WIDTH, TEX_HEIGHT,
+      0, GL_LUMINANCE, GL_UNSIGNED_BYTE, cp->texture);
+#endif  
+  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+#ifdef MIPMAP
+  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+#else
+  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+#endif
+}
+
+static void 
+init_cp(rubikblocks_conf *cp) 
+{
+  int i, j, k, m;
+
+  cp->pause = True;
+  cp->t = 0.0;
+  cp->tmax = twait;
+
+  for(i = -1, m = 0; i <= 1; i++)
+    for(j = -1; j <= 1; j++)
+      for(k = -1; k <= 1; k++)
+      {
+        cp->pieces[m].pos[0] = k;
+        cp->pieces[m].pos[1] = j;
+        cp->pieces[m].pos[2] = i;
+        cp->pieces[m].qr[0] = 1;
+        cp->pieces[m].qr[1] = 0;
+        cp->pieces[m].qr[2] = 0;
+        cp->pieces[m].qr[3] = 0;
+        m++;
+      }
+
+  cp->rot = make_rotator(spin?spinspeed:0, spin?spinspeed:0, spin?spinspeed:0,
+      0.1, wander?wspeed:0, True);
+  cp->trackball = gltrackball_init();
+
+  if(rndstart) randomize(cp);
+}
+
+/*************************************************************************/
+
+ENTRYPOINT void 
+reshape_rubikblocks(ModeInfo *mi, int width, int height) 
+{
+  rubikblocks_conf *cp = &rubikblocks[MI_SCREEN(mi)];
+  if(!height) height = 1;
+  cp->ratio = (GLfloat)width/(GLfloat)height;
+  glViewport(0, 0, (GLint) width, (GLint) height);
+  glMatrixMode(GL_PROJECTION);
+  glLoadIdentity();
+  gluPerspective(30.0, cp->ratio, 1.0, 100.0);
+  glMatrixMode(GL_MODELVIEW);
+  glClear(GL_COLOR_BUFFER_BIT);
+}
+
+ENTRYPOINT void 
+release_rubikblocks(ModeInfo *mi) 
+{
+  if (rubikblocks != NULL) 
+  {
+    int screen;
+    for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) 
+    {
+      rubikblocks_conf *cp = &rubikblocks[screen];
+      if (cp->glx_context) {
+        cp->glx_context = NULL;
+      }
+    }
+    free((void *)rubikblocks);
+    rubikblocks = NULL;
+  }
+  FreeAllGL(mi);
+}
+
+ENTRYPOINT void 
+init_rubikblocks(ModeInfo *mi) 
+{
+  rubikblocks_conf *cp;
+  if(!rubikblocks) 
+  {
+    rubikblocks = (rubikblocks_conf *)calloc(MI_NUM_SCREENS(mi), sizeof(rubikblocks_conf));
+    if(!rubikblocks) return;
+  }
+  cp = &rubikblocks[MI_SCREEN(mi)];
+
+  if(tex)
+    make_texture(cp);
+
+  if ((cp->glx_context = init_GL(mi)) != NULL) 
+  {
+    init_gl(mi);
+    init_cp(cp);
+    init_lists(cp);
+    reshape_rubikblocks(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
+  }
+  else 
+  {
+    MI_CLEARWINDOW(mi);
+  }
+}
+
+ENTRYPOINT void 
+draw_rubikblocks(ModeInfo * mi) 
+{
+  Display *display = MI_DISPLAY(mi);
+  Window window = MI_WINDOW(mi);
+  rubikblocks_conf *cp;
+  if (!rubikblocks) return;
+  cp = &rubikblocks[MI_SCREEN(mi)];
+  MI_IS_DRAWN(mi) = True;
+  if (!cp->glx_context) return;
+  mi->polygon_count = 0;
+  glXMakeCurrent(display, window, *(cp->glx_context));
+  if (!draw_main(mi, cp)) 
+  {
+    release_rubikblocks(mi);
+    return;
+  }
+  if (MI_IS_FPS(mi)) do_fps (mi);
+  glFlush();
+  glXSwapBuffers(display, window);
+}
+
+#ifndef STANDALONE
+ENTRYPOINT void 
+change_rubikblocks(ModeInfo * mi) 
+{
+  rubikblocks_conf *cp = &rubikblocks[MI_SCREEN(mi)];
+  if (!cp->glx_context) return;
+  glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(cp->glx_context));
+  init_gl(mi);
+}
+#endif /* !STANDALONE */
+
+ENTRYPOINT Bool
+rubikblocks_handle_event (ModeInfo *mi, XEvent *event)
+{
+  rubikblocks_conf *cp = &rubikblocks[MI_SCREEN(mi)];
+  if(event->xany.type == ButtonPress && event->xbutton.button == Button1)
+  {
+    cp->button_down = True;
+    gltrackball_start(cp->trackball, event->xbutton.x, event->xbutton.y,
+        MI_WIDTH(mi), MI_HEIGHT(mi));
+    return True;
+  }
+  else if(event->xany.type == ButtonRelease && event->xbutton.button == Button1)
+  {
+    cp->button_down = False;
+    return True;
+  }
+  else if(event->xany.type == ButtonPress &&
+      (event->xbutton.button == Button4 || event->xbutton.button == Button5 ||
+       event->xbutton.button == Button6 || event->xbutton.button == Button7))
+  {
+    gltrackball_mousewheel(cp->trackball,
+        event->xbutton.button, 5, !!event->xbutton.state);
+    return True;
+  }
+  else if(event->xany.type == MotionNotify && cp->button_down)
+  {
+    gltrackball_track(cp->trackball, event->xmotion.x, event->xmotion.y,
+        MI_WIDTH (mi), MI_HEIGHT (mi));
+    return True;
+  }
+  return False;
+}
+
+
+XSCREENSAVER_MODULE ("RubikBlocks", rubikblocks)
+
+#endif
diff --git a/hacks/glx/rubikblocks.man b/hacks/glx/rubikblocks.man
new file mode 100644 (file)
index 0000000..c18d18f
--- /dev/null
@@ -0,0 +1,117 @@
+.TH XScreenSaver 1 "04-Feb-09" "X Version 11"
+.SH NAME
+rubikblocks - animates the Rubik's Mirror Blocks puzzle
+.SH SYNOPSIS
+.B rubikblocks
+[\-display \fIhost:display.screen\fP]
+[\-visual \fIvisual\fP]
+[\-window]
+[\-root]
+[\-install]
+[\-delay \fImicroseconds\fP]
+[\-texture] [\-no\-texture]
+[\-mono]
+[\-wireframe]
+[\-spin] [\-no\-spin]
+[\-wander] [\-no\-wander]
+[\-randomize] [\-no\-randomize]
+[\-spinspeed \fInumber\fP]
+[\-rotspeed \fInumber\fP]
+[\-wanderspeed \fInumber\fP]
+[\-wait \fInumber\fP]
+[\-cubesize \fInumber\fP]
+[\-fps]
+.SH DESCRIPTION
+This program animates a puzzle called Rubik's Mirror Blocks.
+The moves are chosen randomly.
+.SH OPTIONS
+.I rubikblocks
+accepts the following options:
+.TP 8
+.B \-window
+Draw on a newly-created window.  This is the default.
+.TP 8
+.B \-root
+Draw on the root window.
+.TP 8
+.B \-install
+Install a private colormap for the window.
+.TP 8
+.B \-visual \fIvisual\fP\fP
+Specify which visual to use.  Legal values are the name of a visual class,
+or the id number (decimal or hex) of a specific visual.
+.TP 8
+.B \-delay \fImicroseconds\fP
+How long to pause between frames.  Default is 20000, or 0.02 second.
+.TP 8
+.B \-texture
+Use texture maps.  This is the default.
+.TP 8
+.B \-no\-texture
+Use solid colors.  Looks a bit weird.
+.TP 8
+.B \-mono
+Disable both texture maps and colors.  Ditto.
+.TP 8
+.B \-wireframe
+Only draw outlines.  Outlines of each piece, not only the whole object, are drawn.
+.TP 8
+.B \-spin
+Spin the whole object around X, Y and Z axes.  This is the default.
+.TP 8
+.B \-no\-spin
+Do not spin, stay in the same tilt all the time.
+.TP 8
+.B \-wander
+Move the object around the screen.  This is the default.
+.TP 8
+.B \-no\-wander
+Keep the object centered on the screen.
+.TP 8
+.B \-randomize
+Shuffle the puzzle randomly at startup.  This is the default.
+.TP 8
+.B \-no\-randomize
+Do not shuffle at startup, begin at the shape of cube.
+.TP 8
+.B \-spinspeed \fInumber\fP
+The relative speed of spinning.  Default is 1.0.
+.TP 8
+.B \-rotspeed \fInumber\fP
+The relative speed of the moves.  Default is 3.0.  Setting to \(<= 0.0
+makes the object stay at one configuration.
+.TP 8
+.B \-wanderspeed \fInumber\fP
+The relative speed of wandering around the screen.  Default is 0.02.
+.TP 8
+.B \-wait \fInumber\fP
+How long to stay at final position after each move.  The meaning of
+the argument is again relative.  Default is 40.0.
+.TP 8
+.B \-cubesize \fInumber\fP
+Size of the object.  Value of 3.0 fills roughly all the screen.
+.TP 8
+.B \-fps
+Display the current frame rate, CPU load, and polygon count.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1)
+.SH COPYRIGHT
+Copyright \(co 2009 by Vasek Potocek.  Permission to use, copy, modify, 
+distribute, and sell this software and its documentation for any purpose is 
+hereby granted without fee, provided that the above copyright notice appear 
+in all copies and that both that copyright notice and this permission notice
+appear in supporting documentation.  No representations are made about the 
+suitability of this software for any purpose.  It is provided "as is" without
+express or implied warranty.
+.SH AUTHOR
+Vasek Potocek <vasek.potocek@post.cz>, 04-Feb-09.
index b389f5e2ec700ce1c8d8aeedb0efcb867cf001d0..8957c1924ea15b2f52756f2d90623107f5debcf9 100644 (file)
@@ -1,4 +1,4 @@
-/* sonar, Copyright (c) 1998-2008 Jamie Zawinski and Stephen Martin
+/* sonar, Copyright (c) 1998-2009 Jamie Zawinski and Stephen Martin
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
@@ -205,11 +205,30 @@ resolve_bogie_hostname (ping_data *pd, sonar_bogie *sb, Bool resolve_p)
           strlen (sb->name) >= 80)
         return 0;
 
+      /* .ssh/known_hosts sometimes contains weirdness like "[host]:port".
+         Ignore it. */
+      if (strchr (sb->name, '['))
+        {
+          if (pd->debug_p)
+            fprintf (stderr, "%s:   ignoring bogus address \"%s\"\n", 
+                     progname, sb->name);
+          return 0;
+        }
+
+      /* If the name contains a colon, it's probably IPv6. */
+      if (strchr (sb->name, ':'))
+        {
+          if (pd->debug_p)
+            fprintf (stderr, "%s:   ignoring ipv6 address \"%s\"\n", 
+                     progname, sb->name);
+          return 0;
+        }
+
       hent = gethostbyname (sb->name);
       if (!hent)
         {
           if (pd->debug_p)
-            fprintf (stderr, "%s: could not resolve host:  %s\n",
+            fprintf (stderr, "%s:   could not resolve host:  %s\n",
                      progname, sb->name);
           return 0;
         }
@@ -327,7 +346,7 @@ read_hosts_file (sonar_sensor_data *ssd, const char *filename)
   if (!fp)
     {
       char buf[1024];
-      sprintf(buf, "%s: %s", progname, filename);
+      sprintf(buf, "%s:  %s", progname, filename);
 #ifdef HAVE_COCOA
       if (pd->debug_p)  /* on OSX don't syslog this */
 #endif
index 535b52fea5599ea0d014ada3804e7638a2b7a5d1..cdafdef5d0f4dd349047fcf7fae5a79c1993d257 100644 (file)
@@ -236,6 +236,9 @@ draw_screen (ModeInfo *mi, Bool mesh_p, Bool sweep_p)
 
       r0 = i     / (GLfloat) r_steps;
       r1 = (i+1) / (GLfloat) r_steps;
+
+      if (r1 > 1) r1 = 1; /* avoid asin lossage */
+
       z0 = cos (curvature/2 * asin (r0)) / 2 - zoff;
       z1 = cos (curvature/2 * asin (r1)) / 2 - zoff;
 
diff --git a/hacks/glx/surfaces.c b/hacks/glx/surfaces.c
new file mode 100644 (file)
index 0000000..459d122
--- /dev/null
@@ -0,0 +1,680 @@
+/* Surface --- Parametric 3d surfaces visualization */
+
+/*
+ * Revision History:
+ * 2000: written by Andrey Mirtchovski <mirtchov@cpsc.ucalgary.ca>
+ *       
+ * 01-Mar-2003  mirtchov    Modified as a xscreensaver hack.
+ * 01-jan-2009  steger      Renamed from klein.c to surfaces.c.
+ *                          Removed the Klein bottle.
+ *                          Added many new surfaces.
+ *                          Added many command line options.
+ *
+ */
+
+/* surfaces to draw */
+#define SURFACE_RANDOM            -1
+#define SURFACE_DINI              0
+#define SURFACE_ENNEPER           1
+#define SURFACE_KUEN              2
+#define SURFACE_MOEBIUS           3
+#define SURFACE_SEASHELL          4
+#define SURFACE_SWALLOWTAIL       5
+#define SURFACE_BOHEMIAN          6
+#define SURFACE_WHITNEY           7
+#define SURFACE_PLUECKER          8
+#define SURFACE_HENNEBERG         9
+#define SURFACE_CATALAN           10
+#define SURFACE_CORKSCREW         11
+#define NUM_SURFACES              12
+
+/* primitives to draw with 
+ * note that we skip the polygons and
+ * triangle fans -- too slow
+ *
+ * also removed triangle_strip and quads -- 
+ * just doesn't look good enough
+ */
+#define RENDER_RANDOM             -1
+#define RENDER_POINTS             0
+#define RENDER_LINES              1
+#define RENDER_LINE_LOOP          2
+#define NUM_RENDER                3
+
+#ifdef STANDALONE
+# define DEFAULTS                   "*delay:        20000   \n" \
+                                    "*showFPS:      False   \n"
+
+# define refresh_surface 0
+# include "xlockmore.h"     /* from the xscreensaver distribution */
+#else  /* !STANDALONE */
+# include "xlock.h"         /* from the xlockmore distribution */
+#endif /* !STANDALONE */
+
+#ifdef USE_GL
+
+#define DEF_SURFACE      "random"
+#define DEF_MODE         "random"
+#define DEF_SPIN         "True"
+#define DEF_WANDER       "False"
+#define DEF_SPEED        "300"
+
+#include "rotator.h"
+#include "gltrackball.h"
+
+#undef countof
+#define countof(x) (sizeof((x))/sizeof((*x)))
+
+
+static char *surface_type;
+static char *render_mode;
+static int render;
+static int speed;
+static Bool do_spin;
+static Bool do_wander;
+
+static XrmOptionDescRec opts[] = {
+  { "-surface",        ".surface", XrmoptionSepArg, 0 },
+  { "-random-surface", ".surface", XrmoptionNoArg,  "random" },
+  { "-dini",           ".surface", XrmoptionNoArg,  "dini" },
+  { "-enneper",        ".surface", XrmoptionNoArg,  "enneper" },
+  { "-kuen",           ".surface", XrmoptionNoArg,  "kuen" },
+  { "-moebius",        ".surface", XrmoptionNoArg,  "moebius" },
+  { "-seashell",       ".surface", XrmoptionNoArg,  "seashell" },
+  { "-swallowtail",    ".surface", XrmoptionNoArg,  "swallowtail" },
+  { "-bohemian",       ".surface", XrmoptionNoArg,  "bohemian" },
+  { "-whitney",        ".surface", XrmoptionNoArg,  "whitney" },
+  { "-pluecker",       ".surface", XrmoptionNoArg,  "pluecker" },
+  { "-henneberg",      ".surface", XrmoptionNoArg,  "henneberg" },
+  { "-catalan",        ".surface", XrmoptionNoArg,  "catalan" },
+  { "-corkscrew",      ".surface", XrmoptionNoArg,  "corkscrew" },
+  { "-mode",           ".mode",    XrmoptionSepArg, 0 },
+  { "-random-mode",    ".mode",    XrmoptionNoArg,  "random" },
+  { "-points",         ".mode",    XrmoptionNoArg,  "points" },
+  { "-lines",          ".mode",    XrmoptionNoArg,  "lines" },
+  { "-line-loops",     ".mode",    XrmoptionNoArg,  "line-loops" },
+  { "-speed",          ".speed",   XrmoptionSepArg, 0 },
+  { "-spin",           ".spin",    XrmoptionNoArg, "True" },
+  { "+spin",           ".spin",    XrmoptionNoArg, "False" },
+  { "-wander",         ".wander",  XrmoptionNoArg, "True" },
+  { "+wander",         ".wander",  XrmoptionNoArg, "False" },
+};
+
+static argtype vars[] = {
+  {&surface_type, "surface", "Surface", DEF_SURFACE, t_String },
+  {&render_mode,  "mode",    "Mode",    DEF_MODE,    t_String },
+  {&do_spin,      "spin",    "Spin",    DEF_SPIN,    t_Bool },
+  {&do_wander,    "wander",  "Wander",  DEF_WANDER,  t_Bool },
+  {&speed,        "speed",   "Speed",   DEF_SPEED,   t_Int },
+};
+
+
+ENTRYPOINT ModeSpecOpt surface_opts =
+{countof(opts), opts, countof(vars), vars, NULL};
+
+
+
+typedef struct {
+  GLfloat x;
+  GLfloat y;
+  GLfloat z;
+} GL_VECTOR;
+
+typedef struct {
+  GLXContext *glx_context;
+  Window      window;
+  rotator    *rot;
+  trackball_state *trackball;
+  Bool        button_down_p;
+
+  int  render;
+  Bool random_render;
+  int  surface;
+  Bool random_surface;
+  int  frame;
+
+  float du, dv;
+  float a, b, c;
+
+  float draw_step;
+} surfacestruct;
+
+static surfacestruct *surface = NULL;
+
+
+static void draw(ModeInfo *mi)
+{
+  surfacestruct *sp = &surface[MI_SCREEN(mi)];
+  double u, v;
+  float coord[3];
+  int render;
+
+  mi->polygon_count = 0;
+  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+  glEnable(GL_DEPTH_TEST);
+  glEnable(GL_NORMALIZE);
+  glEnable(GL_CULL_FACE);
+
+  glPushMatrix();
+
+  {
+    double x, y, z;
+    get_position(sp->rot, &x, &y, &z, !sp->button_down_p);
+    glTranslatef((x-0.5)*10, (y-0.5)*10, (z-0.5)*20);
+
+    gltrackball_rotate(sp->trackball);
+
+    get_rotation(sp->rot, &x, &y, &z, !sp->button_down_p);
+    glRotatef(x*360, 1.0, 0.0, 0.0);
+    glRotatef(y*360, 0.0, 1.0, 0.0);
+    glRotatef(z*360, 0.0, 0.0, 1.0);
+  }
+
+  glScalef(4.0, 4.0, 4.0);
+
+  switch(sp->surface)
+  {
+    case SURFACE_DINI:
+      for (v=0.11; v<=2.0; v+=sp->dv)
+      {
+        glBegin(sp->render);
+        for (u=0; u<=6.0*M_PI; u+=sp->du)
+        {
+          coord[0] = sp->a*cos(u)*sin(v);
+          coord[1] = sp->a*sin(u)*sin(v);
+          coord[2] = sp->a*(cos(v)+log(tan(0.5*v)))+0.2*sp->b*u;
+          glColor3f(coord[0]+0.7, coord[1]+0.7, coord[2]+0.7);
+          glVertex3fv(coord);
+          mi->polygon_count++;
+        }
+        glEnd();
+      }
+      break;
+    case SURFACE_ENNEPER:
+      for (u=-M_PI; u<=M_PI; u+=sp->du)
+      {
+        glBegin(sp->render);
+        for (v=-M_PI; v<M_PI; v+=sp->dv)
+        {
+          coord[0] = sp->a*(u-(1.0/3.0*u*u*u)+u*v*v);
+          coord[1] = sp->b*(v-(1.0/3.0*v*v*v)+u*u*v);
+          coord[2] = u*u-v*v;
+          glColor3f(coord[0]+0.7, coord[1]+0.7, coord[2]+0.7);
+          glVertex3fv(coord);
+          mi->polygon_count++;
+        }
+        glEnd();
+      }
+      break;
+    case SURFACE_KUEN:
+      for (u=-4.48; u<=4.48; u+=sp->du)
+      {
+        glBegin(sp->render);
+        for (v=M_PI/51; v<M_PI; v+=sp->dv)
+        {
+          coord[0] = 2*(cos(u)+u*sin(u))*sin(v)/(1+u*u*sin(v)*sin(v));
+          coord[1] = 2*(sin(u)-u*cos(u))*sin(v)/(1+u*u*sin(v)*sin(v));
+          coord[2] = log(tan(0.5*v))+2*cos(v)/(1+u*u*sin(v)*sin(v));
+          glColor3f(coord[0]+0.7, coord[1]+0.7, coord[2]+0.7);
+          glVertex3fv(coord);
+          mi->polygon_count++;
+        }
+        glEnd();
+      }
+      break;
+    case SURFACE_MOEBIUS:
+      for (u=-M_PI; u<M_PI; u+=sp->du)
+      {
+        glBegin(sp->render);
+        for (v=-0.735; v<0.74; v+=sp->dv)
+        {
+          coord[0] = cos(u)+v*cos(u/2)*cos(u);
+          coord[1] = sin(u)+v*cos(u/2)*sin(u);
+          coord[2] = v*sin(u/2);
+          glColor3f(coord[0]+0.7, coord[1]+0.7, coord[2]+0.7);
+          glVertex3fv(coord);
+          mi->polygon_count++;
+        }
+        glEnd();
+      }
+      break;
+    case SURFACE_SEASHELL:
+      for (u=0; u<2*M_PI; u+=sp->du)
+      {
+        glBegin(sp->render);
+        for (v=0; v<2*M_PI; v+=sp->dv)
+        {
+          coord[0] = sp->a*(1-v/(2*M_PI))*cos(2*v)*(1+cos(u))+sp->c*cos(2*v);
+          coord[1] = sp->a*(1-v/(2*M_PI))*sin(2*v)*(1+cos(u))+sp->c*sin(2*v);
+          coord[2] = 2*sp->b*v/(2*M_PI)+sp->a*(1-v/(2*M_PI))*sin(u);
+          glColor3f(coord[0]+0.7, coord[1]+0.7, coord[2]+0.7);
+          glVertex3fv(coord);
+          mi->polygon_count++;
+        }
+        glEnd();
+      }
+      break;
+    case SURFACE_SWALLOWTAIL:
+      for (u=-2.5; u<2.0; u+=sp->du)
+      {
+        glBegin(sp->render);
+        for (v=-1.085; v<1.09; v+=sp->dv)
+        {
+          coord[0] = u*v*v+3*v*v*v*v;
+          coord[1] = -2*u*v-4*v*v*v;
+          coord[2] = u;
+          glColor3f(coord[0]+0.7, coord[1]+0.7, coord[2]+0.7);
+          glVertex3fv(coord);
+          mi->polygon_count++;
+        }
+        glEnd();
+      }
+      break;
+    case SURFACE_BOHEMIAN:
+      for (u=-M_PI; u<M_PI; u+=sp->du)
+      {
+        glBegin(sp->render);
+        for (v=-M_PI; v<M_PI; v+=sp->dv)
+        {
+          coord[0] = sp->a*cos(u);
+          coord[1] = sp->b*cos(v)+sp->a*sin(u);
+          coord[2] = sin(v);
+          glColor3f(coord[0]+0.7, coord[1]+0.7, coord[2]+0.7);
+          glVertex3fv(coord);
+          mi->polygon_count++;
+        }
+        glEnd();
+      }
+      break;
+    case SURFACE_WHITNEY:
+      for (v=-1.995; v<2.0; v+=sp->dv)
+      {
+        glBegin(sp->render);
+        for (u=-1.995; u<2.0; u+=sp->du)
+        {
+          coord[0] = u*v;
+          coord[1] = u;
+          coord[2] = v*v-2;
+          glColor3f(coord[0]+0.7, coord[1]+0.7, coord[2]+0.7);
+          glVertex3fv(coord);
+          mi->polygon_count++;
+        }
+        glEnd();
+      }
+      break;
+    case SURFACE_PLUECKER:
+      for (u=0; u<2.5; u+=sp->dv)
+      {
+        glBegin(sp->render);
+        for (v=-M_PI; v<M_PI; v+=sp->du)
+        {
+          coord[0] = u*cos(v);
+          coord[1] = u*sin(v);
+          coord[2] = 2*cos(v)*sin(v);
+          glColor3f(coord[0]+0.7, coord[1]+0.7, coord[2]+0.7);
+          glVertex3fv(coord);
+          mi->polygon_count++;
+        }
+        glEnd();
+      }
+      break;
+    case SURFACE_HENNEBERG:
+      for (u=0.9; u<2.55; u+=sp->dv)
+      {
+        glBegin(sp->render);
+        for (v=-M_PI; v<M_PI; v+=sp->du)
+        {
+          coord[0] = sinh(1.0/3.0*u)*cos(v)-1.0/3.0*sinh(u)*cos(3.0*v);
+          coord[1] = sinh(1.0/3.0*u)*sin(v)+1.0/3.0*sinh(u)*sin(3.0*v);
+          coord[2] = cosh(2.0/3.0*u)*cos(2.0*v);
+          glColor3f(coord[0]+0.7, coord[1]+0.7, coord[2]+0.7);
+          glVertex3fv(coord);
+          mi->polygon_count++;
+        }
+        glEnd();
+      }
+      break;
+    case SURFACE_CATALAN:
+      for (v=-2; v<2; v+=sp->du)
+      {
+        glBegin(sp->render);
+        for (u=-2*M_PI; u<2*M_PI+0.05; u+=sp->dv)
+        {
+          coord[0] = 0.33*(u-sin(u)*cosh(v));
+          coord[1] = 0.33*(1.0-cos(u)*cosh(v));
+          coord[2] = 0.33*4.0*sin(0.5*u)*sinh(0.5*v);
+          glColor3f(coord[0]+0.7, coord[1]+0.7, coord[2]+0.7);
+          glVertex3fv(coord);
+          mi->polygon_count++;
+        }
+        glEnd();
+      }
+      break;
+    case SURFACE_CORKSCREW:
+      for (v=-M_PI; v<M_PI; v+=sp->du)
+      {
+        glBegin(sp->render);
+        for (u=-M_PI; u<M_PI; u+=sp->dv)
+        {
+          coord[0] = 0.5*(sp->a+2.0)*cos(u)*cos(v);
+          coord[1] = 0.5*(sp->a+2.0)*sin(u)*cos(v);
+          coord[2] = 0.5*(sp->a+2.0)*sin(v)+u;
+          glColor3f(coord[0]+0.7, coord[1]+0.7, coord[2]+0.7);
+          glVertex3fv(coord);
+          mi->polygon_count++;
+        }
+        glEnd();
+      }
+      break;
+  }
+  glPopMatrix();
+
+  if (sp->render == GL_LINES)
+    mi->polygon_count /= 2;
+
+  sp->a = sin(sp->draw_step+=0.01);
+  sp->b = cos(sp->draw_step+=0.01);
+  sp->c = sin(sp->draw_step+0.25*M_PI);
+
+  if (sp->random_surface || sp->random_render)
+  {
+    sp->frame++;
+    if (sp->frame >= speed)
+    {
+      sp->frame = 0;
+      if (sp->random_surface)
+        sp->surface = random() % NUM_SURFACES;
+      if (sp->random_render)
+      {
+        render = random() % NUM_RENDER;
+        switch (render)
+        {
+          case RENDER_POINTS:
+            sp->render = GL_POINTS;
+            break;
+          case RENDER_LINES:
+            sp->render = GL_LINES;
+            break;
+          case RENDER_LINE_LOOP:
+            if (sp->surface == SURFACE_BOHEMIAN ||
+                sp->surface == SURFACE_PLUECKER ||
+                sp->surface == SURFACE_HENNEBERG)
+              sp->render = GL_LINE_LOOP;
+            else
+              sp->render = GL_LINE_STRIP;
+            break;
+          default:
+            sp->render = GL_LINE_LOOP;
+            break;
+        }
+      }
+    }
+  }
+}
+
+
+/* new window size or exposure */
+ENTRYPOINT void reshape_surface(ModeInfo *mi, int width, int height)
+{
+  GLfloat h = (GLfloat) height / (GLfloat) width;
+
+  glViewport(0, 0, (GLint) width, (GLint) height);
+  glMatrixMode(GL_PROJECTION);
+  glLoadIdentity();
+  gluPerspective (30.0, 1/h, 1.0, 100.0);
+
+  glMatrixMode(GL_MODELVIEW);
+  glLoadIdentity();
+  gluLookAt(0.0, 0.0, 30.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
+    
+  glClear(GL_COLOR_BUFFER_BIT);
+}
+
+
+ENTRYPOINT Bool surface_handle_event(ModeInfo *mi, XEvent *event)
+{
+  surfacestruct *sp = &surface[MI_SCREEN(mi)];
+
+  if (event->xany.type == ButtonPress && event->xbutton.button == Button1)
+  {
+    sp->button_down_p = True;
+    gltrackball_start(sp->trackball, event->xbutton.x, event->xbutton.y,
+                      MI_WIDTH (mi), MI_HEIGHT (mi));
+    return True;
+  }
+  else if (event->xany.type == ButtonRelease &&
+           event->xbutton.button == Button1)
+  {
+    sp->button_down_p = False;
+    return True;
+  }
+  else if (event->xany.type == ButtonPress &&
+           (event->xbutton.button == Button4 ||
+            event->xbutton.button == Button5 ||
+            event->xbutton.button == Button6 ||
+            event->xbutton.button == Button7)) {
+    gltrackball_mousewheel(sp->trackball, event->xbutton.button, 10,
+                           !!event->xbutton.state);
+    return True;
+  }
+  else if (event->xany.type == MotionNotify && sp->button_down_p)
+  {
+    gltrackball_track (sp->trackball, event->xmotion.x, event->xmotion.y,
+                       MI_WIDTH (mi), MI_HEIGHT (mi));
+    return True;
+  }
+
+  return False;
+}
+
+
+ENTRYPOINT void init_surface(ModeInfo *mi)
+{
+  int    screen = MI_SCREEN(mi);
+  surfacestruct *sp;
+
+  if (surface == NULL)
+  {
+    if ((surface = (surfacestruct *) calloc(MI_NUM_SCREENS(mi),
+                                            sizeof(surfacestruct))) == NULL)
+      return;
+  }
+  sp = &surface[screen];
+
+  sp->window = MI_WINDOW(mi);
+
+  {
+    double spin_speed    = 1.0;
+    double wander_speed = 0.03;
+    sp->rot = make_rotator(do_spin ? spin_speed : 0,
+                           do_spin ? spin_speed : 0,
+                           do_spin ? spin_speed : 0,
+                           1.0,
+                           do_wander ? wander_speed : 0,
+                           True);
+    sp->trackball = gltrackball_init ();
+  }
+
+  if (!strcasecmp(surface_type,"random"))
+  {
+    sp->random_surface = True;
+    sp->surface = random() % NUM_SURFACES;
+  }
+  else if (!strcasecmp(surface_type,"dini"))
+  {
+    sp->random_surface = False;
+    sp->surface = SURFACE_DINI;
+  }
+  else if (!strcasecmp(surface_type,"enneper"))
+  {
+    sp->random_surface = False;
+    sp->surface = SURFACE_ENNEPER;
+  }
+  else if (!strcasecmp(surface_type,"kuen"))
+  {
+    sp->random_surface = False;
+    sp->surface = SURFACE_KUEN;
+  }
+  else if (!strcasecmp(surface_type,"moebius"))
+  {
+    sp->random_surface = False;
+    sp->surface = SURFACE_MOEBIUS;
+  }
+  else if (!strcasecmp(surface_type,"seashell"))
+  {
+    sp->random_surface = False;
+    sp->surface = SURFACE_SEASHELL;
+  }
+  else if (!strcasecmp(surface_type,"swallowtail"))
+  {
+    sp->random_surface = False;
+    sp->surface = SURFACE_SWALLOWTAIL;
+  }
+  else if (!strcasecmp(surface_type,"bohemian"))
+  {
+    sp->random_surface = False;
+    sp->surface = SURFACE_BOHEMIAN;
+  }
+  else if (!strcasecmp(surface_type,"whitney"))
+  {
+    sp->random_surface = False;
+    sp->surface = SURFACE_WHITNEY;
+  }
+  else if (!strcasecmp(surface_type,"pluecker"))
+  {
+    sp->random_surface = False;
+    sp->surface = SURFACE_PLUECKER;
+  }
+  else if (!strcasecmp(surface_type,"henneberg"))
+  {
+    sp->random_surface = False;
+    sp->surface = SURFACE_HENNEBERG;
+  }
+  else if (!strcasecmp(surface_type,"catalan"))
+  {
+    sp->random_surface = False;
+    sp->surface = SURFACE_CATALAN;
+  }
+  else if (!strcasecmp(surface_type,"corkscrew"))
+  {
+    sp->random_surface = False;
+    sp->surface = SURFACE_CORKSCREW;
+  }
+  else
+  {
+    sp->random_surface = True;
+    sp->surface = random() % NUM_SURFACES;
+  }
+
+  if (!strcasecmp(render_mode,"random"))
+  {
+    sp->random_render = True;
+    render = random() % NUM_RENDER;
+  }
+  else if (!strcasecmp(render_mode,"points"))
+  {
+    sp->random_render = False;
+    render = RENDER_POINTS;
+  }
+  else if (!strcasecmp(render_mode,"lines"))
+  {
+    sp->random_render = False;
+    render = RENDER_LINES;
+  }
+  else if (!strcasecmp(render_mode,"line-loops"))
+  {
+    sp->random_render = False;
+    render = RENDER_LINE_LOOP;
+  }
+  else
+  {
+    sp->random_render = True;
+    render = random() % NUM_RENDER;
+  }
+
+  switch (render)
+  {
+    case RENDER_POINTS:
+      sp->render = GL_POINTS;
+      break;
+    case RENDER_LINES:
+      sp->render = GL_LINES;
+      break;
+    case RENDER_LINE_LOOP:
+      if (sp->surface == SURFACE_BOHEMIAN ||
+          sp->surface == SURFACE_PLUECKER ||
+          sp->surface == SURFACE_HENNEBERG)
+        sp->render = GL_LINE_LOOP;
+      else
+        sp->render = GL_LINE_STRIP;
+      break;
+    default:
+      sp->render = GL_LINE_LOOP;
+      break;
+  }
+
+  sp->frame = 0;
+
+  sp->du = 0.07;
+  sp->dv = 0.07;
+  sp->a = sp->b = 1;
+  sp->c = 0.1;
+
+  if ((sp->glx_context = init_GL(mi)) != NULL)
+  {
+    reshape_surface(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
+  }
+  else
+  {
+    MI_CLEARWINDOW(mi);
+  }
+}
+
+
+ENTRYPOINT void draw_surface(ModeInfo * mi)
+{
+  surfacestruct *sp = &surface[MI_SCREEN(mi)];
+  Display *display = MI_DISPLAY(mi);
+  Window window = MI_WINDOW(mi);
+
+  if (!sp->glx_context)
+    return;
+
+  glDrawBuffer(GL_BACK);
+
+  glXMakeCurrent(display, window, *(sp->glx_context));
+  draw(mi);
+  if (mi->fps_p)
+    do_fps(mi);
+  glFinish();
+  glXSwapBuffers(display, window);
+}
+
+
+ENTRYPOINT void release_surface(ModeInfo * mi)
+{
+  if (surface != NULL)
+  {
+    int  screen;
+
+    for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
+    {
+      surfacestruct *sp = &surface[screen];
+
+      if (sp->glx_context)
+      {
+        /* Display lists MUST be freed while their glXContext is current. */
+        glXMakeCurrent(MI_DISPLAY(mi), sp->window, *(sp->glx_context));
+      }
+    }
+    (void) free((void *)surface);
+    surface = NULL;
+  }
+  FreeAllGL(mi);
+}
+
+
+XSCREENSAVER_MODULE_2("Surfaces", surfaces, surface)
+
+#endif
diff --git a/hacks/glx/surfaces.man b/hacks/glx/surfaces.man
new file mode 100644 (file)
index 0000000..4c62a0e
--- /dev/null
@@ -0,0 +1,127 @@
+.TH XScreenSaver 1 "" "X Version 11"
+.SH NAME
+surfaces - Draws some interesting 3d parametric surfaces.
+.SH SYNOPSIS
+.B surfaces
+[\-display \fIhost:display.screen\fP]
+[\-visual \fIvisual\fP]
+[\-window]
+[\-root]
+[\-speed \fInumber\fP]
+[\-rand]
+[\-spin]
+[\-wander]
+[\-fps]
+[\-surface \fIsurface-name\fP]
+[\-random-surface]
+[\-dini]
+[\-enneper]
+[\-kuen]
+[\-moebius]
+[\-seashell]
+[\-swallowtail]
+[\-bohemian]
+[\-whitney]
+[\-pluecker]
+[\-henneberg]
+[\-catalan]
+[\-corkscrew]
+[\-mode \fIdisplay-mode\fP]
+[\-random-mode]
+[\-points]
+[\-lines]
+[\-line-loops]
+.SH DESCRIPTION
+This draws one of several three dimensional parametric surfaces.
+.SH OPTIONS
+.TP 8
+.B \-visual \fIvisual\fP
+Specify which visual to use.  Legal values are the name of a visual
+class, or the id number (decimal or hex) of a specific visual.
+.TP 8
+.B \-window
+Draw on a newly-created window.  This is the default.
+.TP 8
+.B \-root
+Draw on the root window.
+.TP 8
+.B \-delay \fInumber\fP
+Per-frame delay, in microseconds.  Default: 20000 (0.02 seconds.).
+.TP 8
+.B \-speed \fInumber\fP
+Number of frames before changing shape.  Default: 1000.
+.TP 8
+.B \-surface random \fP(Shortcut: \fB\-random-surface\fP)
+Display a random surface.  This is the default.
+.TP 8
+.B \-surface dini \fP(Shortcut: \fB\-dini\fP)
+Display Dini's surface.
+.TP 8
+.B \-surface enneper \fP(Shortcut: \fB\-enneper\fP)
+Display Enneper's minimal surface.
+.TP 8
+.B \-surface kuen \fP(Shortcut: \fB\-kuen\fP)
+Display the Kuen surface.
+.TP 8
+.B \-surface moebius \fP(Shortcut: \fB\-moebius\fP)
+Display the Moebius strip.
+.TP 8
+.B \-surface seashell \fP(Shortcut: \fB\-seashell\fP)
+Display the seashell surface.
+.TP 8
+.B \-surface swallowtail \fP(Shortcut: \fB\-swallowtail\fP)
+Display the swallowtail catastrophe.
+.TP 8
+.B \-surface bohemian \fP(Shortcut: \fB\-bohemian\fP)
+Display the Bohemian dome.
+.TP 8
+.B \-surface whitney \fP(Shortcut: \fB\-whitney\fP)
+Display the Whitney umbrella.
+.TP 8
+.B \-surface pluecker \fP(Shortcut: \fB\-pluecker\fP)
+Display Pluecker's conoid.
+.TP 8
+.B \-surface henneberg \fP(Shortcut: \fB\-henneberg\fP)
+Display Henneberg's minimal surface.
+.TP 8
+.B \-surface catalan \fP(Shortcut: \fB\-catalan\fP)
+Display Catalan's minimal surface.
+.TP 8
+.B \-surface corkscrew \fP(Shortcut: \fB\-corkscrew\fP)
+Display the corkscrew surface.
+.TP 8
+.B \-mode random \fP(Shortcut: \fB\-random-mode\fP)
+Use random OpenGL primitives to display the surface.  This is the
+default.
+.TP 8
+.B \-mode points \fP(Shortcut: \fB\-points\fP)
+Use OpenGL points to display the surface.
+.TP 8
+.B \-mode lines \fP(Shortcut: \fB\-lines\fP)
+Use OpenGL lines to display the surface.
+.TP 8
+.B \-mode line-loops \fP(Shortcut: \fB\-line-loops\fP)
+Use OpenGL line loops to display the surface.
+.TP 8
+.B \-wander | \-no-wander
+Whether to wander around the screen.
+.TP 8
+.B \-spin | \-no-spin
+Whether to rotate around the center of the figure.
+.TP 8
+.B \-fps
+Display the current frame rate, CPU load, and polygon count.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1)
+.SH AUTHORS
+Andrey Mirtchovski, Carsten Steger
index 15822a4924369e413f705366139277219e92fdec..6a593d03786a43060fe665f2b30065eb0524505c 100644 (file)
@@ -257,13 +257,13 @@ load_texture_font (Display *dpy, char *res)
 
           /* See comment in print_texture_string for bit layout explanation.
            */
-          int lbearing = (f->per_char
+          int lbearing = (f->per_char && ii >= f->min_char_or_byte2
                           ? f->per_char[ii - f->min_char_or_byte2].lbearing
                           : f->min_bounds.lbearing);
-          int ascent   = (f->per_char
+          int ascent   = (f->per_char && ii >= f->min_char_or_byte2
                           ? f->per_char[ii - f->min_char_or_byte2].ascent
                           : f->max_bounds.ascent);
-          int width    = (f->per_char
+          int width    = (f->per_char && ii >= f->min_char_or_byte2
                           ? f->per_char[ii - f->min_char_or_byte2].width
                           : f->max_bounds.width);
 
@@ -334,7 +334,7 @@ texture_string_width (texture_font_data *data, const char *c,
   while (*c)
     {
       int cc = *((unsigned char *) c);
-      w += (f->per_char
+      w += (f->per_char && cc >= f->min_char_or_byte2
             ? f->per_char[cc-f->min_char_or_byte2].width
             : f->max_bounds.width);
       c++;
@@ -430,19 +430,19 @@ print_texture_string (texture_font_data *data, const char *string)
              We want to make a quad from point A to point C.
              We want to position that quad so that point B lies at x,y.
            */
-          int lbearing = (f->per_char
+          int lbearing = (f->per_char && c >= f->min_char_or_byte2
                           ? f->per_char[c - f->min_char_or_byte2].lbearing
                           : f->min_bounds.lbearing);
-          int rbearing = (f->per_char
+          int rbearing = (f->per_char && c >= f->min_char_or_byte2
                           ? f->per_char[c - f->min_char_or_byte2].rbearing
                           : f->max_bounds.rbearing);
-          int ascent   = (f->per_char
+          int ascent   = (f->per_char && c >= f->min_char_or_byte2
                           ? f->per_char[c - f->min_char_or_byte2].ascent
                           : f->max_bounds.ascent);
-          int descent  = (f->per_char
+          int descent  = (f->per_char && c >= f->min_char_or_byte2
                           ? f->per_char[c - f->min_char_or_byte2].descent
                           : f->max_bounds.descent);
-          int cwidth   = (f->per_char
+          int cwidth   = (f->per_char && c >= f->min_char_or_byte2
                           ? f->per_char[c - f->min_char_or_byte2].width
                           : f->max_bounds.width);
 
index 90076fb8d64ddea0f845c9add6a29164d502ae03..ef3ca0623206e398a7b2527517e3a69dd36c0252 100644 (file)
@@ -1,4 +1,4 @@
-/* topblock, Copyright (c) 2006-2008
+/* topblock, Copyright (c) 2006-2009
  *  rednuht <topblock.xscreensaver@jumpstation.co.uk>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
@@ -231,8 +231,6 @@ init_topBlock (ModeInfo *mi)
        dropSpeed = 80/dropSpeed;
        dropSpeed = (blockHeight/dropSpeed); 
 
-  tb->glx_context = init_GL(mi);
-
   reshape_topBlock (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
   if (0==1) {
       glClearColor(1.0f, 1.0f, 1.0f, 0.5f);
index 8792a6f7c57cc71acb5464bf78d16d46c97d32e8..bbe4965e0c4b6217488916350b556f37d2cc49b4 100644 (file)
@@ -117,9 +117,7 @@ Increases viewing Z coordinate.
 .TP 8
 .B c
 Decreases viewing Z coordinate.
-..UR <address>
-.UE
-TP 8
+.TP 8
 .B f
 Increases camera location X coordinate.
 .TP 8
@@ -169,4 +167,4 @@ suitability of this software for any purpose.  It is provided "as is" without
 express or implied warranty.
 .SH AUTHOR
 rednuht <topblock.xscreensaver@jumpstation.co.uk> 
-<http://www.jumpstation.co.uk/xscreensaver/topblock/>
\ No newline at end of file
+<http://www.jumpstation.co.uk/xscreensaver/topblock/>
index 1356b25ca0c42c96c5c9af692b93273b377efdbc..2b4bbf80829e0d9a40496cb0a3d1b0dd54b9e53f 100644 (file)
@@ -1,4 +1,4 @@
-/* voronoi, Copyright (c) 2007 Jamie Zawinski <jwz@jwz.org>
+/* voronoi, Copyright (c) 2007, 2008 Jamie Zawinski <jwz@jwz.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
@@ -142,31 +142,20 @@ cone (void)
   int i;
   int faces = 64;
   GLfloat step = M_PI * 2 / faces;
-  GLfloat s2 = step/2;
-  GLfloat th;
-  GLfloat x, y, x0, y0;
-
-  glBegin(GL_TRIANGLES);
-
-  th = 0;
-  x = 1;
-  y = 0;
-  x0 = cos (s2);
-  y0 = sin (s2);
+  GLfloat th = 0;
+  GLfloat x = 1;
+  GLfloat y = 0;
 
+  glBegin(GL_TRIANGLE_FAN);
+  glVertex3f (0, 0, 1);
   for (i = 0; i < faces; i++)
     {
-      glVertex3f(0,  0, 1);
-      glVertex3f(x, y, 0);
-
+      glVertex3f (x, y, 0);
       th += step;
-      x0 = cos (th + s2);
-      y0 = sin (th + s2);
-      x  = cos (th);
-      y  = sin (th);
-
-      glVertex3f(x, y, 0);
+      x = cos (th);
+      y = sin (th);
     }
+  glVertex3f (1, 0, 0);
   glEnd();
   return faces;
 }
index d72b4ebdd4aa4ad0d4884893441d05c3e4aecec0..3f41f9bf0905658e9630411864d63d5fc85091e8 100644 (file)
@@ -118,6 +118,8 @@ init_GL(ModeInfo * mi)
       glDrawBuffer (GL_FRONT);
   }
 
+  /* Sometimes glDrawBuffer() throws "invalid op". Dunno why. Ignore. */
+  clear_gl_error ();
 
   /* GLXContext is already a pointer type.
      Why this function returns a pointer to a pointer, I have no idea...
index 4028fb3c7e069799c5a0e27f10b3e9ce295f0a9b..d2308386d6551101aecb180cbca173740c16c0dc 100644 (file)
@@ -47,7 +47,6 @@
 #define SCALE       10000  /* fixed-point math, for sub-pixel motion */
 #define DEF_COUNT   12    /* When planes and count are 0, how many blobs. */
 
-
 #define RAND(n) ((long) ((random() & 0x7fffffff) % ((long) (n))))
 #define RANDSIGN() ((random() & 1) ? 1 : -1)
 
@@ -126,7 +125,7 @@ make_blob (Display *dpy, int maxx, int maxy, int size)
   b->spline = make_spline (b->npoints);
   b->r = (long *) malloc (sizeof(*b->r) * b->npoints);
   for (i = 0; i < b->npoints; i++)
-    b->r[i] = ((random() % mid) + (mid/2)) * RANDSIGN();
+    b->r[i] = (long) ((random() % mid) + (mid/2)) * RANDSIGN();
   return b;
 }
 
diff --git a/hacks/juggle.man b/hacks/juggle.man
deleted file mode 100644 (file)
index 17ea20b..0000000
+++ /dev/null
@@ -1,181 +0,0 @@
-'\" t
-.\" ** The above line should force tbl to be used as a preprocessor **
-.TH XScreenSaver 1 "" "X Version 11"
-.SH NAME
-juggle - juggling man screen saver.
-.SH SYNOPSIS
-.B juggle
-[\-display host:display.screen ]
-[\-root ]
-[\-window ]
-[\-mono ]
-[\-install | \-noinstall ]
-[\-visual visual ]
-[\-window\-id id ]
-[\-pattern pattern ]
-[\-tail number ]
-[\-real | \-no\-real ]
-[\-describe | \-no\-describe ]
-[\-balls | \-no\-balls ]
-[\-clubs | \-no\-clubs ]
-[\-torches | \-no\-torches ]
-[\-knives | \-no\-knives ]
-[\-rings | \-no\-rings ]
-[\-bballs | \-no\-bballs ]
-[\-count count ]
-[\-cycles cycles ]
-[\-delay delay ]
-[\-ncolors ncolors ]
-[\-fps]
-.SH DESCRIPTION
-Draws a stick-man juggling various collections of objects.
-.SH OPTIONS
-.I juggle
-accepts the following options:
-.TP 8
-.B \-display host:display.screen
-X11 display to use.  Overrides
-.B DISPLAY
-environment variable.
-.TP 8
-.B \-root
-Draw on the root window.
-.TP 8
-.B \-window
-Draw on a newly-created X window.  This is the default.
-.TP 8
-.B \-mono
-Draw in monochrome.
-.TP 8
-.B \-install | \-noinstall
-Turn on/off installing colormap.
-.TP 8
-.B \-visual visual
-Specify which visual to use.  Legal values are the name of a visual class,
-or the id number (decimal or hex) of a specific visual.
-.TP 8
-.B \-window\-id id
-Draw on an already existing X window.
-.TP 8
-.B \-pattern\ \(dq pattern \(dq
-Specify juggling pattern in annotated
-.B site-swap
-notation.  In 
-.B site-swap
-notation, the "height" of each throw is given.  E.g., "3" is the height
-needed to juggle a 3\-Cascade.  Note that these sequences need to be
-chosen carefully, to avoid collisions.
-
-Annotations indicate relative hand movements or tricks:
-.TS
-cb l.
-\&\-   Inside throw (default)
-+      Outside throw
-\&=    Cross Throw
-&      Cross Catch
-x      Cross Throw and Catch
-\&_    Bounce
-.TE
-.TP 8
-.B \-pattern\ \(dq[ pattern ]\(dq
-Specify juggling pattern in annotated
-.B Adam
-notation.  Adam notation is a little harder to visualize.  Each
-integer
-.B n
-represents a cyclic permutation of (0...n).  The equivalent
-.B site-swap
-value is determined by calculating how many of the permutations it
-takes to get back to the identity.  The largest number used is the
-same as the number of objects in the pattern.  The advantage of Adam
-notation is that these sequences do not need to be chosen carefully,
-since all possible sequences are juggle-able.  Annotations are the same
-as in
-.B site-swap
-notation.
-
-For example, both of these describe a 3\-Shower:
-.IP
-.B \-pattern\ "+5 1"
-.IP
-.B \-pattern\ "[+3 1]"
-
-For further examples, see the
-.B portfolio
-list in the source code.
-.TP 8
-.B \-tail number
-Minimum Trail Length.  0 \- 100.  Default: 1.  Objects may override
-this, for example flaming torches always leave a trail.
-.TP 8
-.BR \-real | \-no\-real
-Turn on/off real-time juggling.
-.B Deprecated.
-There should be no need to turn off real-time juggling, even on slow
-systems.  Adjust speed using
-.B \-count
-above.
-.TP 8
-.BR \-describe | \-no\-describe
-Turn on/off pattern descriptions.
-.TP 8 
-.BR \-balls | \-no\-balls
-Turn on/off Balls.
-.TP 8
-.BR \-clubs | \-no\-clubs
-Turn on/off Clubs.
-.TP 8
-.BR \-torches | \-no\-torches
-Turn on/off Flaming Torches.
-.TP 8
-.BR \-knives | \-no\-knives
-Turn on/off Knives.
-.TP 8
-.BR \-rings | \-no\-rings
-Turn on/off Rings.
-.TP 8
-.BR \-bballs | \-no\-bballs
-Turn on/off Bowling Balls.
-.TP 8
-.B \-count number
-Speed. 50 \- 1000.  Default: 200.  This determines the expected time
-interval between a throw and the next catch, in milliseconds.
-.TP 8
-.B \-cycles number
-Performance Length. 50 \- 1000.  Default: 1000.  Setting this smaller
-will force the juggler to switch patterns (and objects) more often.
-.TP 8
-.B \-delay delay
-Additional delay between frames, in microseconds.  Default: 10000.
-.B Deprecated.
-Adjust speed using
-.BR \-count .
-.TP 8
-.B \-ncolors ncolors
-Maximum number of colors to use.  Default: 32.
-.TP 8
-.B \-fps
-Display the current frame rate and CPU load.
-.SH ENVIRONMENT
-.PP
-.TP 8
-.B DISPLAY
-to get the default host and display number.
-.TP 8
-.B XENVIRONMENT
-to get the name of a resource file that overrides the global resources
-stored in the RESOURCE_MANAGER property.
-.SH SEE ALSO
-.BR X (1),
-.BR xscreensaver (1)
-.SH COPYRIGHT
-Copyright \(co 1996,2000,2002,2004 by Tim Auckland.  Permission to
-use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided
-that the above copyright notice appear in all copies and that both
-that copyright notice and this permission notice appear in supporting
-documentation.  No representations are made about the suitability of
-this software for any purpose.  It is provided "as is" without express
-or implied warranty.
-.SH AUTHOR
-Tim Auckland.
index 827c94e04163d3b368b09384c3c2f5d6915bc878..e9ba541a390e27ace0b549e39c328d1b2adb889d 100644 (file)
@@ -1,6 +1,6 @@
 .TH XScreenSaver 1 "" "X Version 11"
 .SH NAME
-MetaBalls.
+MetaBalls - draws 2D metaballs
 .SH SYNOPSIS
 .B MetaBalls
 [\-display \fIhost:display.screen\fP]
index 12f923dce3b5969b4a37f5fde14f08f40a64ef05..f5089a64b897d06be35b0d58eb3fe9aa56596433 100755 (executable)
@@ -18,7 +18,7 @@ use diagnostics;
 use strict;
 
 my $progname = $0; $progname =~ s@.*/@@g;
-my $version = q{ $Revision: 1.3 $ }; $version =~ s/^[^\d]+([\d.]+).*/$1/;
+my $version = q{ $Revision: 1.4 $ }; $version =~ s/^[^\d]+([\d.]+).*/$1/;
 
 my $verbose = 0;
 
@@ -85,8 +85,10 @@ sub parse_makefiles() {
     close IN;
 
     $body =~ s/\\\n//gs;
-    my ($var) = ($body =~ m/^RETIRED_EXES\s*=\s*(.*)$/mi);
+    my ($var)  = ($body =~ m/^RETIRED_EXES\s*=\s*(.*)$/mi);
+    my ($var2) = ($body =~ m/^RETIRED_GL_EXES\s*=\s*(.*)$/mi);
     error ("no RETIRED_EXES in $mf") unless $var;
+    $var .= " $var2" if $var2;
     foreach my $hack (split (/\s+/, $var)) {
       $disable{$hack} = 2;
     }
index 970c6d4f25ef349251869d8f4f40fe979b39438f..332972b0dfd700927c3461af243ea732cd796d78 100644 (file)
@@ -70,13 +70,7 @@ static void talk_1 (struct state *);
 static int think (struct state *);
 static unsigned long look (struct state *); 
 
-#define FROM_ARGV    1
-#define FROM_PROGRAM 2
-#define FROM_FILE    3
-#define FROM_RESRC   4
-
 #define IS_MOVING  1
-#define GET_PASSWD 2
 
 #if defined(HAVE_GDK_PIXBUF) || defined(HAVE_XPM)
 # include "images/noseguy/nose-f1.xpm"
index 3ce65d73ce8ea9ba203cc9589c83b33c9a79dc01..7be6c03cfb27ab8a4e714029c486010e767961ae 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1999-2008 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 1999-2009 Jamie Zawinski <jwz@jwz.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
@@ -1354,6 +1354,7 @@ drain_input (p_state *state)
            {
              waitpid(state->pid, NULL, 0);
              fclose (state->pipe);
+              state->pid = 0;
            }
          else
            {
@@ -1436,7 +1437,7 @@ phosphor_reshape (Display *dpy, Window window, void *closure,
   resize_grid (state);
 
 # if defined(HAVE_FORKPTY) && defined(TIOCSWINSZ)
-  if (state->pid)
+  if (state->pid && state->pipe)
     {
       /* Tell the sub-process that the screen size has changed. */
       struct winsize ws;
index 5b26950a42003ec13f5942520c34e25fab7fae5f..39040ea377c66067619ea4bdc19932c23226d90a 100644 (file)
@@ -344,7 +344,7 @@ static void Initialize( struct state *st )
        else if( st->iDegreeCount > 5400 ) st->iDegreeCount = 5400;
        CreateTables( st, st->iDegreeCount );
 #ifdef VERBOSE
-       printf( "%s: Using a %d degree circle.\n", progname );
+       printf( "%s: Using a %d degree circle.\n", progname, st->iDegreeCount );
 #endif /* VERBOSE */
   
        /*  Get the base color. */
@@ -425,16 +425,6 @@ shadebobs_draw (Display *dpy, Window window, void *closure)
   for( st->iShadeBob=0; st->iShadeBob<st->nShadeBobCount; st->iShadeBob++ )
     Execute( st, &st->aShadeBobs[ st->iShadeBob ] );
 
-#ifdef VERBOSE
-  iFrame++;
-  if( nTime - time( NULL ) )
-    {
-      printf( "%s: %d FPS\n", progname, iFrame );
-      nTime = time( NULL );
-      iFrame = 0;
-    }
-#endif  /*  VERBOSE */
-
   return st->delay;
 }
 
index 493643e4cd82d2d5b085b3141ad881c7b272fd6d..33890e6b00f29bf194bd30156ea2fe624de6a465 100644 (file)
@@ -15,7 +15,7 @@ truchet - draws curved or angular Truchet patterns
 .SH DESCRIPTION
 The \fItruchet\fP program draws arc and line based Truchet patterns.
 .SH OPTIONS
-.l truchet
+.I truchet
 accepts the following options:
 .TP 8
 .B  \-window
index 6387a42a4909d38c05ea00b11cead074e8186996..c6069e42525b7bbe85fea156fe21948b599c08d6 100644 (file)
@@ -795,7 +795,7 @@ vermiculate_init (Display *d, Window w)
     st->mygc = XCreateGC (st->dpy, st->window, 0, &mygcv);
   }
 
-  st->point = (unsigned char *) malloc (st->wid * st->hei);
+  st->point = (unsigned char *) calloc (1, st->wid * st->hei);
   maininit (st);
   palupdate (st, True);
   consume_instring(st);
index 24baec50cfd966048c385884d2767cf8133757af..520e53ae5e9efb423f7a578bc329deb76f62c974 100755 (executable)
@@ -60,7 +60,7 @@ use bytes;  # Larry can take Unicode and shove it up his ass sideways.
 
 
 my $progname = $0; $progname =~ s@.*/@@g;
-my $version = q{ $Revision: 1.148 $ }; $version =~ s/^[^0-9]+([0-9.]+).*$/$1/;
+my $version = q{ $Revision: 1.149 $ }; $version =~ s/^[^0-9]+([0-9.]+).*$/$1/;
 my $copyright = "WebCollage $version, Copyright (c) 1999-2008" .
     " Jamie Zawinski <jwz\@jwz.org>\n" .
     "            http://www.jwz.org/webcollage/\n";
@@ -3512,6 +3512,40 @@ sub update_imagemap($$$$$$$$) {
 }
 
 
+# Figure out what the proxy server should be, either from environment
+# variables or by parsing the output of the (MacOS) program "scutil",
+# which tells us what the system-wide proxy settings are.
+#
+sub set_proxy() {
+
+  if (! $http_proxy) {
+    # historical suckage: the environment variable name is lower case.
+    $http_proxy = $ENV{http_proxy} || $ENV{HTTP_PROXY};
+  }
+
+  if (defined ($http_proxy)) {
+    if ($http_proxy && $http_proxy =~ m@^http://([^/]*)/?$@ ) {
+      # historical suckage: allow "http://host:port" as well as "host:port".
+      $http_proxy = $1;
+    }
+
+  } else {
+    my $proxy_data = `scutil --proxy 2>/dev/null`;
+    my ($server) = ($proxy_data =~ m/\bHTTPProxy\s*:\s*([^\s]+)/s);
+    my ($port)   = ($proxy_data =~ m/\bHTTPPort\s*:\s*([^\s]+)/s);
+    # Note: this ignores the "ExceptionsList".
+    if ($server) {
+      $http_proxy = $server;
+      $http_proxy .= ":$port" if $port;
+    }
+  }
+
+  if ($http_proxy) {
+    LOG ($verbose_net, "proxy server: $http_proxy");
+  }
+}
+
+
 sub init_signals() {
 
   $SIG{HUP}  = \&signal_cleanup;
@@ -3542,9 +3576,6 @@ sub main() {
   my $root_p = 0;
   my $window_id = undef;
 
-  # historical suckage: the environment variable name is lower case.
-  $http_proxy = $ENV{http_proxy} || $ENV{HTTP_PROXY};
-
   while ($_ = $ARGV[0]) {
     shift @ARGV;
     if ($_ eq "-display" ||
@@ -3645,14 +3676,6 @@ sub main() {
     }
   }
 
-  if ($http_proxy && $http_proxy eq "") {
-    $http_proxy = undef;
-  }
-  if ($http_proxy && $http_proxy =~ m@^http://([^/]*)/?$@ ) {
-    # historical suckage: allow "http://host:port" as well as "host:port".
-    $http_proxy = $1;
-  }
-
   if (!$root_p && !$no_output_p && !$cocoa_p) {
     print STDERR $copyright;
     error "the -root argument is mandatory (for now.)";
@@ -3730,6 +3753,7 @@ sub main() {
   }
 
   init_signals();
+  set_proxy();
 
   spawn_driftnet ($driftnet_cmd) if ($driftnet_cmd);
 
index 11e3dcf474fe994a56228716c579482301c006d1..f05aee166f9d6ecf778a9bcddaec5f7077ff76c4 100644 (file)
@@ -1,5 +1,5 @@
 /* webcollage-helper-cocoa --- scales and pastes one image into another
- * xscreensaver, Copyright (c) 2002-2008 Jamie Zawinski <jwz@jwz.org>
+ * xscreensaver, Copyright (c) 2002-2009 Jamie Zawinski <jwz@jwz.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
 #include <unistd.h>
 #include <sys/stat.h>
 
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4
+ typedef int          NSInteger;
+ typedef unsigned int NSUInteger;
+#endif
+
+
 char *progname;
 static int verbose_p = 0;
 
@@ -142,7 +149,7 @@ bevel_image (NSImage *img, int bevel_pct,
                    bytesPerRow: 0
                   bitsPerPixel: 0];
 
-  int xx, yy;
+  NSInteger xx, yy;
   double *ramp = (double *) malloc (sizeof(*ramp) * (bevel_size + 1));
 
   if (!ramp)
@@ -183,7 +190,7 @@ bevel_image (NSImage *img, int bevel_pct,
           r = rx * ry;
           if (r != 1)
             {
-              unsigned int p[4];
+              NSUInteger p[4];
               p[0] = 0xFF * r;
               p[1] = p[2] = p[3] = 0xFF;
               [rep setPixel:p atX:xx y:yy];
@@ -296,7 +303,8 @@ write_image (NSImage *img, const char *file)
                                properties:props];
 
   [jpeg_data writeToFile:
-               [NSString stringWithCString:file]
+               [NSString stringWithCString:file
+                                  encoding:NSISOLatin1StringEncoding]
              atomically:YES];
 
   if (verbose_p)
index bc121a9629510c017d3522522bb8c3749b41780b..4b2ebc3ccf5a213df41b18da17ee362ea7678d34 100644 (file)
@@ -190,7 +190,7 @@ default: all
 all-yes: $(CATALOGS)
 all-no:
 
-$(srcdir)/$(GETTEXT_PACKAGE).pot: $(POTFILES)
+$(GETTEXT_PACKAGE).pot: $(POTFILES)
        @INTLTOOL_EXTRACT=$(INTLTOOL_EXTRACT) ; \
        export INTLTOOL_EXTRACT ; \
        echo top_srcdir=$(top_srcdir) $(GENPOT) ; \
@@ -274,6 +274,7 @@ clean: mostlyclean
 
 distclean: clean
        rm -f Makefile Makefile.in POTFILES *.mo *.msg *.cat *.cat.m *.gmo *.pot
+       rm -f stamp-it
 
 maintainer-clean: distclean
        @echo "This command is intended for maintainers to use;"
@@ -281,9 +282,7 @@ maintainer-clean: distclean
        rm -f $(GMOFILES)
 
 depend:
-# fuck off.  love, jwz.
-#distdepend: generate_potfiles_in update-po $(DISTFILES)
-distdepend::
+distdepend: generate_potfiles_in update-po $(DISTFILES)
 
 
 # jwz: Generates po/POTFILES.in by examining the source tree:
@@ -292,6 +291,8 @@ distdepend::
 generate_potfiles_in:
        @tmp=po.$$$$ ;                          \
         file=POTFILES.in ;                     \
+        echo "sleeping 3 seconds..." ;\
+        sleep 3; \
         ( cd $(top_srcdir);                    \
           echo "# Auto-generated: `LANG=C date`" ;     \
           ( grep -l '_("' driver/*.[ch] ;      \
@@ -362,16 +363,21 @@ POTFILES: POTFILES.in
            && (sed -e '/^#/d'                                          \
                    -e "s/^\[.*\] +//"                                  \
                    -e '/^[     ]*$$/d'                                 \
-                   -e "s@.*@   $$posrcprefix& \\\\@" < $(srcdir)/$@.in \
+                   -e "s@.*@   $$posrcprefix& \\\\@" < $@.in           \
                | sed -e '$$s/\\$$//') > $@-t \
            && chmod a-w $@-t \
            && mv $@-t $@ )
 
-# Please to be fucking the hell off.   This breaks "make distdepend". -jwz
-#Makefile: Makefile.in.in ../config.status POTFILES
-#      cd .. \
-#        && CONFIG_FILES=$(subdir)/$@.in CONFIG_HEADERS= \
-#             $(SHELL) ./config.status
+Makefile: stamp-it
+       @if test ! -f $@; then \
+               rm -f stamp-it; \
+               $(MAKE) stamp-it; \
+       fi
+
+stamp-it: Makefile.in.in ../config.status POTFILES
+       cd .. \
+         && CONFIG_FILES=$(subdir)/Makefile.in CONFIG_HEADERS= \
+              $(SHELL) ./config.status
 
 # Tell versions [3.59,3.63) of GNU make not to export all variables.
 # Otherwise a system limit (for SysV at least) may be exceeded.
index 399f0872cf4b569fe6dc4293fa2817586f20adb0..eca5bbf0265d183506b68de0ead3605025699407 100644 (file)
-# Auto-generated: Sun Aug  3 02:50:46 PDT 2008
+# Auto-generated: Thu Sep  3 02:08:38 PDT 2009
 driver/demo-Gtk-conf.c
 driver/demo-Gtk-support.c
 driver/demo-Gtk-widgets.c
 driver/demo-Gtk.c
-driver/screensaver-properties.desktop.in.h
-driver/xscreensaver-demo.glade2.h
-hacks/config/abstractile.xml.h
-hacks/config/anemone.xml.h
-hacks/config/anemotaxis.xml.h
-hacks/config/ant.xml.h
-hacks/config/antinspect.xml.h
-hacks/config/antmaze.xml.h
-hacks/config/antspotlight.xml.h
-hacks/config/apollonian.xml.h
-hacks/config/apple2.xml.h
-hacks/config/atlantis.xml.h
-hacks/config/attraction.xml.h
-hacks/config/atunnel.xml.h
-hacks/config/barcode.xml.h
-hacks/config/blaster.xml.h
-hacks/config/blinkbox.xml.h
-hacks/config/blitspin.xml.h
-hacks/config/blocktube.xml.h
-hacks/config/boing.xml.h
-hacks/config/bouboule.xml.h
-hacks/config/bouncingcow.xml.h
-hacks/config/boxed.xml.h
-hacks/config/boxfit.xml.h
-hacks/config/braid.xml.h
-hacks/config/bsod.xml.h
-hacks/config/bubble3d.xml.h
-hacks/config/bubbles.xml.h
-hacks/config/bumps.xml.h
-hacks/config/cage.xml.h
-hacks/config/carousel.xml.h
-hacks/config/ccurve.xml.h
-hacks/config/celtic.xml.h
-hacks/config/circuit.xml.h
-hacks/config/cloudlife.xml.h
-hacks/config/compass.xml.h
-hacks/config/coral.xml.h
-hacks/config/crackberg.xml.h
-hacks/config/critical.xml.h
-hacks/config/crystal.xml.h
-hacks/config/cube21.xml.h
-hacks/config/cubenetic.xml.h
-hacks/config/cubestorm.xml.h
-hacks/config/cubicgrid.xml.h
-hacks/config/cwaves.xml.h
-hacks/config/cynosure.xml.h
-hacks/config/dangerball.xml.h
-hacks/config/decayscreen.xml.h
-hacks/config/deco.xml.h
-hacks/config/deluxe.xml.h
-hacks/config/demon.xml.h
-hacks/config/discrete.xml.h
-hacks/config/distort.xml.h
-hacks/config/dnalogo.xml.h
-hacks/config/drift.xml.h
-hacks/config/endgame.xml.h
-hacks/config/engine.xml.h
-hacks/config/epicycle.xml.h
-hacks/config/eruption.xml.h
-hacks/config/euler2d.xml.h
-hacks/config/extrusion.xml.h
-hacks/config/fadeplot.xml.h
-hacks/config/fiberlamp.xml.h
-hacks/config/fireworkx.xml.h
-hacks/config/flag.xml.h
-hacks/config/flame.xml.h
-hacks/config/flipflop.xml.h
-hacks/config/flipscreen3d.xml.h
-hacks/config/fliptext.xml.h
-hacks/config/flow.xml.h
-hacks/config/fluidballs.xml.h
-hacks/config/flurry.xml.h
-hacks/config/flyingtoasters.xml.h
-hacks/config/fontglide.xml.h
-hacks/config/forest.xml.h
-hacks/config/fuzzyflakes.xml.h
-hacks/config/galaxy.xml.h
-hacks/config/gears.xml.h
-hacks/config/gflux.xml.h
-hacks/config/glblur.xml.h
-hacks/config/glcells.xml.h
-hacks/config/gleidescope.xml.h
-hacks/config/glforestfire.xml.h
-hacks/config/glhanoi.xml.h
-hacks/config/glknots.xml.h
-hacks/config/glmatrix.xml.h
-hacks/config/glplanet.xml.h
-hacks/config/glschool.xml.h
-hacks/config/glslideshow.xml.h
-hacks/config/glsnake.xml.h
-hacks/config/gltext.xml.h
-hacks/config/goop.xml.h
-hacks/config/grav.xml.h
-hacks/config/greynetic.xml.h
-hacks/config/halftone.xml.h
-hacks/config/halo.xml.h
-hacks/config/helix.xml.h
-hacks/config/hopalong.xml.h
-hacks/config/hyperball.xml.h
-hacks/config/hypercube.xml.h
-hacks/config/hypertorus.xml.h
-hacks/config/hypnowheel.xml.h
-hacks/config/ifs.xml.h
-hacks/config/imsmap.xml.h
-hacks/config/interaggregate.xml.h
-hacks/config/interference.xml.h
-hacks/config/intermomentary.xml.h
-hacks/config/jigglypuff.xml.h
-hacks/config/jigsaw.xml.h
-hacks/config/juggle.xml.h
-hacks/config/juggler3d.xml.h
-hacks/config/julia.xml.h
-hacks/config/kaleidescope.xml.h
-hacks/config/klein.xml.h
-hacks/config/kumppa.xml.h
-hacks/config/lament.xml.h
-hacks/config/laser.xml.h
-hacks/config/lavalite.xml.h
-hacks/config/lcdscrub.xml.h
-hacks/config/lightning.xml.h
-hacks/config/lisa.xml.h
-hacks/config/lissie.xml.h
-hacks/config/lmorph.xml.h
-hacks/config/lockward.xml.h
-hacks/config/loop.xml.h
-hacks/config/m6502.xml.h
-hacks/config/maze.xml.h
-hacks/config/memscroller.xml.h
-hacks/config/menger.xml.h
-hacks/config/metaballs.xml.h
-hacks/config/mirrorblob.xml.h
-hacks/config/moebius.xml.h
-hacks/config/moebiusgears.xml.h
-hacks/config/moire.xml.h
-hacks/config/moire2.xml.h
-hacks/config/molecule.xml.h
-hacks/config/morph3d.xml.h
-hacks/config/mountain.xml.h
-hacks/config/munch.xml.h
-hacks/config/nerverot.xml.h
-hacks/config/noof.xml.h
-hacks/config/noseguy.xml.h
-hacks/config/pacman.xml.h
-hacks/config/pedal.xml.h
-hacks/config/penetrate.xml.h
-hacks/config/penrose.xml.h
-hacks/config/petri.xml.h
-hacks/config/phosphor.xml.h
-hacks/config/piecewise.xml.h
-hacks/config/pinion.xml.h
-hacks/config/pipes.xml.h
-hacks/config/polyhedra.xml.h
-hacks/config/polyominoes.xml.h
-hacks/config/polytopes.xml.h
-hacks/config/pong.xml.h
-hacks/config/popsquares.xml.h
-hacks/config/providence.xml.h
-hacks/config/pulsar.xml.h
-hacks/config/pyro.xml.h
-hacks/config/qix.xml.h
-hacks/config/queens.xml.h
-hacks/config/rd-bomb.xml.h
-hacks/config/rdbomb.xml.h
-hacks/config/ripples.xml.h
-hacks/config/rocks.xml.h
-hacks/config/rorschach.xml.h
-hacks/config/rotor.xml.h
-hacks/config/rotzoomer.xml.h
-hacks/config/rubik.xml.h
-hacks/config/sballs.xml.h
-hacks/config/shadebobs.xml.h
-hacks/config/sierpinski.xml.h
-hacks/config/sierpinski3d.xml.h
-hacks/config/skytentacles.xml.h
-hacks/config/slidescreen.xml.h
-hacks/config/slip.xml.h
-hacks/config/sonar.xml.h
-hacks/config/speedmine.xml.h
-hacks/config/sphere.xml.h
-hacks/config/spheremonics.xml.h
-hacks/config/spiral.xml.h
-hacks/config/spotlight.xml.h
-hacks/config/sproingies.xml.h
-hacks/config/squiral.xml.h
-hacks/config/stairs.xml.h
-hacks/config/starfish.xml.h
-hacks/config/starwars.xml.h
-hacks/config/stonerview.xml.h
-hacks/config/strange.xml.h
-hacks/config/substrate.xml.h
-hacks/config/superquadrics.xml.h
-hacks/config/swirl.xml.h
-hacks/config/t3d.xml.h
-hacks/config/tangram.xml.h
-hacks/config/thornbird.xml.h
-hacks/config/timetunnel.xml.h
-hacks/config/topblock.xml.h
-hacks/config/triangle.xml.h
-hacks/config/truchet.xml.h
-hacks/config/twang.xml.h
-hacks/config/vermiculate.xml.h
-hacks/config/vidwhacker.xml.h
-hacks/config/vines.xml.h
-hacks/config/voronoi.xml.h
-hacks/config/wander.xml.h
-hacks/config/webcollage.xml.h
-hacks/config/whirlwindwarp.xml.h
-hacks/config/whirlygig.xml.h
-hacks/config/worm.xml.h
-hacks/config/wormhole.xml.h
-hacks/config/xanalogtv.xml.h
-hacks/config/xflame.xml.h
-hacks/config/xjack.xml.h
-hacks/config/xlyap.xml.h
-hacks/config/xmatrix.xml.h
-hacks/config/xrayswarm.xml.h
-hacks/config/xspirograph.xml.h
-hacks/config/zoom.xml.h
+driver/screensaver-properties.desktop.in
+driver/xscreensaver-demo.glade2
+hacks/config/abstractile.xml
+hacks/config/anemone.xml
+hacks/config/anemotaxis.xml
+hacks/config/ant.xml
+hacks/config/antinspect.xml
+hacks/config/antmaze.xml
+hacks/config/antspotlight.xml
+hacks/config/apollonian.xml
+hacks/config/apple2.xml
+hacks/config/atlantis.xml
+hacks/config/attraction.xml
+hacks/config/atunnel.xml
+hacks/config/barcode.xml
+hacks/config/blaster.xml
+hacks/config/blinkbox.xml
+hacks/config/blitspin.xml
+hacks/config/blocktube.xml
+hacks/config/boing.xml
+hacks/config/bouboule.xml
+hacks/config/bouncingcow.xml
+hacks/config/boxed.xml
+hacks/config/boxfit.xml
+hacks/config/braid.xml
+hacks/config/bsod.xml
+hacks/config/bubble3d.xml
+hacks/config/bubbles.xml
+hacks/config/bumps.xml
+hacks/config/cage.xml
+hacks/config/carousel.xml
+hacks/config/ccurve.xml
+hacks/config/celtic.xml
+hacks/config/circuit.xml
+hacks/config/cloudlife.xml
+hacks/config/compass.xml
+hacks/config/coral.xml
+hacks/config/crackberg.xml
+hacks/config/critical.xml
+hacks/config/crystal.xml
+hacks/config/cube21.xml
+hacks/config/cubenetic.xml
+hacks/config/cubestorm.xml
+hacks/config/cubicgrid.xml
+hacks/config/cwaves.xml
+hacks/config/cynosure.xml
+hacks/config/dangerball.xml
+hacks/config/decayscreen.xml
+hacks/config/deco.xml
+hacks/config/deluxe.xml
+hacks/config/demon.xml
+hacks/config/discrete.xml
+hacks/config/distort.xml
+hacks/config/dnalogo.xml
+hacks/config/drift.xml
+hacks/config/endgame.xml
+hacks/config/engine.xml
+hacks/config/epicycle.xml
+hacks/config/eruption.xml
+hacks/config/euler2d.xml
+hacks/config/extrusion.xml
+hacks/config/fadeplot.xml
+hacks/config/fiberlamp.xml
+hacks/config/fireworkx.xml
+hacks/config/flag.xml
+hacks/config/flame.xml
+hacks/config/flipflop.xml
+hacks/config/flipscreen3d.xml
+hacks/config/fliptext.xml
+hacks/config/flow.xml
+hacks/config/fluidballs.xml
+hacks/config/flurry.xml
+hacks/config/flyingtoasters.xml
+hacks/config/fontglide.xml
+hacks/config/forest.xml
+hacks/config/fuzzyflakes.xml
+hacks/config/galaxy.xml
+hacks/config/gears.xml
+hacks/config/gflux.xml
+hacks/config/glblur.xml
+hacks/config/glcells.xml
+hacks/config/gleidescope.xml
+hacks/config/glforestfire.xml
+hacks/config/glhanoi.xml
+hacks/config/glknots.xml
+hacks/config/glmatrix.xml
+hacks/config/glplanet.xml
+hacks/config/glschool.xml
+hacks/config/glslideshow.xml
+hacks/config/glsnake.xml
+hacks/config/gltext.xml
+hacks/config/goop.xml
+hacks/config/grav.xml
+hacks/config/greynetic.xml
+hacks/config/halftone.xml
+hacks/config/halo.xml
+hacks/config/helix.xml
+hacks/config/hopalong.xml
+hacks/config/hyperball.xml
+hacks/config/hypercube.xml
+hacks/config/hypertorus.xml
+hacks/config/hypnowheel.xml
+hacks/config/ifs.xml
+hacks/config/imsmap.xml
+hacks/config/interaggregate.xml
+hacks/config/interference.xml
+hacks/config/intermomentary.xml
+hacks/config/jigglypuff.xml
+hacks/config/jigsaw.xml
+hacks/config/juggle.xml
+hacks/config/juggler3d.xml
+hacks/config/julia.xml
+hacks/config/kaleidescope.xml
+hacks/config/klein.xml
+hacks/config/kumppa.xml
+hacks/config/lament.xml
+hacks/config/laser.xml
+hacks/config/lavalite.xml
+hacks/config/lcdscrub.xml
+hacks/config/lightning.xml
+hacks/config/lisa.xml
+hacks/config/lissie.xml
+hacks/config/lmorph.xml
+hacks/config/lockward.xml
+hacks/config/loop.xml
+hacks/config/m6502.xml
+hacks/config/maze.xml
+hacks/config/memscroller.xml
+hacks/config/menger.xml
+hacks/config/metaballs.xml
+hacks/config/mirrorblob.xml
+hacks/config/moebius.xml
+hacks/config/moebiusgears.xml
+hacks/config/moire.xml
+hacks/config/moire2.xml
+hacks/config/molecule.xml
+hacks/config/morph3d.xml
+hacks/config/mountain.xml
+hacks/config/munch.xml
+hacks/config/nerverot.xml
+hacks/config/noof.xml
+hacks/config/noseguy.xml
+hacks/config/pacman.xml
+hacks/config/pedal.xml
+hacks/config/penetrate.xml
+hacks/config/penrose.xml
+hacks/config/petri.xml
+hacks/config/phosphor.xml
+hacks/config/photopile.xml
+hacks/config/piecewise.xml
+hacks/config/pinion.xml
+hacks/config/pipes.xml
+hacks/config/polyhedra.xml
+hacks/config/polyominoes.xml
+hacks/config/polytopes.xml
+hacks/config/pong.xml
+hacks/config/popsquares.xml
+hacks/config/providence.xml
+hacks/config/pulsar.xml
+hacks/config/pyro.xml
+hacks/config/qix.xml
+hacks/config/queens.xml
+hacks/config/rd-bomb.xml
+hacks/config/rdbomb.xml
+hacks/config/ripples.xml
+hacks/config/rocks.xml
+hacks/config/rorschach.xml
+hacks/config/rotor.xml
+hacks/config/rotzoomer.xml
+hacks/config/rubik.xml
+hacks/config/rubikblocks.xml
+hacks/config/sballs.xml
+hacks/config/shadebobs.xml
+hacks/config/sierpinski.xml
+hacks/config/sierpinski3d.xml
+hacks/config/skytentacles.xml
+hacks/config/slidescreen.xml
+hacks/config/slip.xml
+hacks/config/sonar.xml
+hacks/config/speedmine.xml
+hacks/config/sphere.xml
+hacks/config/spheremonics.xml
+hacks/config/spiral.xml
+hacks/config/spotlight.xml
+hacks/config/sproingies.xml
+hacks/config/squiral.xml
+hacks/config/stairs.xml
+hacks/config/starfish.xml
+hacks/config/starwars.xml
+hacks/config/stonerview.xml
+hacks/config/strange.xml
+hacks/config/substrate.xml
+hacks/config/superquadrics.xml
+hacks/config/surfaces.xml
+hacks/config/swirl.xml
+hacks/config/t3d.xml
+hacks/config/tangram.xml
+hacks/config/thornbird.xml
+hacks/config/timetunnel.xml
+hacks/config/topblock.xml
+hacks/config/triangle.xml
+hacks/config/truchet.xml
+hacks/config/twang.xml
+hacks/config/vermiculate.xml
+hacks/config/vidwhacker.xml
+hacks/config/vines.xml
+hacks/config/voronoi.xml
+hacks/config/wander.xml
+hacks/config/webcollage.xml
+hacks/config/whirlwindwarp.xml
+hacks/config/whirlygig.xml
+hacks/config/worm.xml
+hacks/config/wormhole.xml
+hacks/config/xanalogtv.xml
+hacks/config/xflame.xml
+hacks/config/xjack.xml
+hacks/config/xlyap.xml
+hacks/config/xmatrix.xml
+hacks/config/xrayswarm.xml
+hacks/config/xspirograph.xml
+hacks/config/zoom.xml
index 8399f997bac7d7626236b97752a1f461d8f013ae..4071cf62e303fced7963d0734517e7bf367d778b 100644 (file)
--- a/setup.com
+++ b/setup.com
@@ -58,7 +58,6 @@ $ imsmap      :== $'mydir'imsmap
 $ interaggregate       :== $'mydir'interaggregate
 $ interference :== $'mydir'interference
 $ intermomentary       :== $'mydir'intermomentary
-$ juggle       :== $'mydir'juggle
 $ julia                :== $'mydir'julia
 $ kaleidescope :== $'mydir'kaleidescope
 $ kumppa       :== $'mydir'kumppa
diff --git a/utils/._colors.c b/utils/._colors.c
new file mode 100644 (file)
index 0000000..1920402
Binary files /dev/null and b/utils/._colors.c differ
index a6df5779a469d5a0a0fad3a5235de3cb0f82eacb..45b46636a240e3c68cb2e0398e92426d2307141e 100644 (file)
@@ -215,86 +215,3 @@ distdepend:: compile_axp.com compile_decc.com
 #
 # DO NOT DELETE: updated by make distdepend
 
-alpha.o: $(srcdir)/alpha.h
-alpha.o: ../config.h
-alpha.o: $(srcdir)/hsv.h
-alpha.o: $(srcdir)/resources.h
-alpha.o: $(srcdir)/utils.h
-alpha.o: $(srcdir)/visual.h
-alpha.o: $(srcdir)/yarandom.h
-colorbars.o: $(srcdir)/colorbars.h
-colorbars.o: ../config.h
-colorbars.o: $(srcdir)/resources.h
-colorbars.o: $(srcdir)/utils.h
-colors.o: $(srcdir)/colors.h
-colors.o: ../config.h
-colors.o: $(srcdir)/hsv.h
-colors.o: $(srcdir)/utils.h
-colors.o: $(srcdir)/visual.h
-colors.o: $(srcdir)/yarandom.h
-erase.o: ../config.h
-erase.o: $(srcdir)/erase.h
-erase.o: $(srcdir)/resources.h
-erase.o: $(srcdir)/usleep.h
-erase.o: $(srcdir)/utils.h
-erase.o: $(srcdir)/yarandom.h
-fade.o: ../config.h
-fade.o: $(srcdir)/fade.h
-fade.o: $(srcdir)/usleep.h
-fade.o: $(srcdir)/utils.h
-fade.o: $(srcdir)/visual.h
-grabclient.o: ../config.h
-grabclient.o: $(srcdir)/grabscreen.h
-grabclient.o: $(srcdir)/resources.h
-grabclient.o: $(srcdir)/utils.h
-grabclient.o: $(srcdir)/vroot.h
-grabscreen.o: $(srcdir)/colors.h
-grabscreen.o: ../config.h
-grabscreen.o: $(srcdir)/grabscreen.h
-grabscreen.o: $(srcdir)/resources.h
-grabscreen.o: $(srcdir)/usleep.h
-grabscreen.o: $(srcdir)/utils.h
-grabscreen.o: $(srcdir)/visual.h
-grabscreen.o: $(srcdir)/vroot.h
-grabscreen.o: $(srcdir)/yarandom.h
-hsv.o: ../config.h
-hsv.o: $(srcdir)/hsv.h
-hsv.o: $(srcdir)/utils.h
-logo.o: ../config.h
-logo.o: $(srcdir)/images/logo-180.xpm
-logo.o: $(srcdir)/images/logo-50.xpm
-logo.o: $(srcdir)/minixpm.h
-logo.o: $(srcdir)/resources.h
-logo.o: $(srcdir)/utils.h
-logo.o: $(srcdir)/visual.h
-minixpm.o: ../config.h
-minixpm.o: $(srcdir)/minixpm.h
-overlay.o: ../config.h
-overlay.o: $(srcdir)/utils.h
-overlay.o: $(srcdir)/visual.h
-resources.o: ../config.h
-resources.o: $(srcdir)/resources.h
-resources.o: $(srcdir)/utils.h
-spline.o: ../config.h
-spline.o: $(srcdir)/spline.h
-spline.o: $(srcdir)/utils.h
-usleep.o: ../config.h
-visual-gl.o: ../config.h
-visual-gl.o: $(srcdir)/utils.h
-visual-gl.o: $(srcdir)/visual.h
-visual.o: ../config.h
-visual.o: $(srcdir)/resources.h
-visual.o: $(srcdir)/utils.h
-visual.o: $(srcdir)/visual.h
-xdbe.o: ../config.h
-xdbe.o: $(srcdir)/resources.h
-xdbe.o: $(srcdir)/utils.h
-xdbe.o: $(srcdir)/xdbe.h
-xmu.o: ../config.h
-xshm.o: ../config.h
-xshm.o: $(srcdir)/resources.h
-xshm.o: $(srcdir)/utils.h
-xshm.o: $(srcdir)/xshm.h
-yarandom.o: ../config.h
-yarandom.o: $(srcdir)/yarandom.h
-
index 16dbc452145bd396023921b73934e173a2e17470..85381def0bed64dfa9e3004f13f0a5afdb6d1ccd 100644 (file)
@@ -1,2 +1,2 @@
 static const char screensaver_id[] =
-       "@(#)xscreensaver 5.08 (27-Dec-2008), by Jamie Zawinski (jwz@jwz.org)";
+       "@(#)xscreensaver 5.09 (03-Sep-2009), by Jamie Zawinski (jwz@jwz.org)";
index 3c8a7a8bd9357baeb437dee07e3500136ab406ef..45ef596d02e89b28ded1680ee6fb6f3db828d8aa 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1999-2007 by Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 1999-2009 by Jamie Zawinski <jwz@jwz.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
@@ -142,6 +142,18 @@ describe_gl_visual (FILE *f, Screen *screen, Visual *visual,
         printf ("    GLX type:          indexed (%d)\n", value);
       }
 
+# ifndef  GLX_NONE_EXT       /* Hooray for gratuitious name changes. */
+#  define GLX_NONE_EXT                    GLX_NONE
+#  define GLX_TRANSPARENT_TYPE_EXT        GLX_TRANSPARENT_TYPE
+#  define GLX_TRANSPARENT_INDEX_EXT       GLX_TRANSPARENT_INDEX
+#  define GLX_TRANSPARENT_INDEX_VALUE_EXT GLX_TRANSPARENT_INDEX_VALUE
+#  define GLX_TRANSPARENT_RGB_EXT         GLX_TRANSPARENT_RGB
+#  define GLX_TRANSPARENT_RED_VALUE_EXT   GLX_TRANSPARENT_RED_VALUE
+#  define GLX_TRANSPARENT_GREEN_VALUE_EXT GLX_TRANSPARENT_GREEN_VALUE
+#  define GLX_TRANSPARENT_BLUE_VALUE_EXT  GLX_TRANSPARENT_BLUE_VALUE
+#  define GLX_TRANSPARENT_ALPHA_VALUE_EXT GLX_TRANSPARENT_ALPHA_VALUE
+# endif
+
 # ifdef GLX_VISUAL_CAVEAT_EXT
     if (!glXGetConfig (dpy, vi_out, GLX_VISUAL_CAVEAT_EXT, &value) &&
         value != GLX_NONE_EXT)
index eaa97fc6fffebbbfd1674196844aa2c151507ab7..276c00407957c5cbf943a274d40fd04fd3f53748 100644 (file)
@@ -1,5 +1,5 @@
 %define        name xscreensaver
-%define        version 5.08
+%define        version 5.09
 
 Summary:       X screen saver and locker
 Name:          %{name}
index 7a050184f6f8b6781b2f6ee7607b0bdbe118fe56..0cbc5d9ea004a822c3ff3b951e6db280919824c7 100644 (file)
@@ -3,7 +3,7 @@
        archiveVersion = 1;
        classes = {
        };
-       objectVersion = 42;
+       objectVersion = 44;
        objects = {
 
 /* Begin PBXAggregateTarget section */
@@ -18,6 +18,7 @@
                                AF137D650F075E5C004DE3B2 /* PBXTargetDependency */,
                                AF137D630F075E5C004DE3B2 /* PBXTargetDependency */,
                                AF137D610F075E5C004DE3B2 /* PBXTargetDependency */,
+                               AFB581B0102F363300342B11 /* PBXTargetDependency */,
                                AF137D5F0F075E5C004DE3B2 /* PBXTargetDependency */,
                                AF137D5D0F075E5C004DE3B2 /* PBXTargetDependency */,
                                AF137D5B0F075E5C004DE3B2 /* PBXTargetDependency */,
                                AF7779BF09B6608100EA3033 /* PBXTargetDependency */,
                                AF7779BD09B6608100EA3033 /* PBXTargetDependency */,
                                AF7779BB09B6608100EA3033 /* PBXTargetDependency */,
-                               AF7779B909B6608100EA3033 /* PBXTargetDependency */,
                                AF7779B709B6608100EA3033 /* PBXTargetDependency */,
                                AF7779AD09B6608100EA3033 /* PBXTargetDependency */,
                                AF7779AB09B6608100EA3033 /* PBXTargetDependency */,
                                AF7779F509B660B100EA3033 /* PBXTargetDependency */,
                                AF7779F309B660B000EA3033 /* PBXTargetDependency */,
                                AF7779F109B660B000EA3033 /* PBXTargetDependency */,
+                               AF32D9F90F3AD0D90080F535 /* PBXTargetDependency */,
                                AF4540D20E52BE8800AE87B5 /* PBXTargetDependency */,
                                AF7779EF09B660B000EA3033 /* PBXTargetDependency */,
                                AF7779ED09B660B000EA3033 /* PBXTargetDependency */,
                                AF7779E509B660B000EA3033 /* PBXTargetDependency */,
                                AF7779E309B660B000EA3033 /* PBXTargetDependency */,
                                AF7779E109B660AF00EA3033 /* PBXTargetDependency */,
+                               AF4A3460102A59A400A81B2A /* PBXTargetDependency */,
                                AF7779DF09B660AF00EA3033 /* PBXTargetDependency */,
                                AF7779DD09B660AF00EA3033 /* PBXTargetDependency */,
                                AF998EF70A083E1D0051049D /* PBXTargetDependency */,
                AF0DCA500C4CBB0D00D76972 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF48112B0990A2C700FB32B8 /* Carbon.framework */; };
                AF0DCA600C4CBB7300D76972 /* voronoi.c in Sources */ = {isa = PBXBuildFile; fileRef = AF0DCA5F0C4CBB7300D76972 /* voronoi.c */; };
                AF0DCA620C4CBB8E00D76972 /* voronoi.xml in Resources */ = {isa = PBXBuildFile; fileRef = AF0DCA610C4CBB8E00D76972 /* voronoi.xml */; };
+               AF0F46DD104E1809000A929C /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF0F46DC104E1809000A929C /* AppKit.framework */; };
                AF0FAF0C09CA6FF900EE1051 /* xscreensaver-text in Resources */ = {isa = PBXBuildFile; fileRef = AF0FAF0B09CA6FF900EE1051 /* xscreensaver-text */; };
                AF0FAF0D09CA6FF900EE1051 /* xscreensaver-text in Resources */ = {isa = PBXBuildFile; fileRef = AF0FAF0B09CA6FF900EE1051 /* xscreensaver-text */; };
                AF0FAF0E09CA6FF900EE1051 /* xscreensaver-text in Resources */ = {isa = PBXBuildFile; fileRef = AF0FAF0B09CA6FF900EE1051 /* xscreensaver-text */; };
                AF1A177F0D6D6F3E008AF328 /* lcdscrub.c in Sources */ = {isa = PBXBuildFile; fileRef = AF1A177E0D6D6F3E008AF328 /* lcdscrub.c */; };
                AF1A17810D6D6F62008AF328 /* lcdscrub.xml in Resources */ = {isa = PBXBuildFile; fileRef = AF1A17800D6D6F62008AF328 /* lcdscrub.xml */; };
                AF1A26760990E77C00147B80 /* ScreenSaver.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF976ED30989BF59001F8B92 /* ScreenSaver.framework */; };
+               AF32D9E70F3AD0B40080F535 /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
+               AF32D9E90F3AD0B40080F535 /* libjwxyz.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AF4808C1098C3B6C00FB32B8 /* libjwxyz.a */; };
+               AF32D9EA0F3AD0B40080F535 /* ScreenSaver.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF976ED30989BF59001F8B92 /* ScreenSaver.framework */; };
+               AF32D9EB0F3AD0B40080F535 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
+               AF32D9EC0F3AD0B40080F535 /* AGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF480FE70990375900FB32B8 /* AGL.framework */; };
+               AF32D9ED0F3AD0B40080F535 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF480DF1098F528500FB32B8 /* OpenGL.framework */; };
+               AF32D9EE0F3AD0B40080F535 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF48112B0990A2C700FB32B8 /* Carbon.framework */; };
+               AF32D9FB0F3AD1200080F535 /* rubikblocks.c in Sources */ = {isa = PBXBuildFile; fileRef = AF32D9FA0F3AD1200080F535 /* rubikblocks.c */; };
+               AF32D9FD0F3AD1330080F535 /* rubikblocks.xml in Resources */ = {isa = PBXBuildFile; fileRef = AF32D9FC0F3AD1330080F535 /* rubikblocks.xml */; };
                AF35E8900E63823600691F2F /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
                AF35E8910E63823600691F2F /* sonar-icmp.c in Sources */ = {isa = PBXBuildFile; fileRef = AFE30BFF0E52B1DC00CCF4A5 /* sonar-icmp.c */; };
                AF35E8920E63823600691F2F /* sonar-sim.c in Sources */ = {isa = PBXBuildFile; fileRef = AFE30C000E52B1DC00CCF4A5 /* sonar-sim.c */; };
                AF48E1690A0C268500F94CF9 /* glschool_gl.c in Sources */ = {isa = PBXBuildFile; fileRef = AF48E1640A0C268500F94CF9 /* glschool_gl.c */; };
                AF48E16A0A0C268500F94CF9 /* glschool.c in Sources */ = {isa = PBXBuildFile; fileRef = AF48E1660A0C268500F94CF9 /* glschool.c */; };
                AF48E16C0A0C26A400F94CF9 /* glschool.xml in Resources */ = {isa = PBXBuildFile; fileRef = AF48E16B0A0C26A400F94CF9 /* glschool.xml */; };
+               AF4A3450102A593600A81B2A /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
+               AF4A3452102A593600A81B2A /* libjwxyz.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AF4808C1098C3B6C00FB32B8 /* libjwxyz.a */; };
+               AF4A3453102A593600A81B2A /* ScreenSaver.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF976ED30989BF59001F8B92 /* ScreenSaver.framework */; };
+               AF4A3454102A593600A81B2A /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
+               AF4A3455102A593600A81B2A /* AGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF480FE70990375900FB32B8 /* AGL.framework */; };
+               AF4A3456102A593600A81B2A /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF480DF1098F528500FB32B8 /* OpenGL.framework */; };
+               AF4A3457102A593600A81B2A /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF48112B0990A2C700FB32B8 /* Carbon.framework */; };
+               AF4A3462102A59EB00A81B2A /* surfaces.xml in Resources */ = {isa = PBXBuildFile; fileRef = AF4A3461102A59EB00A81B2A /* surfaces.xml */; };
+               AF4A3464102A5A0E00A81B2A /* surfaces.c in Sources */ = {isa = PBXBuildFile; fileRef = AF4A3463102A5A0E00A81B2A /* surfaces.c */; };
                AF4FD6EC0CE7A486005EE58E /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
                AF4FD6EF0CE7A486005EE58E /* libjwxyz.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AF4808C1098C3B6C00FB32B8 /* libjwxyz.a */; };
                AF4FD6F00CE7A486005EE58E /* ScreenSaver.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF976ED30989BF59001F8B92 /* ScreenSaver.framework */; };
                        isa = PBXContainerItemProxy;
                        containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
                        proxyType = 1;
-                       remoteGlobalIDString = AF137D410F075C9B004DE3B2 /* Obsolete */;
+                       remoteGlobalIDString = AF137D410F075C9B004DE3B2;
                        remoteInfo = Obsolete;
                };
                AF137D480F075E5C004DE3B2 /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
                        proxyType = 1;
-                       remoteGlobalIDString = AFD5709B0996B88E00BA26F7 /* Worm */;
+                       remoteGlobalIDString = AFD5709B0996B88E00BA26F7;
                        remoteInfo = Worm;
                };
                AF137D4A0F075E5C004DE3B2 /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
                        proxyType = 1;
-                       remoteGlobalIDString = AF477208099D4EE8001F091E /* Whirlygig */;
+                       remoteGlobalIDString = AF477208099D4EE8001F091E;
                        remoteInfo = Whirlygig;
                };
                AF137D4C0F075E5C004DE3B2 /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
                        proxyType = 1;
-                       remoteGlobalIDString = AFD56F0B0996AAFA00BA26F7 /* Vines */;
+                       remoteGlobalIDString = AFD56F0B0996AAFA00BA26F7;
                        remoteInfo = Vines;
                };
                AF137D4E0F075E5C004DE3B2 /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
                        proxyType = 1;
-                       remoteGlobalIDString = AF4771A7099D4949001F091E /* T3D */;
+                       remoteGlobalIDString = AF4771A7099D4949001F091E;
                        remoteInfo = T3D;
                };
                AF137D500F075E5C004DE3B2 /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
                        proxyType = 1;
-                       remoteGlobalIDString = AFD570430996B61600BA26F7 /* Spiral */;
+                       remoteGlobalIDString = AFD570430996B61600BA26F7;
                        remoteInfo = Spiral;
                };
                AF137D520F075E5C004DE3B2 /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
                        proxyType = 1;
-                       remoteGlobalIDString = AFD570260996B56D00BA26F7 /* Sphere */;
+                       remoteGlobalIDString = AFD570260996B56D00BA26F7;
                        remoteInfo = Sphere;
                };
                AF137D540F075E5C004DE3B2 /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
                        proxyType = 1;
-                       remoteGlobalIDString = AFD570B10996B93000BA26F7 /* Rotor */;
+                       remoteGlobalIDString = AFD570B10996B93000BA26F7;
                        remoteInfo = Rotor;
                };
                AF137D560F075E5C004DE3B2 /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
                        proxyType = 1;
-                       remoteGlobalIDString = AFD56FCF0996B20900BA26F7 /* Lissie */;
+                       remoteGlobalIDString = AFD56FCF0996B20900BA26F7;
                        remoteInfo = Lissie;
                };
                AF137D580F075E5C004DE3B2 /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
                        proxyType = 1;
-                       remoteGlobalIDString = AFD56FB90996B18F00BA26F7 /* Lisa */;
+                       remoteGlobalIDString = AFD56FB90996B18F00BA26F7;
                        remoteInfo = Lisa;
                };
                AF137D5A0F075E5C004DE3B2 /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
                        proxyType = 1;
-                       remoteGlobalIDString = AFD56FA30996B10F00BA26F7 /* Lightning */;
+                       remoteGlobalIDString = AFD56FA30996B10F00BA26F7;
                        remoteInfo = Lightning;
                };
                AF137D5C0F075E5C004DE3B2 /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
                        proxyType = 1;
-                       remoteGlobalIDString = AFD56F8C0996B09400BA26F7 /* Laser */;
+                       remoteGlobalIDString = AFD56F8C0996B09400BA26F7;
                        remoteInfo = Laser;
                };
                AF137D5E0F075E5C004DE3B2 /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
                        proxyType = 1;
-                       remoteGlobalIDString = AF4774B4099D8B5F001F091E /* LMorph */;
+                       remoteGlobalIDString = AF4774B4099D8B5F001F091E;
                        remoteInfo = LMorph;
                };
                AF137D600F075E5C004DE3B2 /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
                        proxyType = 1;
-                       remoteGlobalIDString = AFA55CCC09934CE400F3E977 /* GLForestFire */;
+                       remoteGlobalIDString = AFA55CCC09934CE400F3E977;
                        remoteInfo = GLForestFire;
                };
                AF137D620F075E5C004DE3B2 /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
                        proxyType = 1;
-                       remoteGlobalIDString = AFD56EDA0996A95700BA26F7 /* Forest */;
+                       remoteGlobalIDString = AFD56EDA0996A95700BA26F7;
                        remoteInfo = Forest;
                };
                AF137D640F075E5C004DE3B2 /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
                        proxyType = 1;
-                       remoteGlobalIDString = AF477909099DE379001F091E /* Flag */;
+                       remoteGlobalIDString = AF477909099DE379001F091E;
                        remoteInfo = Flag;
                };
                AF137D660F075E5C004DE3B2 /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
                        proxyType = 1;
-                       remoteGlobalIDString = AF47765A099DA78E001F091E /* Critical */;
+                       remoteGlobalIDString = AF47765A099DA78E001F091E;
                        remoteInfo = Critical;
                };
                AF137D680F075E5C004DE3B2 /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
                        proxyType = 1;
-                       remoteGlobalIDString = AF6427A809A2DE36000F4CD4 /* Bubbles */;
+                       remoteGlobalIDString = AF6427A809A2DE36000F4CD4;
                        remoteInfo = Bubbles;
                };
                AF1A17630D6D6EE3008AF328 /* PBXContainerItemProxy */ = {
                        remoteGlobalIDString = AF1A17610D6D6EE3008AF328;
                        remoteInfo = LCDscrub;
                };
+               AF32D9E20F3AD0B40080F535 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AF4808C0098C3B6C00FB32B8;
+                       remoteInfo = jwxyz;
+               };
+               AF32D9F80F3AD0D90080F535 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AF32D9E00F3AD0B40080F535;
+                       remoteInfo = RubikBlocks;
+               };
                AF35E88C0E63823600691F2F /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
                        remoteGlobalIDString = AF48DEEF0A0C25E000F94CF9;
                        remoteInfo = GLSchool;
                };
+               AF4A344B102A593600A81B2A /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AF4808C0098C3B6C00FB32B8;
+                       remoteInfo = jwxyz;
+               };
+               AF4A345F102A59A400A81B2A /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AF4A3449102A593600A81B2A;
+                       remoteInfo = Surfaces;
+               };
                AF4FD6E80CE7A486005EE58E /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
                        remoteGlobalIDString = AFD572F9099701C000BA26F7;
                        remoteInfo = Julia;
                };
-               AF7779B809B6608100EA3033 /* PBXContainerItemProxy */ = {
-                       isa = PBXContainerItemProxy;
-                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
-                       proxyType = 1;
-                       remoteGlobalIDString = AFD571B50996D9DC00BA26F7;
-                       remoteInfo = Juggle;
-               };
                AF7779BA09B6608100EA3033 /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
                        remoteGlobalIDString = AF4808C0098C3B6C00FB32B8;
                        remoteInfo = jwxyz;
                };
+               AFB581AF102F363300342B11 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AFD571B50996D9DC00BA26F7;
+                       remoteInfo = Juggle;
+               };
                AFCAD5F80992DFE00009617A /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
                AF0DCA560C4CBB0D00D76972 /* Voronoi.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Voronoi.saver; sourceTree = BUILT_PRODUCTS_DIR; };
                AF0DCA5F0C4CBB7300D76972 /* voronoi.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; name = voronoi.c; path = hacks/glx/voronoi.c; sourceTree = "<group>"; };
                AF0DCA610C4CBB8E00D76972 /* voronoi.xml */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text.xml; path = voronoi.xml; sourceTree = "<group>"; };
+               AF0F46DC104E1809000A929C /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
                AF0FAF0B09CA6FF900EE1051 /* xscreensaver-text */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text.script.perl; name = "xscreensaver-text"; path = "driver/xscreensaver-text"; sourceTree = "<group>"; };
                AF0FAF1209CA712600EE1051 /* xscreensaver-getimage-file */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text.script.perl; name = "xscreensaver-getimage-file"; path = "driver/xscreensaver-getimage-file"; sourceTree = "<group>"; };
                AF14EE300E3CEF1A004CBBD2 /* XScreenSaver.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = XScreenSaver.icns; path = OSX/XScreenSaver.icns; sourceTree = "<group>"; };
                AF1A17730D6D6EE3008AF328 /* LCDscrub.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = LCDscrub.saver; sourceTree = BUILT_PRODUCTS_DIR; };
                AF1A177E0D6D6F3E008AF328 /* lcdscrub.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; name = lcdscrub.c; path = hacks/lcdscrub.c; sourceTree = "<group>"; };
                AF1A17800D6D6F62008AF328 /* lcdscrub.xml */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text.xml; path = lcdscrub.xml; sourceTree = "<group>"; };
+               AF32D9F40F3AD0B40080F535 /* RubikBlocks.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RubikBlocks.saver; sourceTree = BUILT_PRODUCTS_DIR; };
+               AF32D9FA0F3AD1200080F535 /* rubikblocks.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; name = rubikblocks.c; path = hacks/glx/rubikblocks.c; sourceTree = "<group>"; };
+               AF32D9FC0F3AD1330080F535 /* rubikblocks.xml */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text.xml; path = rubikblocks.xml; sourceTree = "<group>"; };
                AF34085409B80AAF00F2CEC1 /* StarWars.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = StarWars.saver; sourceTree = BUILT_PRODUCTS_DIR; };
                AF34085509B80AB000F2CEC1 /* StonerView.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = StonerView.saver; sourceTree = BUILT_PRODUCTS_DIR; };
                AF34085609B80AB000F2CEC1 /* Gleidescope.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Gleidescope.saver; sourceTree = BUILT_PRODUCTS_DIR; };
                AF48E1660A0C268500F94CF9 /* glschool.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; name = glschool.c; path = hacks/glx/glschool.c; sourceTree = "<group>"; };
                AF48E1670A0C268500F94CF9 /* glschool.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; name = glschool.h; path = hacks/glx/glschool.h; sourceTree = "<group>"; };
                AF48E16B0A0C26A400F94CF9 /* glschool.xml */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text.xml; path = glschool.xml; sourceTree = "<group>"; };
+               AF4A345D102A593600A81B2A /* Surfaces.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Surfaces.saver; sourceTree = BUILT_PRODUCTS_DIR; };
+               AF4A3461102A59EB00A81B2A /* surfaces.xml */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text.xml; path = surfaces.xml; sourceTree = "<group>"; };
+               AF4A3463102A5A0E00A81B2A /* surfaces.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; name = surfaces.c; path = hacks/glx/surfaces.c; sourceTree = "<group>"; };
                AF4FD6FA0CE7A486005EE58E /* Lockward.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Lockward.saver; sourceTree = BUILT_PRODUCTS_DIR; };
                AF4FD7000CE7A577005EE58E /* lockward.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; name = lockward.c; path = hacks/glx/lockward.c; sourceTree = "<group>"; };
                AF4FD7020CE7A5BC005EE58E /* lockward.xml */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text.xml; path = lockward.xml; sourceTree = "<group>"; };
                AFC25B9A0988BC08000655EE /* colors.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; name = colors.h; path = utils/colors.h; sourceTree = "<group>"; };
                AFCCCBAD09BFE4B000353F4D /* rdbomb.xml */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text.xml; path = rdbomb.xml; sourceTree = "<group>"; };
                AFD51B300F063B4A00471C02 /* Photopile.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Photopile.saver; sourceTree = BUILT_PRODUCTS_DIR; };
-               AFD51B330F063B4B00471C02 /* XScreenSaver copy.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "XScreenSaver copy.plist"; path = "OSX/XScreenSaver copy.plist"; sourceTree = "<group>"; };
                AFD51DB60F063BCE00471C02 /* photopile.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; name = photopile.c; path = hacks/glx/photopile.c; sourceTree = "<group>"; };
                AFD51DB80F063BE700471C02 /* photopile.xml */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text.xml; path = photopile.xml; sourceTree = "<group>"; };
                AFD56E040996A03800BA26F7 /* GLText.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = GLText.saver; sourceTree = BUILT_PRODUCTS_DIR; };
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AF32D9E80F3AD0B40080F535 /* Frameworks */ = {
+                       isa = PBXFrameworksBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF32D9E90F3AD0B40080F535 /* libjwxyz.a in Frameworks */,
+                               AF32D9EA0F3AD0B40080F535 /* ScreenSaver.framework in Frameworks */,
+                               AF32D9EB0F3AD0B40080F535 /* Cocoa.framework in Frameworks */,
+                               AF32D9EC0F3AD0B40080F535 /* AGL.framework in Frameworks */,
+                               AF32D9ED0F3AD0B40080F535 /* OpenGL.framework in Frameworks */,
+                               AF32D9EE0F3AD0B40080F535 /* Carbon.framework in Frameworks */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AF35E8940E63823600691F2F /* Frameworks */ = {
                        isa = PBXFrameworksBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AF4A3451102A593600A81B2A /* Frameworks */ = {
+                       isa = PBXFrameworksBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF4A3452102A593600A81B2A /* libjwxyz.a in Frameworks */,
+                               AF4A3453102A593600A81B2A /* ScreenSaver.framework in Frameworks */,
+                               AF4A3454102A593600A81B2A /* Cocoa.framework in Frameworks */,
+                               AF4A3455102A593600A81B2A /* AGL.framework in Frameworks */,
+                               AF4A3456102A593600A81B2A /* OpenGL.framework in Frameworks */,
+                               AF4A3457102A593600A81B2A /* Carbon.framework in Frameworks */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AF4FD6EE0CE7A486005EE58E /* Frameworks */ = {
                        isa = PBXFrameworksBuildPhase;
                        buildActionMask = 2147483647;
                                AF77786D09B6536000EA3033 /* AGL.framework in Frameworks */,
                                AF77786E09B6536000EA3033 /* OpenGL.framework in Frameworks */,
                                AF77786F09B6536000EA3033 /* Carbon.framework in Frameworks */,
+                               AF0F46DD104E1809000A929C /* AppKit.framework in Frameworks */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                AFE30BFC0E52B14700CCF4A5 /* Sonar.saver */,
                                AF35E8A00E63823600691F2F /* Jigsaw.saver */,
                                AFD51B300F063B4A00471C02 /* Photopile.saver */,
+                               AF32D9F40F3AD0B40080F535 /* RubikBlocks.saver */,
+                               AF4A345D102A593600A81B2A /* Surfaces.saver */,
                        );
                        name = Products;
                        sourceTree = "<group>";
                                29B97317FDCFA39411CA2CEA /* Resources */,
                                29B97323FDCFA39411CA2CEA /* Frameworks */,
                                19C28FACFE9D520D11CA2CBB /* Products */,
+                               AF0F46DC104E1809000A929C /* AppKit.framework */,
                        );
                        name = xscreensaver;
                        sourceTree = "<group>";
                                8D1107310486CEB800E47090 /* XScreenSaver.plist */,
                                AF0FAF1209CA712600EE1051 /* xscreensaver-getimage-file */,
                                AF0FAF0B09CA6FF900EE1051 /* xscreensaver-text */,
-                               AFD51B330F063B4B00471C02 /* XScreenSaver copy.plist */,
                        );
                        name = Resources;
                        sourceTree = "<group>";
                AF480DD0098F4F2000FB32B8 /* OpenGL */ = {
                        isa = PBXGroup;
                        children = (
+                               AF32D9FA0F3AD1200080F535 /* rubikblocks.c */,
                                AFE6A40B0CDD7BC3002805BF /* moebiusgears.c */,
                                AF642409099FFAF0000F4CD4 /* extrusion-helix2.c */,
                                AF64240A099FFAF0000F4CD4 /* extrusion-helix3.c */,
                                AF998EF80A083E750051049D /* topblock.c */,
                                AFE6A16A0CDD78EA002805BF /* involute.c */,
                                AFE6A16B0CDD78EA002805BF /* involute.h */,
+                               AF4A3463102A5A0E00A81B2A /* surfaces.c */,
                                AF0DCA5F0C4CBB7300D76972 /* voronoi.c */,
                                AFA563660993970F00F3E977 /* cube21.c */,
                                AF4FF4D00D52CC8400666F98 /* cubicgrid.c */,
                AFC258670988A468000655EE /* config */ = {
                        isa = PBXGroup;
                        children = (
+                               AF32D9FC0F3AD1330080F535 /* rubikblocks.xml */,
                                AFE6A4360CDD8026002805BF /* abstractile.xml */,
                                AFE6A40D0CDD7BDC002805BF /* moebiusgears.xml */,
                                AFC258680988A468000655EE /* anemone.xml */,
                                AFC258CF0988A468000655EE /* jigsaw.xml */,
                                AFC258D00988A468000655EE /* juggle.xml */,
                                AFC258D10988A468000655EE /* juggler3d.xml */,
+                               AF4A3461102A59EB00A81B2A /* surfaces.xml */,
                                AFC258D20988A468000655EE /* julia.xml */,
                                AFC258D30988A468000655EE /* kaleidescope.xml */,
                                AFC258D40988A468000655EE /* klein.xml */,
                        productReference = AF1A17730D6D6EE3008AF328 /* LCDscrub.saver */;
                        productType = "com.apple.product-type.bundle";
                };
+               AF32D9E00F3AD0B40080F535 /* RubikBlocks */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = AF32D9F10F3AD0B40080F535 /* Build configuration list for PBXNativeTarget "RubikBlocks" */;
+                       buildPhases = (
+                               AF32D9E30F3AD0B40080F535 /* Resources */,
+                               AF32D9E50F3AD0B40080F535 /* Sources */,
+                               AF32D9E80F3AD0B40080F535 /* Frameworks */,
+                               AF32D9EF0F3AD0B40080F535 /* Rez */,
+                               AF32D9F00F3AD0B40080F535 /* ShellScript */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                               AF32D9E10F3AD0B40080F535 /* PBXTargetDependency */,
+                       );
+                       name = RubikBlocks;
+                       productName = Rubik;
+                       productReference = AF32D9F40F3AD0B40080F535 /* RubikBlocks.saver */;
+                       productType = "com.apple.product-type.bundle";
+               };
                AF35E88A0E63823600691F2F /* Jigsaw */ = {
                        isa = PBXNativeTarget;
                        buildConfigurationList = AF35E89D0E63823600691F2F /* Build configuration list for PBXNativeTarget "Jigsaw" */;
                        productReference = AF48DF030A0C25E000F94CF9 /* GLSchool.saver */;
                        productType = "com.apple.product-type.bundle";
                };
+               AF4A3449102A593600A81B2A /* Surfaces */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = AF4A345A102A593600A81B2A /* Build configuration list for PBXNativeTarget "Surfaces" */;
+                       buildPhases = (
+                               AF4A344C102A593600A81B2A /* Resources */,
+                               AF4A344E102A593600A81B2A /* Sources */,
+                               AF4A3451102A593600A81B2A /* Frameworks */,
+                               AF4A3458102A593600A81B2A /* Rez */,
+                               AF4A3459102A593600A81B2A /* ShellScript */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                               AF4A344A102A593600A81B2A /* PBXTargetDependency */,
+                       );
+                       name = Surfaces;
+                       productName = Klein;
+                       productReference = AF4A345D102A593600A81B2A /* Surfaces.saver */;
+                       productType = "com.apple.product-type.bundle";
+               };
                AF4FD6E60CE7A486005EE58E /* Lockward */ = {
                        isa = PBXNativeTarget;
                        buildConfigurationList = AF4FD6F70CE7A486005EE58E /* Build configuration list for PBXNativeTarget "Lockward" */;
                29B97313FDCFA39411CA2CEA /* Project object */ = {
                        isa = PBXProject;
                        buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "xscreensaver" */;
-                       compatibilityVersion = "Xcode 2.4";
+                       compatibilityVersion = "Xcode 3.0";
                        hasScannedForEncodings = 1;
                        mainGroup = 29B97314FDCFA39411CA2CEA /* xscreensaver */;
                        projectDirPath = "";
                                AFD56F230996AB8A00BA26F7 /* Galaxy */,
                                AFD56F4F0996AEEE00BA26F7 /* Grav */,
                                AFD56F6B0996B01600BA26F7 /* Hopalong */,
-                               AFD571B50996D9DC00BA26F7 /* Juggle */,
                                AFD572F9099701C000BA26F7 /* Julia */,
                                AF794FCD09974FA60059A8B0 /* Loop */,
                                AFD5706F0996B72700BA26F7 /* Mountain */,
                                AFA55B2509933E8D00F3E977 /* Pulsar */,
                                AFA55DF009935E4900F3E977 /* Queens */,
                                AFA559CF0993330600F3E977 /* Rubik */,
+                               AF32D9E00F3AD0B40080F535 /* RubikBlocks */,
                                AFA55D3C0993565300F3E977 /* SBalls */,
                                AFA55B7909933F7200F3E977 /* Sierpinski3D */,
                                AFE2A4560E2E904600ADB298 /* SkyTentacles */,
                                AF77781009B6504400EA3033 /* StarWars */,
                                AF7777A809B64B2600EA3033 /* StonerView */,
                                AFA559920993322100F3E977 /* Superquadrics */,
+                               AF4A3449102A593600A81B2A /* Surfaces */,
                                AFA562F20993943B00F3E977 /* Tangram */,
                                AFA56379099397B300F3E977 /* TimeTunnel */,
                                AF998EDA0A083DB30051049D /* TopBlock */,
                                AF0DCA420C4CBB0D00D76972 /* Voronoi */,
-                               AF9771D60989DC4A001F8B92 /* SaverTester */,
-                               AF137D410F075C9B004DE3B2 /* Obsolete */,
                                AF6427A809A2DE36000F4CD4 /* Bubbles */,
                                AF47765A099DA78E001F091E /* Critical */,
                                AF477909099DE379001F091E /* Flag */,
                                AFD56EDA0996A95700BA26F7 /* Forest */,
                                AFA55CCC09934CE400F3E977 /* GLForestFire */,
+                               AFD571B50996D9DC00BA26F7 /* Juggle */,
                                AF4774B4099D8B5F001F091E /* LMorph */,
                                AFD56F8C0996B09400BA26F7 /* Laser */,
                                AFD56FA30996B10F00BA26F7 /* Lightning */,
                                AFD56F0B0996AAFA00BA26F7 /* Vines */,
                                AF477208099D4EE8001F091E /* Whirlygig */,
                                AFD5709B0996B88E00BA26F7 /* Worm */,
+                               AF137D410F075C9B004DE3B2 /* Obsolete */,
+                               AF9771D60989DC4A001F8B92 /* SaverTester */,
                        );
                };
 /* End PBXProject section */
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AF32D9E30F3AD0B40080F535 /* Resources */ = {
+                       isa = PBXResourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF32D9FD0F3AD1330080F535 /* rubikblocks.xml in Resources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AF35E88D0E63823600691F2F /* Resources */ = {
                        isa = PBXResourcesBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AF4A344C102A593600A81B2A /* Resources */ = {
+                       isa = PBXResourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF4A3462102A59EB00A81B2A /* surfaces.xml in Resources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AF4FD6E90CE7A486005EE58E /* Resources */ = {
                        isa = PBXResourcesBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AF32D9EF0F3AD0B40080F535 /* Rez */ = {
+                       isa = PBXRezBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AF35E89B0E63823600691F2F /* Rez */ = {
                        isa = PBXRezBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AF4A3458102A593600A81B2A /* Rez */ = {
+                       isa = PBXRezBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AF4FD6F50CE7A486005EE58E /* Rez */ = {
                        isa = PBXRezBuildPhase;
                        buildActionMask = 2147483647;
                        shellScript = "$SOURCE_ROOT/OSX/update-info-plist.pl $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX";
                        showEnvVarsInLog = 0;
                };
+               AF32D9F00F3AD0B40080F535 /* ShellScript */ = {
+                       isa = PBXShellScriptBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       inputPaths = (
+                       );
+                       outputPaths = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+                       shellPath = /bin/sh;
+                       shellScript = "$SOURCE_ROOT/OSX/update-info-plist.pl $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX";
+                       showEnvVarsInLog = 0;
+               };
                AF35E89C0E63823600691F2F /* ShellScript */ = {
                        isa = PBXShellScriptBuildPhase;
                        buildActionMask = 2147483647;
                        shellScript = "$SOURCE_ROOT/OSX/update-info-plist.pl $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX";
                        showEnvVarsInLog = 0;
                };
+               AF4A3459102A593600A81B2A /* ShellScript */ = {
+                       isa = PBXShellScriptBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       inputPaths = (
+                       );
+                       outputPaths = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+                       shellPath = /bin/sh;
+                       shellScript = "$SOURCE_ROOT/OSX/update-info-plist.pl $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX";
+                       showEnvVarsInLog = 0;
+               };
                AF4FD6F60CE7A486005EE58E /* ShellScript */ = {
                        isa = PBXShellScriptBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AF32D9E50F3AD0B40080F535 /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF32D9E70F3AD0B40080F535 /* XScreenSaverSubclass.m in Sources */,
+                               AF32D9FB0F3AD1200080F535 /* rubikblocks.c in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AF35E88F0E63823600691F2F /* Sources */ = {
                        isa = PBXSourcesBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AF4A344E102A593600A81B2A /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF4A3450102A593600A81B2A /* XScreenSaverSubclass.m in Sources */,
+                               AF4A3464102A5A0E00A81B2A /* surfaces.c in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AF4FD6EB0CE7A486005EE58E /* Sources */ = {
                        isa = PBXSourcesBuildPhase;
                        buildActionMask = 2147483647;
                        target = AF1A17610D6D6EE3008AF328 /* LCDscrub */;
                        targetProxy = AF1A17830D6D6FA7008AF328 /* PBXContainerItemProxy */;
                };
+               AF32D9E10F3AD0B40080F535 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
+                       targetProxy = AF32D9E20F3AD0B40080F535 /* PBXContainerItemProxy */;
+               };
+               AF32D9F90F3AD0D90080F535 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AF32D9E00F3AD0B40080F535 /* RubikBlocks */;
+                       targetProxy = AF32D9F80F3AD0D90080F535 /* PBXContainerItemProxy */;
+               };
                AF35E88B0E63823600691F2F /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
                        target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
                        target = AF48DEEF0A0C25E000F94CF9 /* GLSchool */;
                        targetProxy = AF48DF050A0C261100F94CF9 /* PBXContainerItemProxy */;
                };
+               AF4A344A102A593600A81B2A /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
+                       targetProxy = AF4A344B102A593600A81B2A /* PBXContainerItemProxy */;
+               };
+               AF4A3460102A59A400A81B2A /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AF4A3449102A593600A81B2A /* Surfaces */;
+                       targetProxy = AF4A345F102A59A400A81B2A /* PBXContainerItemProxy */;
+               };
                AF4FD6E70CE7A486005EE58E /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
                        target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
                        target = AFD572F9099701C000BA26F7 /* Julia */;
                        targetProxy = AF7779B609B6608100EA3033 /* PBXContainerItemProxy */;
                };
-               AF7779B909B6608100EA3033 /* PBXTargetDependency */ = {
-                       isa = PBXTargetDependency;
-                       target = AFD571B50996D9DC00BA26F7 /* Juggle */;
-                       targetProxy = AF7779B809B6608100EA3033 /* PBXContainerItemProxy */;
-               };
                AF7779BB09B6608100EA3033 /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
                        target = AFD56F6B0996B01600BA26F7 /* Hopalong */;
                        target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
                        targetProxy = AFA563A6099398BB00F3E977 /* PBXContainerItemProxy */;
                };
+               AFB581B0102F363300342B11 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AFD571B50996D9DC00BA26F7 /* Juggle */;
+                       targetProxy = AFB581AF102F363300342B11 /* PBXContainerItemProxy */;
+               };
                AFCAD5F90992DFE00009617A /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
                        target = AF9771D60989DC4A001F8B92 /* SaverTester */;
                        };
                        name = Release;
                };
+               AF32D9F20F3AD0B40080F535 /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = (
+                                       "USE_GL=1",
+                                       "$(GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS)",
+                               );
+                       };
+                       name = Debug;
+               };
+               AF32D9F30F3AD0B40080F535 /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = (
+                                       "USE_GL=1",
+                                       "$(GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS)",
+                               );
+                       };
+                       name = Release;
+               };
                AF35E89E0E63823600691F2F /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
                        };
                        name = Release;
                };
+               AF4A345B102A593600A81B2A /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = (
+                                       "USE_GL=1",
+                                       "$(GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS)",
+                               );
+                       };
+                       name = Debug;
+               };
+               AF4A345C102A593600A81B2A /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = (
+                                       "USE_GL=1",
+                                       "$(GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS)",
+                               );
+                       };
+                       name = Release;
+               };
                AF4FD6F80CE7A486005EE58E /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
                                GCC_DYNAMIC_NO_PIC = NO;
                                GCC_ENABLE_FIX_AND_CONTINUE = YES;
                                GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
-                               GCC_MODEL_TUNING = G5;
                                GCC_OPTIMIZATION_LEVEL = 0;
                                GCC_PRECOMPILE_PREFIX_HEADER = YES;
                                GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h";
                                COPY_PHASE_STRIP = YES;
                                GCC_ENABLE_FIX_AND_CONTINUE = NO;
                                GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
-                               GCC_MODEL_TUNING = G5;
                                GCC_PRECOMPILE_PREFIX_HEADER = YES;
                                GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h";
                                INSTALL_PATH = "$(HOME)/bin";
                C01FCF4F08A954540054247B /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
+                               ARCHS = "$(NATIVE_ARCH_ACTUAL)";
                                COPY_PHASE_STRIP = NO;
-                               GCC_MODEL_TUNING = G5;
+                               GCC_ENABLE_OBJC_GC = supported;
                                GCC_OPTIMIZATION_LEVEL = 0;
                                GCC_PRECOMPILE_PREFIX_HEADER = YES;
                                GCC_PREFIX_HEADER = OSX/xscreensaver_Prefix.pch;
                                        "CLASS=XScreenSaver${EXECUTABLE_NAME}View",
                                        "$(GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS)",
                                );
+                               GCC_VERSION = 4.0;
                                GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
                                GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
                                GCC_WARN_ABOUT_RETURN_TYPE = YES;
                                GCC_WARN_CHECK_SWITCH_STATEMENTS = YES;
-                               GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO;
+                               GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES;
                                GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES;
                                GCC_WARN_MISSING_PARENTHESES = YES;
                                GCC_WARN_SHADOW = NO;
                                );
                                PREBINDING = NO;
                                PRODUCT_NAME = "$(TARGET_NAME)";
-                               SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk;
+                               SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.4u.sdk";
+                               "SDKROOT[arch=x86_64]" = "$(DEVELOPER_SDK_DIR)/MacOSX10.6.sdk";
                                USER_HEADER_SEARCH_PATHS = "$(PROJECT_DIR) $(USER_HEADER_SEARCH_PATHS)";
                                WARNING_CFLAGS = "-Wimplicit";
                                WRAPPER_EXTENSION = saver;
                C01FCF5008A954540054247B /* Release */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
-                               ARCHS = (
-                                       ppc,
-                                       i386,
-                               );
+                               ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
+                               ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
+                               GCC_ENABLE_OBJC_GC = supported;
                                GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
-                               GCC_MODEL_TUNING = G5;
                                GCC_PRECOMPILE_PREFIX_HEADER = YES;
                                GCC_PREFIX_HEADER = OSX/xscreensaver_Prefix.pch;
                                GCC_PREPROCESSOR_DEFINITIONS = (
                                        "CLASS=XScreenSaver${EXECUTABLE_NAME}View",
                                        "$(GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS)",
                                );
+                               GCC_VERSION = 4.0;
                                GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
                                GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
                                GCC_WARN_ABOUT_RETURN_TYPE = YES;
                                GCC_WARN_CHECK_SWITCH_STATEMENTS = YES;
-                               GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO;
+                               GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES;
                                GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES;
                                GCC_WARN_MISSING_PARENTHESES = YES;
                                GCC_WARN_SHADOW = NO;
                                );
                                PREBINDING = NO;
                                PRODUCT_NAME = "$(TARGET_NAME)";
-                               SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk;
+                               SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.4u.sdk";
+                               "SDKROOT[arch=x86_64]" = "$(DEVELOPER_SDK_DIR)/MacOSX10.6.sdk";
                                USER_HEADER_SEARCH_PATHS = "$(PROJECT_DIR) $(USER_HEADER_SEARCH_PATHS)";
                                WARNING_CFLAGS = "-Wimplicit";
                                WRAPPER_EXTENSION = saver;
                        defaultConfigurationIsVisible = 0;
                        defaultConfigurationName = Release;
                };
+               AF32D9F10F3AD0B40080F535 /* Build configuration list for PBXNativeTarget "RubikBlocks" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               AF32D9F20F3AD0B40080F535 /* Debug */,
+                               AF32D9F30F3AD0B40080F535 /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
                AF35E89D0E63823600691F2F /* Build configuration list for PBXNativeTarget "Jigsaw" */ = {
                        isa = XCConfigurationList;
                        buildConfigurations = (
                        defaultConfigurationIsVisible = 0;
                        defaultConfigurationName = Release;
                };
+               AF4A345A102A593600A81B2A /* Build configuration list for PBXNativeTarget "Surfaces" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               AF4A345B102A593600A81B2A /* Debug */,
+                               AF4A345C102A593600A81B2A /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
                AF4FD6F70CE7A486005EE58E /* Build configuration list for PBXNativeTarget "Lockward" */ = {
                        isa = XCConfigurationList;
                        buildConfigurations = (