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.
  */
 
 /* Implment all setter methods in terms of "setDoubleValue", above.
  */
 
--(void) setFloatValue:(double)v
+-(void) setFloatValue:(float)v
 {
   [self setDoubleValue:(double)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"'         \
                                                                              \
   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                                                \
       ../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
  *
  * 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);
   }
 
     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;
 }
 
   return result;
 }
 
index 4ea79aaae06933b72fefdbfb29e111c41abee197..a2ab493756581e8bc669dbe0694a2f67050bb2c1 100644 (file)
@@ -184,7 +184,7 @@ find_saverView (NSView *v)
     [NSUserDefaultsController sharedUserDefaultsController];
   [prefs addObserver:self
          forKeyPath:key
     [NSUserDefaultsController sharedUserDefaultsController];
   [prefs addObserver:self
          forKeyPath:key
-            options:nil
+            options:0
             context:@selector(selectedSaverDidChange:)];
   [popup   bind:@"selectedObject"
        toObject:prefs
             context:@selector(selectedSaverDidChange:)];
   [popup   bind:@"selectedObject"
        toObject:prefs
index 4a5dcba74ca7478cc163d32c7da17c3878e3e3df..edcbb3583219bfff058557bd0e33b4c4f2fa6d25 100644 (file)
        <key>CFBundlePackageType</key>
        <string>APPL</string>
        <key>CFBundleShortVersionString</key>
        <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>
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleVersion</key>
-       <string>5.08</string>
+       <string>5.09</string>
        <key>LSMinimumSystemVersion</key>
        <key>LSMinimumSystemVersion</key>
-       <string>10.4.0</string>
+       <string>10.4</string>
        <key>NSMainNibFile</key>
        <string>SaverTester</string>
        <key>NSPrincipalClass</key>
        <key>NSMainNibFile</key>
        <string>SaverTester</string>
        <key>NSPrincipalClass</key>
index 48fcdd0d139c363442dac1ea7654da79af6f0368..c3f76020cc4348a8a466abc0ab9013810f5ada0c 100644 (file)
        <key>CFBundlePackageType</key>
        <string>BNDL</string>
        <key>CFBundleShortVersionString</key>
        <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>
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleVersion</key>
-       <string>5.08</string>
+       <string>5.09</string>
        <key>LSMinimumSystemVersion</key>
        <key>LSMinimumSystemVersion</key>
-       <string>10.4.0</string>
+       <string>10.4</string>
        <key>NSMainNibFile</key>
        <string>SaverTester</string>
        <key>NSPrincipalClass</key>
        <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
  *
  * 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];
                                      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];
 
     file = [file stringByAbbreviatingWithTildeInPath];
     [txt setStringValue:file];
 
@@ -1047,6 +1047,7 @@ static char *
 anchorize (const char *url)
 {
   const char *wiki = "http://en.wikipedia.org/wiki/";
 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: \"");
   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;
 
     *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);
   }
   } 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;
   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.
   [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]);
   }
   
 //          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.
    */
   /* 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
 *
 * 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 "XScreenSaverView.h"
-#import <AGL/agl.h>
+#import <AppKit/NSOpenGL.h>
 
 @interface XScreenSaverGLView : XScreenSaverView
 {
 
 @interface XScreenSaverGLView : XScreenSaverView
 {
-  AGLContext agl_ctx;      // OpenGL rendering context
+  NSOpenGLContext *ogl_ctx;      // OpenGL rendering context
 }
 
 @end
 }
 
 @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
 *
 * 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
 
 
 @implementation XScreenSaverGLView
 
+#if 0
 - (void) dealloc
 {
 - (void) dealloc
 {
-  if (agl_ctx)
-    aglDestroyContext (agl_ctx);
+  /* #### Do we have to destroy ogl_ctx? */
   [super dealloc];
 }
   [super dealloc];
 }
+#endif
 
 
 - (void)stopAnimation
 
 
 - (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.
   //
   // 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
 {
 }
 
 
 // #### 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
 {
 - (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
 {
 }
 
 
 - (void)drawRect:(NSRect)rect
 {
-  if (! agl_ctx)
+  if (! ogl_ctx)
     [super drawRect:rect];
 }
 
 
     [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
 
   [self resizeContext];
 }
 
 @end
 
+
 /* Utility functions...
  */
 
 /* Utility functions...
  */
 
@@ -123,35 +104,38 @@ init_GL (ModeInfo *mi)
 {
   Window win = mi->window;
   XScreenSaverGLView *view = (XScreenSaverGLView *) jwxyz_window_view (win);
 {
   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;
   // 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.
 
   // 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;
   // 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);
 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)
  */
 void
 glXMakeCurrent (Display *dpy, Window window, GLXContext context)
@@ -197,41 +182,6 @@ clear_gl_error (void)
 {
   while (glGetError() != GL_NO_ERROR)
     ;
 {
   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)
 {
 void
 check_gl_error (const char *type)
 {
-  check_agl_error (type);
-  
   char buf[100];
   GLenum i;
   const char *e;
   char buf[100];
   GLenum i;
   const char *e;
index 932e7db776b680ca156010b03f4f4e295427f55b..528c4f6c5b0a36e3032445aea201d4a230a35957 100644 (file)
@@ -81,7 +81,7 @@ int mono_p = 0;
     perror ("putenv");
     abort();
   }
     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\
 \
 \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
 \
 {\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
  *
  * 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);
 
 // 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.) */
 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
  *
  * 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 <stdlib.h>
+#import <stdint.h>
 #import <Cocoa/Cocoa.h>
 #import "jwxyz.h"
 #import "jwxyz-timers.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.
 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)      ));
                   (((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)
 {
 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)
 {
 }
 
 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)) +
     (y * (ximage->bytes_per_line >> 2)) +
-    x) = pixel;
+    x) = (uint32_t) pixel;
   return 0;
 }
 
   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;
            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");
   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;
     nsfrom.size.height = height;
     [bm initWithFocusedViewRect:nsfrom];
     depth = 32;
+    alpha_first_p = ([bm bitmapFormat] & NSAlphaFirstBitmapFormat);
     ibpp = [bm bitsPerPixel];
     ibpl = [bm bytesPerRow];
     data = [bm bitmapData];
     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).
   /* 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) {
    */
   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++) {
 
       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));
       }
 
         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;
 
       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;
     }
       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)
 {
 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);
   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,
   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
  *
  * 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 <stdlib.h>
+#import <stdint.h>
 #import <Cocoa/Cocoa.h>
 #import "jwxyz.h"
 #import "grabscreen.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;
 
   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:
 
   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++) {
     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++) {
       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;
         // 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);
         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;
       }
         // 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 */
       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;
       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;
       }
 
         map[y] = pixel;
       }
 
@@ -254,3 +255,4 @@ osx_load_image_file (Screen *screen, Window xwindow, Drawable drawable,
   [img release];
   return True;
 }
   [img release];
   return True;
 }
+
index 069d0c3b6ea47f5c246a43f0503362f7fab51e0b..3f39bd09df1aeeea554d9f3c5865cf0d3515a2e1 100755 (executable)
@@ -1,5 +1,5 @@
 #!/usr/bin/perl -w
 #!/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
 #
 # 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;
 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;
 
 
 my $verbose = 1;
 
@@ -72,6 +72,7 @@ sub update_saver_xml($$) {
   $desc =~ s/\s*$//s;
 
   # in case it's done already...
   $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;
   $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)) {
   #
   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";
       $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.
   $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;
 
   $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
 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'.
                         `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.
 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*)
 
     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
         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
       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
 LOCK_OBJS
 JPEG_EXES
 GL_EXES
+RETIRED_GL_EXES
 SUID_EXES
 GL_UTIL_EXES
 GL_MEN
 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
   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
    { 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
 
    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; }
    #
    { 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
 else
   ac_cv_header_stdc=no
 fi
-rm -rf conftest*
+rm -f -r conftest*
 
 fi
 
 
 fi
 
@@ -4406,7 +4417,7 @@ if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
 else
   ac_cv_header_stdc=no
 fi
 else
   ac_cv_header_stdc=no
 fi
-rm -rf conftest*
+rm -f -r conftest*
 
 fi
 
 
 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.
       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
       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_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
     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
 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
 
 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.
 
 
     # 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_CPPFLAGS="$CPPFLAGS"
-  ac_save_LDFLAGS="$LDFLAGS"
-#  ac_save_LIBS="$LIBS"
-
   if test \! -z "$includedir" ; then
     CPPFLAGS="$CPPFLAGS -I$includedir"
   fi
   if test \! -z "$includedir" ; then
     CPPFLAGS="$CPPFLAGS -I$includedir"
   fi
-  # note: $X_CFLAGS includes $x_includes
   CPPFLAGS="$CPPFLAGS $X_CFLAGS"
   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`
   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.  */
 /* 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 ()
 {
 int
 main ()
 {
-return XRRGetOutputInfo ();
+XRRScreenResources *res =
+                           XRRGetScreenResources (0, 0);
   ;
   return 0;
 }
 _ACEOF
   ;
   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
 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
   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
   (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
 
 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
 
 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
 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
 
 #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
 
 
   fi
 
 
@@ -12735,7 +12723,7 @@ else
   { echo "$as_me:$LINENO: result: no" >&5
 echo "${ECHO_T}no" >&6; }
 fi
   { echo "$as_me:$LINENO: result: no" >&5
 echo "${ECHO_T}no" >&6; }
 fi
-rm -rf conftest*
+rm -f -r conftest*
 
   CPPFLAGS="$ac_save_CPPFLAGS"
 
 
   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
   $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
 
   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
   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
 #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)'
 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=" "
   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
 
 
 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
 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
 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
 
 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
     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*)
 
  ;;
     "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
         sed -e "/POTFILES =/r po/POTFILES" po/Makefile.in > po/Makefile
+        mv po/stamp-it.tmp po/stamp-it
       esac ;;
 
   esac
       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
 
 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_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
 
 
   fi
 
 
@@ -3601,7 +3623,7 @@ tab='     '
 if test "$have_gl" = yes; then
   GL_EXES='$(GL_EXES)'
   SUID_EXES='$(SUID_EXES)'
 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=" "
   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(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)
 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
 
 #
 # 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
 !
 !            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/
 !
 ! 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\
 - 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\
 @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:                          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\
                                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\
                                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\
                                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\
 @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:                                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\
 -                              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.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
 *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\
 - 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:                          lavalite -root                              \\n\
 -                              polyominoes -root                           \\n\
   GL:                          queens -root                                \\n\
 - GL:                          glslideshow -root                           \\n\
   GL:                          hypertorus -root                            \\n\
 - GL:                          jigglypuff -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\
                                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\
                                xanalogtv -root                             \\n\
 -                              abstractile -root                           \\n\
                                anemotaxis -root                            \\n\
                                fiberlamp -root                             \\n\
   GL:                          fliptext -root                              \\n\
   GL:                          glhanoi -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:                          tangram -root                               \\n\
   GL:                          timetunnel -root                            \\n\
   GL:                          glschool -root                              \\n\
   GL:                          moebiusgears -root                          \\n\
   GL:                          voronoi -root                               \\n\
   GL:                          hypnowheel -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\
 -                              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",
 "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.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",
 "*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
 /* 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
  *
  * 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/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!
    */
 
   /* 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,
  * (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
  *
  * 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;
          
          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 */
 
          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
  *
  * 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)
 {
 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];
   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;
        }
          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 :
               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;
               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;
 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. */
 
   /* 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)
     {
 
   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)
          {
       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:
        break;
 
       case ClientMessage:
-       if (handle_clientmessage (si, &event, until_idle_p))
+       if (handle_clientmessage (si, &event.x_event, until_idle_p))
          goto DONE;
        break;
 
          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)
          {
            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;
            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;
             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";*/
               {
                 /*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";
               {
                 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;
               }
                 x = y = -1;
               }
-           else if (event.xany.type == ButtonPress)
+           else if (event.x_event.xany.type == ButtonPress)
               {
                 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)
               }
 
             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. */
 
                 /* 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;
                   {
                     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)",
                     fprintf (stderr, " (%s%s)",
-                             (event.xkey.send_event ? "synthetic " : ""),
+                             (event.x_event.xkey.send_event ? "synthetic " : ""),
                              XKeysymToString (keysym));
                   }
 
                              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. */
          }
 
        /* 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
 
         
         /* 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.
          */
            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++)
           {
             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)
                   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 &&
        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. */
              ;
              /* 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
       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.)
              */
          {
             /* 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)
              {
                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);
                  }
 
                      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",
                  {
                    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;
              }
                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",
              {
                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",
            else
              fprintf (stderr,
                       "%s: unknown MIT-SCREEN-SAVER event %d received!\n",
-                      blurb(), sevent->state);
+                      blurb(), event.sevent.state);
          }
        else
 
          }
        else
 
@@ -989,7 +1000,7 @@ sleep_until_idle (saver_info *si, Bool until_idle_p)
 
 
 #ifdef HAVE_SGI_SAVER_EXTENSION
 
 
 #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. */
          {
             /* 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;
          }
            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,
                                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
 #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.
              */
           {
             /* 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 */
             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. */
                 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. */
 # 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. */
 #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:
       }
     }
  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)
      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),
   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
 #!/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
 #
 # 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
 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;
 
 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;
 
 
 my $verbose = 0;
 
@@ -236,14 +238,14 @@ sub read_cache($) {
     $cache_file_name = "$ENV{HOME}/.xscreensaver-getimage.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: $!");
 
   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) {
   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
 #!/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
 #
 # 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;
 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;
 
 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};
 
 
   # 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);
   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';
     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';
                               $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';
                               $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';
                               $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; }
                               $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 \
                  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 \
                  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 \
 
 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@
 
 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 \
                  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 \
                  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 \
 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 \
 
 STAR           = *
 EXTRAS         = README Makefile.in xml2man.pl m6502.sh .gdbinit \
@@ -349,13 +349,13 @@ install-xml:
        done
 
 uninstall-program:
        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:
          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* ;          \
        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) ;                       \
 
 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:
             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 *~ "#"*
 
 distclean: clean
        -rm -f Makefile TAGS *~ "#"*
@@ -968,1829 +968,3 @@ webcollage-helper: webcollage-helper.o
 #
 # DO NOT DELETE: updated by make distdepend
 
 #
 # 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
 
             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/
 
 
                      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"
 
     <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"
 
     <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"
 
     <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.
 
   <_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
 
 
 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"
    <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"/>
 
             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>
-
    <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>
   </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>
 
   <_description>
-3D simulation of a juggler performing with balls, clubs and rings.  
+Draws a 3D juggling stick-man.
 
 http://en.wikipedia.org/wiki/Siteswap
 
 
 http://en.wikipedia.org/wiki/Siteswap
 
-Written by Brian Apps; 2005.
+Written by Tim Auckland and Jamie Zawinski; 2002.
   </_description>
 </screensaver>
   </_description>
 </screensaver>
index 0cd83fa759519ce3247a1120b207ea4d7affd4cc..5f9ae718e47e865a146810441c0822654bd3fc5a 100644 (file)
 
   <command arg="-root"/>
 
 
   <command arg="-root"/>
 
+  <hgroup>
   <number id="delay" type="slider" arg="-delay %"
           _label="Frame rate" _low-label="Low" _high-label="High"
   <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"/>
           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>
 
   <_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
 
 
 http://en.wikipedia.org/wiki/Klein_bottle
 
-Written by Andrey Mirtchovski; 2003.
+Written by Carsten Steger; 2008.
   </_description>
 </screensaver>
   </_description>
 </screensaver>
index 53e0e68f817ec5076ce5a4f7683f366f22bf7563..7ea18c7a1d399ff49de40cf34346af2264cabf2c 100644 (file)
@@ -43,9 +43,8 @@
   </hgroup>
 
   <_description>
   </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>
 
 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
 .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]
 .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;
   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,
       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 \
                  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 \
 
 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 \
                  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 \
 
 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 \
                  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
 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)
 
 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 \
 
 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 \
                  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
 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::
 
 # 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 ;                                \
         idir="$(install_prefix)$(HACKDIR)" ;                           \
         for program in $$exes; do                                      \
           echo rm -f $$idir/$$program ;                                \
@@ -344,7 +345,7 @@ uninstall-program::
        done
 
 uninstall-man:
        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* ;          \
        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) ;                       \
 
 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:
             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 *~ "#"*
 
 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)
 
 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)
 
 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)
 
 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)
 
 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)
 
 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
 
 ##############################################################################
 #
 # 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->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);
   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
 .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]
 .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_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"
 #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];
 
 typedef union {
     float              f[4];
+#if 0
 #if __VEC__
     vector float       v;
 #endif
 #if __VEC__
     vector float       v;
 #endif
+#endif /* 0 */
 } floatToVector;
 
 typedef union {
     unsigned int       i[4];
 } floatToVector;
 
 typedef union {
     unsigned int       i[4];
+#if 0
 #if __VEC__
     vector unsigned int        v;
 #endif
 #if __VEC__
     vector unsigned int        v;
 #endif
+#endif /* 0 */
 } intToVector;
 
 typedef struct SmokeParticleV  
 } 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);
 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
 #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
 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);
 
 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));
 }
 
        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) {
 #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
+#endif /* 0 */
 
 #define RandFlt(min, max) ((min) + frand((max) - (min)))
 
 
 #define RandFlt(min, max) ((min) + frand((max) - (min)))
 
@@ -196,6 +204,7 @@ void MakeTexture(void);
 
 #define OPT_MODE_SCALAR_BASE           0x0
 
 
 #define OPT_MODE_SCALAR_BASE           0x0
 
+#if 0
 #ifdef __ppc__
 #define OPT_MODE_SCALAR_FRSQRTE                0x1
 #endif
 #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
 #define OPT_MODE_VECTOR_SIMPLE         0x2
 #define OPT_MODE_VECTOR_UNROLLED       0x3
 #endif
+#endif /* 0 */
 
 typedef enum _ColorModes
 {
 
 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
  * 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");
 
   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 -*- */
 /* -*- 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
  * 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 drag_x;
        int drag_y;
        int noise_initted;
-
-        int p[512];
+       int p[512];
 
 } glhcfg;
 
 
 } glhcfg;
 
@@ -275,10 +274,18 @@ static void moveSetup(glhcfg *glhanoi, Disk * disk)
        int dst = glhanoi->dst;
        GLfloat theta;
        GLfloat sintheta, costheta;
        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;
        }
        } 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;
        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)
        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->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)
 }
 
 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);
        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))));
                                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;
 }
 
        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;
 
        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;
 }
 
        return marbleColours;
 }
@@ -1079,14 +1095,16 @@ static void setTexture(glhcfg *glhanoi, int n)
 static int makeTextures(glhcfg *glhanoi)
 {
        GLubyte *marbleTexture;
 static int makeTextures(glhcfg *glhanoi)
 {
        GLubyte *marbleTexture;
-       tex_col_t marbleColours;
+       tex_col_t *marbleColours;
 
        glGenTextures(N_TEXTURES, glhanoi->textureNames);
 
 
        glGenTextures(N_TEXTURES, glhanoi->textureNames);
 
-       marbleColours = makeMarbleColours();
+       if((marbleColours = makeMarbleColours()) == NULL) {
+               return 1;
+       }
        if((marbleTexture =
                makeTexture(glhanoi, MARBLE_TEXTURE_SIZE, MARBLE_TEXTURE_SIZE, 1,
        if((marbleTexture =
                makeTexture(glhanoi, MARBLE_TEXTURE_SIZE, MARBLE_TEXTURE_SIZE, 1,
-                                       makeMarbleTexture, &marbleColours)) == NULL) {
+                                       makeMarbleTexture, marbleColours)) == NULL) {
                return 1;
        }
 
                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);
                                 MARBLE_TEXTURE_SIZE, MARBLE_TEXTURE_SIZE, 0,
                                 GL_RGBA, GL_UNSIGNED_BYTE, marbleTexture);
        free(marbleTexture);
+       freeTexCols(marbleColours);
 
        return 0;
 }
 
        return 0;
 }
@@ -1173,7 +1192,6 @@ static void initTowers(glhcfg *glhanoi)
                                     glhanoi->baseHeight);
        glEndList();
 
                                     glhanoi->baseHeight);
        glEndList();
 
-
        if((glhanoi->poleList = glGenLists(1)) == 0) {
                fprintf(stderr, "can't allocate memory for towers display list\n");
                exit(EXIT_FAILURE);
        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);
 
     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);
 
        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)
 {
 
 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);
 
        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
  * 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.
 /* 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;
   
 
   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");
   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;
 
   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
  * 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.
  *
  * 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__
 
  */
 
 #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.
 /* 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;
   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];
 
   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 */
     {
 
   if (colors == 0)  /* truecolor */
     {
+      int i;
       for (i = 0; i < 256; i++)
         {
           spread_map[0][i] = spread_bits (i, srsiz);
       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();
     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;
     }
                          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;
     }
       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;
     }
       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;
     }
                          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
 #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
 .TH XScreenSaver 1 "" "X Version 11"
 .SH NAME
-Juggler3D - a 3D juggling simulation.
+juggler3d - juggling man screen saver.
 .SH SYNOPSIS
 .B juggler3d
 .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
 [\-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
 .SH OPTIONS
+.I juggler3d
+accepts the following options:
 .TP 8
 .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
 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
 .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
 .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
 .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
 .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
 .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
 .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
 .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
 .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
 .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
 .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
 .SH ENVIRONMENT
 .PP
 .TP 8
@@ -77,12 +169,15 @@ stored in the RESOURCE_MANAGER property.
 .BR X (1),
 .BR xscreensaver (1)
 .SH COPYRIGHT
 .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
 .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
 #ifdef STANDALONE
-# define DEFAULTS                                      "*delay:                20000   \n" \
-                                                                       "*showFPS:      False   \n"
+# define DEFAULTS           "*delay:      10000 \n" \
+                            "*showFPS:    False \n" \
 
 # define refresh_klein 0
 
 # define refresh_klein 0
-# include "xlockmore.h"                /* from the xscreensaver distribution */
+# include "xlockmore.h"         /* from the xscreensaver distribution */
 #else  /* !STANDALONE */
 #else  /* !STANDALONE */
-# include "xlock.h"                    /* from the xlockmore distribution */
+# include "xlock.h"             /* from the xlockmore distribution */
 #endif /* !STANDALONE */
 
 #ifdef USE_GL
 
 #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"
 
 #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 {
 
 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
 .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
 .SH SYNOPSIS
-.B klein
+.B kleinbottle
 [\-display \fIhost:display.screen\fP]
 [\-display \fIhost:display.screen\fP]
+[\-install]
 [\-visual \fIvisual\fP]
 [\-window]
 [\-root]
 [\-visual \fIvisual\fP]
 [\-window]
 [\-root]
-[\-speed \fInumber\fP]
-[\-rand]
-[\-spin]
-[\-wander]
+[\-delay \fIusecs\fP]
 [\-fps]
 [\-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
 .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
 .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.
 .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 \-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
 .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
 .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.
 .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
 .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 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
 .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
  * 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,
  *
  * 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
 #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
 */
 
 # 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 */
 #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" },
     {"+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 },
     {"-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
 
  "OpenGL mirrorblob", 0, NULL};
 #endif
 
-
 /*****************************************************************************
  * Types used in blob code
  *****************************************************************************/
 
 typedef struct
 {
 /*****************************************************************************
  * Types used in blob code
  *****************************************************************************/
 
 typedef struct
 {
-    GLdouble x, y;
+  GLdouble x, y;
 } Vector2D;
 
 typedef struct
 {
 } Vector2D;
 
 typedef struct
 {
-    GLdouble x, y, z;
+  GLdouble x, y, z;
 } Vector3D;
 
 typedef struct
 {
 } Vector3D;
 
 typedef struct
 {
-    GLdouble w;
-    GLdouble x;
-    GLdouble y;
-    GLdouble z;
+  GLdouble w;
+  GLdouble x;
+  GLdouble y;
+  GLdouble z;
 } Quaternion;
 
 typedef struct
 {
 } Quaternion;
 
 typedef struct
 {
-    GLubyte red, green, blue, alpha;
+  GLubyte red, green, blue, alpha;
 } Colour;
 
 typedef struct
 {
 } Colour;
 
 typedef struct
 {
-    Vector3D initial_position;
-    Vector3D position;
-    Vector3D normal;
+  Vector3D initial_position;
+  Vector3D position;
+  Vector3D normal;
 } Node_Data;
 
 typedef struct
 {
 } 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
 {
 } 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 */
 } Bump_Data;
 
 /* Vertices of a tetrahedron */
@@ -263,6 +265,7 @@ const Vector3D zero_vector = { 0.0, 0.0, 0.0 };
 
 typedef enum
 {
 
 typedef enum
 {
+  INITIALISING,
   HOLDING,
   LOADING,
   TRANSITIONING
   HOLDING,
   LOADING,
   TRANSITIONING
@@ -349,11 +352,11 @@ double_time (void)
 static void
 reset_projection(int width, int height)
 {
 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)
 {
 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)
 {
 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)
 {
 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)
 {
 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)
 {
 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)
 {
 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)
 {
 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)
 {
 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)
 {
 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, 
 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;
 }
 
   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)];
 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)
 {
 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)
 {
 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)
 {
 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)
 {
                 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 =
                         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 =
                         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 =
                         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 =
                         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)
 {
 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)
 {
           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)
 {
 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)
 {
 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)
 {
 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:
     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:
 
     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:
         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:
 
         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:
 
 
         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)
 {
 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)
 {
 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)
 {
 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)
 {
 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
 /* 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:
    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;
       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);
 
           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);
           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)
           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
     {
     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);
     }
                           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
  *
  * 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;
 
           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)
       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;
         }
                      progname, sb->name);
           return 0;
         }
@@ -327,7 +346,7 @@ read_hosts_file (sonar_sensor_data *ssd, const char *filename)
   if (!fp)
     {
       char buf[1024];
   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
 #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;
 
       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;
 
       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.
            */
 
           /* 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);
                           ? 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);
                           ? 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);
 
                           ? 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);
   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++;
             ? 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.
            */
              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);
                           ? 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);
                           ? 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);
                           ? 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);
                           ? 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);
 
                           ? 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
  *  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); 
 
        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);
   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.
 .TP 8
 .B c
 Decreases viewing Z coordinate.
-..UR <address>
-.UE
-TP 8
+.TP 8
 .B f
 Increases camera location X coordinate.
 .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> 
 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
  *
  * 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;
   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++)
     {
   for (i = 0; i < faces; i++)
     {
-      glVertex3f(0,  0, 1);
-      glVertex3f(x, y, 0);
-
+      glVertex3f (x, y, 0);
       th += step;
       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;
 }
   glEnd();
   return faces;
 }
index d72b4ebdd4aa4ad0d4884893441d05c3e4aecec0..3f41f9bf0905658e9630411864d63d5fc85091e8 100644 (file)
@@ -118,6 +118,8 @@ init_GL(ModeInfo * mi)
       glDrawBuffer (GL_FRONT);
   }
 
       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...
 
   /* 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 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)
 
 #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->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;
 }
 
   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
 .TH XScreenSaver 1 "" "X Version 11"
 .SH NAME
-MetaBalls.
+MetaBalls - draws 2D metaballs
 .SH SYNOPSIS
 .B MetaBalls
 [\-display \fIhost:display.screen\fP]
 .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;
 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;
 
 
 my $verbose = 0;
 
@@ -85,8 +85,10 @@ sub parse_makefiles() {
     close IN;
 
     $body =~ s/\\\n//gs;
     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;
     error ("no RETIRED_EXES in $mf") unless $var;
+    $var .= " $var2" if $var2;
     foreach my $hack (split (/\s+/, $var)) {
       $disable{$hack} = 2;
     }
     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 *); 
 
 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 IS_MOVING  1
-#define GET_PASSWD 2
 
 #if defined(HAVE_GDK_PIXBUF) || defined(HAVE_XPM)
 # include "images/noseguy/nose-f1.xpm"
 
 #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
  *
  * 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);
            {
              waitpid(state->pid, NULL, 0);
              fclose (state->pipe);
+              state->pid = 0;
            }
          else
            {
            }
          else
            {
@@ -1436,7 +1437,7 @@ phosphor_reshape (Display *dpy, Window window, void *closure,
   resize_grid (state);
 
 # if defined(HAVE_FORKPTY) && defined(TIOCSWINSZ)
   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;
     {
       /* 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
        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. */
 #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 ] );
 
   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;
 }
 
   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
 .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
 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->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);
   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 $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";
 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;
 sub init_signals() {
 
   $SIG{HUP}  = \&signal_cleanup;
@@ -3542,9 +3576,6 @@ sub main() {
   my $root_p = 0;
   my $window_id = undef;
 
   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" ||
   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.)";
   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();
   }
 
   init_signals();
+  set_proxy();
 
   spawn_driftnet ($driftnet_cmd) if ($driftnet_cmd);
 
 
   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
 /* 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
  *
  * 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>
 
 #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;
 
 char *progname;
 static int verbose_p = 0;
 
@@ -142,7 +149,7 @@ bevel_image (NSImage *img, int bevel_pct,
                    bytesPerRow: 0
                   bitsPerPixel: 0];
 
                    bytesPerRow: 0
                   bitsPerPixel: 0];
 
-  int xx, yy;
+  NSInteger xx, yy;
   double *ramp = (double *) malloc (sizeof(*ramp) * (bevel_size + 1));
 
   if (!ramp)
   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)
             {
           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];
               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:
                                properties:props];
 
   [jpeg_data writeToFile:
-               [NSString stringWithCString:file]
+               [NSString stringWithCString:file
+                                  encoding:NSISOLatin1StringEncoding]
              atomically:YES];
 
   if (verbose_p)
              atomically:YES];
 
   if (verbose_p)
index bc121a9629510c017d3522522bb8c3749b41780b..4b2ebc3ccf5a213df41b18da17ee362ea7678d34 100644 (file)
@@ -190,7 +190,7 @@ default: all
 all-yes: $(CATALOGS)
 all-no:
 
 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) ; \
        @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
 
 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;"
 
 maintainer-clean: distclean
        @echo "This command is intended for maintainers to use;"
@@ -281,9 +282,7 @@ maintainer-clean: distclean
        rm -f $(GMOFILES)
 
 depend:
        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:
 
 
 # jwz: Generates po/POTFILES.in by examining the source tree:
@@ -292,6 +291,8 @@ distdepend::
 generate_potfiles_in:
        @tmp=po.$$$$ ;                          \
         file=POTFILES.in ;                     \
 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] ;      \
         ( 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'                                 \
            && (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 $@ )
 
                | 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.
 
 # 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/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
 $ interaggregate       :== $'mydir'interaggregate
 $ interference :== $'mydir'interference
 $ intermomentary       :== $'mydir'intermomentary
-$ juggle       :== $'mydir'juggle
 $ julia                :== $'mydir'julia
 $ kaleidescope :== $'mydir'kaleidescope
 $ kumppa       :== $'mydir'kumppa
 $ 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
 
 #
 # 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[] =
 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
  *
  * 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);
       }
 
         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)
 # 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        name xscreensaver
-%define        version 5.08
+%define        version 5.09
 
 Summary:       X screen saver and locker
 Name:          %{name}
 
 Summary:       X screen saver and locker
 Name:          %{name}
index 7a050184f6f8b6781b2f6ee7607b0bdbe118fe56..0cbc5d9ea004a822c3ff3b951e6db280919824c7 100644 (file)
@@ -3,7 +3,7 @@
        archiveVersion = 1;
        classes = {
        };
        archiveVersion = 1;
        classes = {
        };
-       objectVersion = 42;
+       objectVersion = 44;
        objects = {
 
 /* Begin PBXAggregateTarget section */
        objects = {
 
 /* Begin PBXAggregateTarget section */
@@ -18,6 +18,7 @@
                                AF137D650F075E5C004DE3B2 /* PBXTargetDependency */,
                                AF137D630F075E5C004DE3B2 /* PBXTargetDependency */,
                                AF137D610F075E5C004DE3B2 /* PBXTargetDependency */,
                                AF137D650F075E5C004DE3B2 /* PBXTargetDependency */,
                                AF137D630F075E5C004DE3B2 /* PBXTargetDependency */,
                                AF137D610F075E5C004DE3B2 /* PBXTargetDependency */,
+                               AFB581B0102F363300342B11 /* PBXTargetDependency */,
                                AF137D5F0F075E5C004DE3B2 /* PBXTargetDependency */,
                                AF137D5D0F075E5C004DE3B2 /* PBXTargetDependency */,
                                AF137D5B0F075E5C004DE3B2 /* PBXTargetDependency */,
                                AF137D5F0F075E5C004DE3B2 /* PBXTargetDependency */,
                                AF137D5D0F075E5C004DE3B2 /* PBXTargetDependency */,
                                AF137D5B0F075E5C004DE3B2 /* PBXTargetDependency */,
                                AF7779BF09B6608100EA3033 /* PBXTargetDependency */,
                                AF7779BD09B6608100EA3033 /* PBXTargetDependency */,
                                AF7779BB09B6608100EA3033 /* PBXTargetDependency */,
                                AF7779BF09B6608100EA3033 /* PBXTargetDependency */,
                                AF7779BD09B6608100EA3033 /* PBXTargetDependency */,
                                AF7779BB09B6608100EA3033 /* PBXTargetDependency */,
-                               AF7779B909B6608100EA3033 /* PBXTargetDependency */,
                                AF7779B709B6608100EA3033 /* PBXTargetDependency */,
                                AF7779AD09B6608100EA3033 /* PBXTargetDependency */,
                                AF7779AB09B6608100EA3033 /* PBXTargetDependency */,
                                AF7779B709B6608100EA3033 /* PBXTargetDependency */,
                                AF7779AD09B6608100EA3033 /* PBXTargetDependency */,
                                AF7779AB09B6608100EA3033 /* PBXTargetDependency */,
                                AF7779F509B660B100EA3033 /* PBXTargetDependency */,
                                AF7779F309B660B000EA3033 /* PBXTargetDependency */,
                                AF7779F109B660B000EA3033 /* PBXTargetDependency */,
                                AF7779F509B660B100EA3033 /* PBXTargetDependency */,
                                AF7779F309B660B000EA3033 /* PBXTargetDependency */,
                                AF7779F109B660B000EA3033 /* PBXTargetDependency */,
+                               AF32D9F90F3AD0D90080F535 /* PBXTargetDependency */,
                                AF4540D20E52BE8800AE87B5 /* PBXTargetDependency */,
                                AF7779EF09B660B000EA3033 /* PBXTargetDependency */,
                                AF7779ED09B660B000EA3033 /* PBXTargetDependency */,
                                AF4540D20E52BE8800AE87B5 /* PBXTargetDependency */,
                                AF7779EF09B660B000EA3033 /* PBXTargetDependency */,
                                AF7779ED09B660B000EA3033 /* PBXTargetDependency */,
                                AF7779E509B660B000EA3033 /* PBXTargetDependency */,
                                AF7779E309B660B000EA3033 /* PBXTargetDependency */,
                                AF7779E109B660AF00EA3033 /* PBXTargetDependency */,
                                AF7779E509B660B000EA3033 /* PBXTargetDependency */,
                                AF7779E309B660B000EA3033 /* PBXTargetDependency */,
                                AF7779E109B660AF00EA3033 /* PBXTargetDependency */,
+                               AF4A3460102A59A400A81B2A /* PBXTargetDependency */,
                                AF7779DF09B660AF00EA3033 /* PBXTargetDependency */,
                                AF7779DD09B660AF00EA3033 /* PBXTargetDependency */,
                                AF998EF70A083E1D0051049D /* 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 */; };
                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 */; };
                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 */; };
                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 */; };
                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 */; };
                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 */; };
                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;
                        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;
                        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;
                        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;
                        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;
                        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;
                        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;
                        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;
                        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;
                        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;
                        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;
                        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;
                        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;
                        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;
                        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;
                        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;
                        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;
                        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;
                        remoteInfo = Critical;
                };
                AF137D680F075E5C004DE3B2 /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
                        proxyType = 1;
-                       remoteGlobalIDString = AF6427A809A2DE36000F4CD4 /* Bubbles */;
+                       remoteGlobalIDString = AF6427A809A2DE36000F4CD4;
                        remoteInfo = Bubbles;
                };
                AF1A17630D6D6EE3008AF328 /* PBXContainerItemProxy */ = {
                        remoteInfo = Bubbles;
                };
                AF1A17630D6D6EE3008AF328 /* PBXContainerItemProxy */ = {
                        remoteGlobalIDString = AF1A17610D6D6EE3008AF328;
                        remoteInfo = LCDscrub;
                };
                        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 */;
                AF35E88C0E63823600691F2F /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
                        remoteGlobalIDString = AF48DEEF0A0C25E000F94CF9;
                        remoteInfo = GLSchool;
                };
                        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 */;
                AF4FD6E80CE7A486005EE58E /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
                        remoteGlobalIDString = AFD572F9099701C000BA26F7;
                        remoteInfo = Julia;
                };
                        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 */;
                AF7779BA09B6608100EA3033 /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
                        remoteGlobalIDString = AF4808C0098C3B6C00FB32B8;
                        remoteInfo = jwxyz;
                };
                        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 */;
                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>"; };
                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>"; };
                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; };
                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>"; };
                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>"; };
                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; };
                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; };
                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;
                };
                        );
                        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;
                AF35E8940E63823600691F2F /* Frameworks */ = {
                        isa = PBXFrameworksBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                        );
                        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;
                AF4FD6EE0CE7A486005EE58E /* Frameworks */ = {
                        isa = PBXFrameworksBuildPhase;
                        buildActionMask = 2147483647;
                                AF77786D09B6536000EA3033 /* AGL.framework in Frameworks */,
                                AF77786E09B6536000EA3033 /* OpenGL.framework in Frameworks */,
                                AF77786F09B6536000EA3033 /* Carbon.framework in Frameworks */,
                                AF77786D09B6536000EA3033 /* AGL.framework in Frameworks */,
                                AF77786E09B6536000EA3033 /* OpenGL.framework in Frameworks */,
                                AF77786F09B6536000EA3033 /* Carbon.framework in Frameworks */,
+                               AF0F46DD104E1809000A929C /* AppKit.framework in Frameworks */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                AFE30BFC0E52B14700CCF4A5 /* Sonar.saver */,
                                AF35E8A00E63823600691F2F /* Jigsaw.saver */,
                                AFD51B300F063B4A00471C02 /* Photopile.saver */,
                                AFE30BFC0E52B14700CCF4A5 /* Sonar.saver */,
                                AF35E8A00E63823600691F2F /* Jigsaw.saver */,
                                AFD51B300F063B4A00471C02 /* Photopile.saver */,
+                               AF32D9F40F3AD0B40080F535 /* RubikBlocks.saver */,
+                               AF4A345D102A593600A81B2A /* Surfaces.saver */,
                        );
                        name = Products;
                        sourceTree = "<group>";
                        );
                        name = Products;
                        sourceTree = "<group>";
                                29B97317FDCFA39411CA2CEA /* Resources */,
                                29B97323FDCFA39411CA2CEA /* Frameworks */,
                                19C28FACFE9D520D11CA2CBB /* Products */,
                                29B97317FDCFA39411CA2CEA /* Resources */,
                                29B97323FDCFA39411CA2CEA /* Frameworks */,
                                19C28FACFE9D520D11CA2CBB /* Products */,
+                               AF0F46DC104E1809000A929C /* AppKit.framework */,
                        );
                        name = xscreensaver;
                        sourceTree = "<group>";
                        );
                        name = xscreensaver;
                        sourceTree = "<group>";
                                8D1107310486CEB800E47090 /* XScreenSaver.plist */,
                                AF0FAF1209CA712600EE1051 /* xscreensaver-getimage-file */,
                                AF0FAF0B09CA6FF900EE1051 /* xscreensaver-text */,
                                8D1107310486CEB800E47090 /* XScreenSaver.plist */,
                                AF0FAF1209CA712600EE1051 /* xscreensaver-getimage-file */,
                                AF0FAF0B09CA6FF900EE1051 /* xscreensaver-text */,
-                               AFD51B330F063B4B00471C02 /* XScreenSaver copy.plist */,
                        );
                        name = Resources;
                        sourceTree = "<group>";
                        );
                        name = Resources;
                        sourceTree = "<group>";
                AF480DD0098F4F2000FB32B8 /* OpenGL */ = {
                        isa = PBXGroup;
                        children = (
                AF480DD0098F4F2000FB32B8 /* OpenGL */ = {
                        isa = PBXGroup;
                        children = (
+                               AF32D9FA0F3AD1200080F535 /* rubikblocks.c */,
                                AFE6A40B0CDD7BC3002805BF /* moebiusgears.c */,
                                AF642409099FFAF0000F4CD4 /* extrusion-helix2.c */,
                                AF64240A099FFAF0000F4CD4 /* extrusion-helix3.c */,
                                AFE6A40B0CDD7BC3002805BF /* moebiusgears.c */,
                                AF642409099FFAF0000F4CD4 /* extrusion-helix2.c */,
                                AF64240A099FFAF0000F4CD4 /* extrusion-helix3.c */,
                                AF998EF80A083E750051049D /* topblock.c */,
                                AFE6A16A0CDD78EA002805BF /* involute.c */,
                                AFE6A16B0CDD78EA002805BF /* involute.h */,
                                AF998EF80A083E750051049D /* topblock.c */,
                                AFE6A16A0CDD78EA002805BF /* involute.c */,
                                AFE6A16B0CDD78EA002805BF /* involute.h */,
+                               AF4A3463102A5A0E00A81B2A /* surfaces.c */,
                                AF0DCA5F0C4CBB7300D76972 /* voronoi.c */,
                                AFA563660993970F00F3E977 /* cube21.c */,
                                AF4FF4D00D52CC8400666F98 /* cubicgrid.c */,
                                AF0DCA5F0C4CBB7300D76972 /* voronoi.c */,
                                AFA563660993970F00F3E977 /* cube21.c */,
                                AF4FF4D00D52CC8400666F98 /* cubicgrid.c */,
                AFC258670988A468000655EE /* config */ = {
                        isa = PBXGroup;
                        children = (
                AFC258670988A468000655EE /* config */ = {
                        isa = PBXGroup;
                        children = (
+                               AF32D9FC0F3AD1330080F535 /* rubikblocks.xml */,
                                AFE6A4360CDD8026002805BF /* abstractile.xml */,
                                AFE6A40D0CDD7BDC002805BF /* moebiusgears.xml */,
                                AFC258680988A468000655EE /* anemone.xml */,
                                AFE6A4360CDD8026002805BF /* abstractile.xml */,
                                AFE6A40D0CDD7BDC002805BF /* moebiusgears.xml */,
                                AFC258680988A468000655EE /* anemone.xml */,
                                AFC258CF0988A468000655EE /* jigsaw.xml */,
                                AFC258D00988A468000655EE /* juggle.xml */,
                                AFC258D10988A468000655EE /* juggler3d.xml */,
                                AFC258CF0988A468000655EE /* jigsaw.xml */,
                                AFC258D00988A468000655EE /* juggle.xml */,
                                AFC258D10988A468000655EE /* juggler3d.xml */,
+                               AF4A3461102A59EB00A81B2A /* surfaces.xml */,
                                AFC258D20988A468000655EE /* julia.xml */,
                                AFC258D30988A468000655EE /* kaleidescope.xml */,
                                AFC258D40988A468000655EE /* klein.xml */,
                                AFC258D20988A468000655EE /* julia.xml */,
                                AFC258D30988A468000655EE /* kaleidescope.xml */,
                                AFC258D40988A468000655EE /* klein.xml */,
                        productReference = AF1A17730D6D6EE3008AF328 /* LCDscrub.saver */;
                        productType = "com.apple.product-type.bundle";
                };
                        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" */;
                AF35E88A0E63823600691F2F /* Jigsaw */ = {
                        isa = PBXNativeTarget;
                        buildConfigurationList = AF35E89D0E63823600691F2F /* Build configuration list for PBXNativeTarget "Jigsaw" */;
                        productReference = AF48DF030A0C25E000F94CF9 /* GLSchool.saver */;
                        productType = "com.apple.product-type.bundle";
                };
                        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" */;
                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" */;
                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 = "";
                        hasScannedForEncodings = 1;
                        mainGroup = 29B97314FDCFA39411CA2CEA /* xscreensaver */;
                        projectDirPath = "";
                                AFD56F230996AB8A00BA26F7 /* Galaxy */,
                                AFD56F4F0996AEEE00BA26F7 /* Grav */,
                                AFD56F6B0996B01600BA26F7 /* Hopalong */,
                                AFD56F230996AB8A00BA26F7 /* Galaxy */,
                                AFD56F4F0996AEEE00BA26F7 /* Grav */,
                                AFD56F6B0996B01600BA26F7 /* Hopalong */,
-                               AFD571B50996D9DC00BA26F7 /* Juggle */,
                                AFD572F9099701C000BA26F7 /* Julia */,
                                AF794FCD09974FA60059A8B0 /* Loop */,
                                AFD5706F0996B72700BA26F7 /* Mountain */,
                                AFD572F9099701C000BA26F7 /* Julia */,
                                AF794FCD09974FA60059A8B0 /* Loop */,
                                AFD5706F0996B72700BA26F7 /* Mountain */,
                                AFA55B2509933E8D00F3E977 /* Pulsar */,
                                AFA55DF009935E4900F3E977 /* Queens */,
                                AFA559CF0993330600F3E977 /* Rubik */,
                                AFA55B2509933E8D00F3E977 /* Pulsar */,
                                AFA55DF009935E4900F3E977 /* Queens */,
                                AFA559CF0993330600F3E977 /* Rubik */,
+                               AF32D9E00F3AD0B40080F535 /* RubikBlocks */,
                                AFA55D3C0993565300F3E977 /* SBalls */,
                                AFA55B7909933F7200F3E977 /* Sierpinski3D */,
                                AFE2A4560E2E904600ADB298 /* SkyTentacles */,
                                AFA55D3C0993565300F3E977 /* SBalls */,
                                AFA55B7909933F7200F3E977 /* Sierpinski3D */,
                                AFE2A4560E2E904600ADB298 /* SkyTentacles */,
                                AF77781009B6504400EA3033 /* StarWars */,
                                AF7777A809B64B2600EA3033 /* StonerView */,
                                AFA559920993322100F3E977 /* Superquadrics */,
                                AF77781009B6504400EA3033 /* StarWars */,
                                AF7777A809B64B2600EA3033 /* StonerView */,
                                AFA559920993322100F3E977 /* Superquadrics */,
+                               AF4A3449102A593600A81B2A /* Surfaces */,
                                AFA562F20993943B00F3E977 /* Tangram */,
                                AFA56379099397B300F3E977 /* TimeTunnel */,
                                AF998EDA0A083DB30051049D /* TopBlock */,
                                AF0DCA420C4CBB0D00D76972 /* Voronoi */,
                                AFA562F20993943B00F3E977 /* Tangram */,
                                AFA56379099397B300F3E977 /* TimeTunnel */,
                                AF998EDA0A083DB30051049D /* TopBlock */,
                                AF0DCA420C4CBB0D00D76972 /* Voronoi */,
-                               AF9771D60989DC4A001F8B92 /* SaverTester */,
-                               AF137D410F075C9B004DE3B2 /* Obsolete */,
                                AF6427A809A2DE36000F4CD4 /* Bubbles */,
                                AF47765A099DA78E001F091E /* Critical */,
                                AF477909099DE379001F091E /* Flag */,
                                AFD56EDA0996A95700BA26F7 /* Forest */,
                                AFA55CCC09934CE400F3E977 /* GLForestFire */,
                                AF6427A809A2DE36000F4CD4 /* Bubbles */,
                                AF47765A099DA78E001F091E /* Critical */,
                                AF477909099DE379001F091E /* Flag */,
                                AFD56EDA0996A95700BA26F7 /* Forest */,
                                AFA55CCC09934CE400F3E977 /* GLForestFire */,
+                               AFD571B50996D9DC00BA26F7 /* Juggle */,
                                AF4774B4099D8B5F001F091E /* LMorph */,
                                AFD56F8C0996B09400BA26F7 /* Laser */,
                                AFD56FA30996B10F00BA26F7 /* Lightning */,
                                AF4774B4099D8B5F001F091E /* LMorph */,
                                AFD56F8C0996B09400BA26F7 /* Laser */,
                                AFD56FA30996B10F00BA26F7 /* Lightning */,
                                AFD56F0B0996AAFA00BA26F7 /* Vines */,
                                AF477208099D4EE8001F091E /* Whirlygig */,
                                AFD5709B0996B88E00BA26F7 /* Worm */,
                                AFD56F0B0996AAFA00BA26F7 /* Vines */,
                                AF477208099D4EE8001F091E /* Whirlygig */,
                                AFD5709B0996B88E00BA26F7 /* Worm */,
+                               AF137D410F075C9B004DE3B2 /* Obsolete */,
+                               AF9771D60989DC4A001F8B92 /* SaverTester */,
                        );
                };
 /* End PBXProject section */
                        );
                };
 /* End PBXProject section */
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AF32D9E30F3AD0B40080F535 /* Resources */ = {
+                       isa = PBXResourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF32D9FD0F3AD1330080F535 /* rubikblocks.xml in Resources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AF35E88D0E63823600691F2F /* Resources */ = {
                        isa = PBXResourcesBuildPhase;
                        buildActionMask = 2147483647;
                AF35E88D0E63823600691F2F /* Resources */ = {
                        isa = PBXResourcesBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AF4A344C102A593600A81B2A /* Resources */ = {
+                       isa = PBXResourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF4A3462102A59EB00A81B2A /* surfaces.xml in Resources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AF4FD6E90CE7A486005EE58E /* Resources */ = {
                        isa = PBXResourcesBuildPhase;
                        buildActionMask = 2147483647;
                AF4FD6E90CE7A486005EE58E /* Resources */ = {
                        isa = PBXResourcesBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AF32D9EF0F3AD0B40080F535 /* Rez */ = {
+                       isa = PBXRezBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AF35E89B0E63823600691F2F /* Rez */ = {
                        isa = PBXRezBuildPhase;
                        buildActionMask = 2147483647;
                AF35E89B0E63823600691F2F /* Rez */ = {
                        isa = PBXRezBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AF4A3458102A593600A81B2A /* Rez */ = {
+                       isa = PBXRezBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AF4FD6F50CE7A486005EE58E /* Rez */ = {
                        isa = PBXRezBuildPhase;
                        buildActionMask = 2147483647;
                AF4FD6F50CE7A486005EE58E /* Rez */ = {
                        isa = PBXRezBuildPhase;
                        buildActionMask = 2147483647;
                        shellScript = "$SOURCE_ROOT/OSX/update-info-plist.pl $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX";
                        showEnvVarsInLog = 0;
                };
                        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;
                AF35E89C0E63823600691F2F /* ShellScript */ = {
                        isa = PBXShellScriptBuildPhase;
                        buildActionMask = 2147483647;
                        shellScript = "$SOURCE_ROOT/OSX/update-info-plist.pl $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX";
                        showEnvVarsInLog = 0;
                };
                        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;
                AF4FD6F60CE7A486005EE58E /* ShellScript */ = {
                        isa = PBXShellScriptBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                        );
                        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;
                AF35E88F0E63823600691F2F /* Sources */ = {
                        isa = PBXSourcesBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                        );
                        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;
                AF4FD6EB0CE7A486005EE58E /* Sources */ = {
                        isa = PBXSourcesBuildPhase;
                        buildActionMask = 2147483647;
                        target = AF1A17610D6D6EE3008AF328 /* LCDscrub */;
                        targetProxy = AF1A17830D6D6FA7008AF328 /* PBXContainerItemProxy */;
                };
                        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 */;
                AF35E88B0E63823600691F2F /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
                        target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
                        target = AF48DEEF0A0C25E000F94CF9 /* GLSchool */;
                        targetProxy = AF48DF050A0C261100F94CF9 /* PBXContainerItemProxy */;
                };
                        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 */;
                AF4FD6E70CE7A486005EE58E /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
                        target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
                        target = AFD572F9099701C000BA26F7 /* Julia */;
                        targetProxy = AF7779B609B6608100EA3033 /* PBXContainerItemProxy */;
                };
                        target = AFD572F9099701C000BA26F7 /* Julia */;
                        targetProxy = AF7779B609B6608100EA3033 /* PBXContainerItemProxy */;
                };
-               AF7779B909B6608100EA3033 /* PBXTargetDependency */ = {
-                       isa = PBXTargetDependency;
-                       target = AFD571B50996D9DC00BA26F7 /* Juggle */;
-                       targetProxy = AF7779B809B6608100EA3033 /* PBXContainerItemProxy */;
-               };
                AF7779BB09B6608100EA3033 /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
                        target = AFD56F6B0996B01600BA26F7 /* Hopalong */;
                AF7779BB09B6608100EA3033 /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
                        target = AFD56F6B0996B01600BA26F7 /* Hopalong */;
                        target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
                        targetProxy = AFA563A6099398BB00F3E977 /* PBXContainerItemProxy */;
                };
                        target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
                        targetProxy = AFA563A6099398BB00F3E977 /* PBXContainerItemProxy */;
                };
+               AFB581B0102F363300342B11 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AFD571B50996D9DC00BA26F7 /* Juggle */;
+                       targetProxy = AFB581AF102F363300342B11 /* PBXContainerItemProxy */;
+               };
                AFCAD5F90992DFE00009617A /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
                        target = AF9771D60989DC4A001F8B92 /* SaverTester */;
                AFCAD5F90992DFE00009617A /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
                        target = AF9771D60989DC4A001F8B92 /* SaverTester */;
                        };
                        name = Release;
                };
                        };
                        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 = {
                AF35E89E0E63823600691F2F /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
                        };
                        name = Release;
                };
                        };
                        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 = {
                AF4FD6F80CE7A486005EE58E /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
                                GCC_DYNAMIC_NO_PIC = NO;
                                GCC_ENABLE_FIX_AND_CONTINUE = YES;
                                GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
                                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";
                                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;
                                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";
                                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 = {
                C01FCF4F08A954540054247B /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
+                               ARCHS = "$(NATIVE_ARCH_ACTUAL)";
                                COPY_PHASE_STRIP = NO;
                                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;
                                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)",
                                );
                                        "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_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;
                                GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES;
                                GCC_WARN_MISSING_PARENTHESES = YES;
                                GCC_WARN_SHADOW = NO;
                                );
                                PREBINDING = NO;
                                PRODUCT_NAME = "$(TARGET_NAME)";
                                );
                                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;
                                USER_HEADER_SEARCH_PATHS = "$(PROJECT_DIR) $(USER_HEADER_SEARCH_PATHS)";
                                WARNING_CFLAGS = "-Wimplicit";
                                WRAPPER_EXTENSION = saver;
                C01FCF5008A954540054247B /* Release */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
                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_GENERATE_DEBUGGING_SYMBOLS = NO;
-                               GCC_MODEL_TUNING = G5;
                                GCC_PRECOMPILE_PREFIX_HEADER = YES;
                                GCC_PREFIX_HEADER = OSX/xscreensaver_Prefix.pch;
                                GCC_PREPROCESSOR_DEFINITIONS = (
                                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)",
                                );
                                        "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_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;
                                GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES;
                                GCC_WARN_MISSING_PARENTHESES = YES;
                                GCC_WARN_SHADOW = NO;
                                );
                                PREBINDING = NO;
                                PRODUCT_NAME = "$(TARGET_NAME)";
                                );
                                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;
                                USER_HEADER_SEARCH_PATHS = "$(PROJECT_DIR) $(USER_HEADER_SEARCH_PATHS)";
                                WARNING_CFLAGS = "-Wimplicit";
                                WRAPPER_EXTENSION = saver;
                        defaultConfigurationIsVisible = 0;
                        defaultConfigurationName = Release;
                };
                        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 = (
                AF35E89D0E63823600691F2F /* Build configuration list for PBXNativeTarget "Jigsaw" */ = {
                        isa = XCConfigurationList;
                        buildConfigurations = (
                        defaultConfigurationIsVisible = 0;
                        defaultConfigurationName = Release;
                };
                        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 = (
                AF4FD6F70CE7A486005EE58E /* Build configuration list for PBXNativeTarget "Lockward" */ = {
                        isa = XCConfigurationList;
                        buildConfigurations = (