http://slackware.bholcomb.com/slackware/slackware-11.0/source/xap/xscreensaver/xscree...
[xscreensaver] / hacks / t3d.c
index 8b7ee7ed6f64b3cfad0a012f5fc552eeb2bad99a..65beb6d92aa35a928cca7f264246066c2b39be5c 100644 (file)
                           of the command-line options provided by screenhack.c.
 */
 
-#define FASTDRAW
-#define FASTCOPY
-#undef USE_POLYGON
+#ifndef HAVE_COCOA
+# define FASTDRAW
+# define FASTCOPY
+#endif /* !HAVE_COCOA */
 
 #include <stdio.h>
 #include <math.h>
 #include "screenhack.h"
 
 
-static int maxk=34;
-
 #define   WIDTH      200
 #define   HEIGHT     200
 #define   norm       20.0
 
-int timewait=40000;
-
 #define   ROOT       0x1
 #define PI M_PI
 #define TWOPI 2*M_PI
 
 #define MIN(i,j) ((i)<(j)?(i):(j))
 
-#define kmax ((minutes?60:24))
+#define kmax ((st->minutes?60:24))
 /* Anzahl der Kugeln */
 #define sines 52
 /* Werte in der Sinus-Tabelle */
 /*-----------------------------------------------------------------*/
 #define setink(inkcolor) \
-       XSetForeground (dpy,gc,inkcolor)
+       XSetForeground (st->dpy,st->gc,inkcolor)
 
 #define drawline(xx1,yy1,xx2,yy2) \
-       XDrawLine(dpy,win,gc,xx1,yy1,xx2,yy2) 
+       XDrawLine(st->dpy,st->win,st->gc,xx1,yy1,xx2,yy2) 
 
 #define drawseg(segments,nr_segments) \
-       XDrawSegments(dpy,win,gc,segments,nr_segments) 
+       XDrawSegments(st->dpy,st->win,st->gc,segments,nr_segments) 
 
 
 #define polyfill(ppts,pcount) \
-       XFillPolygon(dpy,win,gc,ppts,pcount,Convex,CoordModeOrigin)
+       XFillPolygon(st->dpy,st->win,st->gc,ppts,pcount,Convex,CoordModeOrigin)
 
 
 #define frac(argument) argument-floor(argument)
@@ -62,11 +59,6 @@ int timewait=40000;
 #undef ABS
 #define ABS(x) ((x)<0.0 ? -(x) : (x))
 
-static Colormap cmap;
-/* static XColor gray1; */
-static double r=1.0,g=1.0,b=1.0;
-static double hue=0.0,sat=0.0,val=1.0;
-
 typedef struct {
   double x,y,z,r,d,r1;
   int x1,y1;
@@ -74,65 +66,75 @@ typedef struct {
 
 /* Felder fuer 3D */
 
-static kugeldat kugeln[100];
-
-static double  a[3],/*m[3],*/am[3],x[3],y[3],v[3];
-static double zoom,speed,zaehler,vspeed/*,AE*/;
-static double vturn/*,aturn*/;
-/* static XPoint track[sines]; */
-static double sinus[sines];
-static double cosinus[sines];
-
-static int startx,starty;
-static double /*magx,magy,*/mag=10;
-/* static double lastx,lasty,lastz; */
-/* static int lastcx,lastcy,lastcz; */
-/* static int move=1; */
-static int minutes=0;
-static int cycl=0;
-static double hsvcycl=0.0;
-static double movef =0.5, wobber=2.0, cycle=6.0;
-
-/* time */
-
-/* static double sec; */
-
-/* Windows */
-static XWindowAttributes xgwa;
-static GC      gc;
-static GC orgc;
-static GC andgc;
-static Window  win;
-/* static Font font; */
-static Display *dpy;
-static int     screen, scrnWidth = WIDTH, scrnHeight = HEIGHT;
-static Pixmap  buffer;
-#define maxfast 100
-static int fastch=50;
-#ifdef FASTDRAW
-#      ifdef FASTCOPY
-#              define sum1ton(a) (((a)*(a)+1)/2)
-#              define fastcw sum1ton(fastch)
-               static Pixmap fastcircles;
-               static Pixmap fastmask;
-#      else
-               static XImage* fastcircles[maxfast];
-               static XImage* fastmask[maxfast];
-#      endif
-static int fastdraw=0;
-#endif
 
-static int scrnW2,scrnH2;
-/* static unsigned short flags = 0; */
-/* static char *text; */
-static XColor colors[64];
-static struct tm *zeit;
+struct state {
+  Display *dpy;
+  Window window;
+
+  int maxk;
+  int timewait;
+
+  Colormap cmap;
+  double r,g,b;
+  double hue,sat,val;
+
+  kugeldat kugeln[100];
+
+  double  a[3],am[3],x[3],y[3],v[3];
+  double zoom,speed,zaehler,vspeed;
+  double vturn;
+  double sinus[sines];
+  double cosinus[sines];
+
+  int startx,starty;
+  double mag;
+  int minutes;
+  int cycl;
+  double hsvcycl;
+  double movef, wobber, cycle;
+
+  XWindowAttributes xgwa;
+  GC   gc;
+  GC orgc;
+  GC andgc;
+  int  scrnWidth, scrnHeight;
+  Pixmap  buffer;
+  int fastch;
+
+  int scrnW2,scrnH2;
+  XColor colors[64];
+  struct tm *zeit;
+
+  int planes;
+
+  Window junk_win,in_win;
+  int px,py,junk;
+  unsigned int kb;
+
+  int fastdraw;
+  int draw_color;
+
+# ifdef FASTDRAW
+#  ifdef FASTCOPY
+#   define sum1ton(a) (((a)*(a)+1)/2)
+#   define fastcw sum1ton(st->fastch)
+    Pixmap fastcircles;
+    Pixmap fastmask;
+#  else /* !FASTCOPY */
+    XImage* fastcircles[maxfast];
+    XImage* fastmask[maxfast];
+#  endif /* !FASTCOPY */
+# endif /* FASTDRAW */
+};
+
+
+
+#define maxfast 100
 
-static int planes;
 /* compute time */
 
 static double
-gettime (void)
+gettime (struct state *st)
 {
   struct timeval time1;
   struct tm *zeit;
@@ -188,53 +190,53 @@ hsv2rgb (double h, double s, double v, double *r, double *g, double *b)
 }
 
 static void
-changeColor (double r, double g, double b)
+changeColor (struct state *st, double r, double g, double b)
 {
   int n,n1;
   
   n1=0;
   for(n=30;n<64;n+=3)
     {
-      colors[n1].red   =1023+ n*(int)(1024.*r);
-      colors[n1].blue  =1023+ n*(int)(1024.*b);
-      colors[n1].green =1023+ n*(int)(1024.*g);
+      st->colors[n1].red   =1023+ n*(int)(1024.*r);
+      st->colors[n1].blue  =1023+ n*(int)(1024.*b);
+      st->colors[n1].green =1023+ n*(int)(1024.*g);
       
       n1++;
     }
   
-  XStoreColors (dpy, cmap, colors, 12);
+  XStoreColors (st->dpy, st->cmap, st->colors, 12);
 }
 
 static void 
-initColor (double r, double g, double b)
+initColor (struct state *st, double r, double g, double b)
 {
   int n,n1;
   unsigned long pixels[12];
   unsigned long dummy;
   
-  cmap = xgwa.colormap;
+  st->cmap = st->xgwa.colormap;
   
-  if(hsvcycl!=0.0 && XAllocColorCells(dpy, cmap, 0, &dummy, 0, pixels, 12))
+  if(st->hsvcycl!=0.0 && XAllocColorCells(st->dpy, st->cmap, 0, &dummy, 0, pixels, 12))
     {
       for(n1=0;n1<12;n1++)
        {
-         colors[n1].pixel=pixels[n1];
-         colors[n1].flags=DoRed | DoGreen | DoBlue;
+         st->colors[n1].pixel=pixels[n1];
+         st->colors[n1].flags=DoRed | DoGreen | DoBlue;
        }
       
-      changeColor(r,g,b);
+      changeColor(st,r,g,b);
     }
   else
     {
       n1=0;
       for(n=30;n<64;n+=3)
        {
-         colors[n1].red   =1023+ n*(int)(1024.*r);
-         colors[n1].blue  =1023+ n*(int)(1024.*b);
-         colors[n1].green =1023+ n*(int)(1024.*g);
+         st->colors[n1].red   =1023+ n*(int)(1024.*r);
+         st->colors[n1].blue  =1023+ n*(int)(1024.*b);
+         st->colors[n1].green =1023+ n*(int)(1024.*g);
          
-         if (!(XAllocColor (dpy, cmap, &colors[n1]))) {
-           (void) fprintf (stderr, "Error:  Cannot allocate colors\n");
+         if (!(XAllocColor (st->dpy, st->cmap, &st->colors[n1]))) {
+           fprintf (stderr, "Error:  Cannot allocate colors\n");
            exit (1);
          }
          
@@ -246,81 +248,94 @@ initColor (double r, double g, double b)
 /* ----------------WINDOW-------------------*/
 
 static void
-initialize (void)
+initialize (struct state *st)
 {
   XGCValues *xgc;
   XGCValues *xorgc;
   XGCValues *xandgc;
 
-  XGetWindowAttributes (dpy, win, &xgwa);
-  scrnWidth = xgwa.width;
-  scrnHeight = xgwa.height;
+  st->maxk=34;
+  st->r = st->g = st->b = 1;
+  st->hue = st->sat = 0;
+  st->val = 1;
+  st->mag = 10;
+  st->movef = 0.5;
+  st->wobber = 2;
+  st->cycle = 6;
+  st->scrnWidth = WIDTH;
+  st->scrnHeight = HEIGHT;
+
+
+  XGetWindowAttributes (st->dpy, st->window, &st->xgwa);
+  st->scrnWidth = st->xgwa.width;
+  st->scrnHeight = st->xgwa.height;
 
   {
-    float f = get_float_resource ("cycle", "Float");
+    float f = get_float_resource (st->dpy, "cycle", "Float");
     if (f <= 0 || f > 60) f = 6.0;
-    cycle = 60.0 / f;
+    st->cycle = 60.0 / f;
   }
-  movef = get_float_resource ("move", "Float");
-  wobber = get_float_resource ("wobble", "Float");
+  st->movef = get_float_resource (st->dpy, "move", "Float");
+  st->wobber = get_float_resource (st->dpy, "wobble", "Float");
 
   {
-    double magfac = get_float_resource ("mag", "Float");
-    mag *= magfac;
-    fastch=(int)(fastch*magfac);
+    double magfac = get_float_resource (st->dpy, "mag", "Float");
+    st->mag *= magfac;
+    st->fastch=(int)(st->fastch*magfac);
   }
 
-  if (get_boolean_resource ("minutes", "Boolean")) {
-    minutes=1; maxk+=60-24;
+  if (get_boolean_resource (st->dpy, "minutes", "Boolean")) {
+    st->minutes=1; st->maxk+=60-24;
   }
 
-  timewait = get_integer_resource ("delay", "Integer");
-  fastch = get_integer_resource ("fast", "Integer");
-  cycl = get_boolean_resource ("colcycle", "Integer");
-  hsvcycl = get_float_resource ("hsvcycle", "Integer");
+  st->timewait = get_integer_resource (st->dpy, "delay", "Integer");
+  st->fastch = get_integer_resource (st->dpy, "fast", "Integer");
+  st->cycl = get_boolean_resource (st->dpy, "colcycle", "Integer");
+  st->hsvcycl = get_float_resource (st->dpy, "hsvcycle", "Integer");
 
   {
-    char *s = get_string_resource ("rgb", "RGB");
+    char *s = get_string_resource (st->dpy, "rgb", "RGB");
     char dummy;
     if (s && *s)
       {
         double rr, gg, bb;
         if (3 == sscanf (s, "%lf %lf %lf %c", &rr, &gg, &bb, &dummy))
-          r = rr, g = gg, b = bb;
+          st->r = rr, st->g = gg, st->b = bb;
       }
     if (s) free (s);
 
-    s = get_string_resource ("hsv", "HSV");
+    s = get_string_resource (st->dpy, "hsv", "HSV");
     if (s && *s)
       {
         double hh, ss, vv;
         if (3 == sscanf (s, "%lf %lf %lf %c", &hh, &ss, &vv, &dummy)) {
-          hue = hh, sat = ss, val = vv;
-          hsv2rgb(hue,sat,val,&r,&g,&b);
+          st->hue = hh, st->sat = ss, st->val = vv;
+          hsv2rgb(st->hue,st->sat,st->val,&st->r,&st->g,&st->b);
         }
       }
     if (s) free (s);
   }
 
-  if (fastch>maxfast)
-               fastch=maxfast;
+  if (st->fastch > maxfast)
+    st->fastch=maxfast;
   
   xgc=( XGCValues *) malloc(sizeof(XGCValues) );
   xorgc=( XGCValues *) malloc(sizeof(XGCValues) );
   xandgc=( XGCValues *) malloc(sizeof(XGCValues) );
 
-  screen = screen_number (xgwa.screen);
-  
-  planes=xgwa.depth;
+  st->planes=st->xgwa.depth;
 
-  gc = XCreateGC (dpy, win, 0,  xgc);
+#ifdef HAVE_COCOA
+# define GXandInverted GXcopy  /* #### this can't be right, right? */
+#endif
+ st->gc = XCreateGC (st->dpy, st->window, 0,  xgc);
   xorgc->function =GXor;
-  orgc = XCreateGC (dpy, win, GCFunction,  xorgc);
+  st->orgc = XCreateGC (st->dpy, st->window, GCFunction,  xorgc);
   xandgc->function =GXandInverted;
-  andgc = XCreateGC (dpy, win, GCFunction,  xandgc);
+  st->andgc = XCreateGC (st->dpy, st->window, GCFunction,  xandgc);
   
-  buffer = XCreatePixmap (dpy, win, scrnWidth, scrnHeight,
-                         xgwa.depth); 
+  st->buffer = XCreatePixmap (st->dpy, st->window, st->scrnWidth, st->scrnHeight,
+                         st->xgwa.depth); 
   
 #ifdef DEBUG
   printf("Time 3D drawing ");
@@ -336,73 +351,73 @@ initialize (void)
 #endif /* DEBUG */
   
 #ifdef FASTCOPY
-  fastcircles = XCreatePixmap (dpy, win, fastcw, fastch+1, xgwa.depth);
-  fastmask    = XCreatePixmap (dpy, win, fastcw, fastch+1, xgwa.depth);
+  st->fastcircles = XCreatePixmap (st->dpy, st->window, fastcw, st->fastch+1, st->xgwa.depth);
+  st->fastmask    = XCreatePixmap (st->dpy, st->window, fastcw, st->fastch+1, st->xgwa.depth);
 #endif
   
-  setink(BlackPixel (dpy, screen));
-  XFillRectangle (dpy, buffer     , gc, 0, 0, scrnWidth, scrnHeight);  
+  setink(BlackPixelOfScreen (st->xgwa.screen));
+  XFillRectangle (st->dpy, st->buffer     , st->gc, 0, 0, st->scrnWidth, st->scrnHeight);      
   
 #ifdef FASTCOPY
   
   setink(0);
-  XFillRectangle (dpy, fastcircles, gc, 0, 0, fastcw, fastch+1);
-  XFillRectangle (dpy, fastmask   , gc, 0, 0, fastcw, fastch+1);
+  XFillRectangle (st->dpy, st->fastcircles, st->gc, 0, 0, fastcw, st->fastch+1);
+  XFillRectangle (st->dpy, st->fastmask   , st->gc, 0, 0, fastcw, st->fastch+1);
   
 #endif
 
 #ifdef PRTDBX
   printf("move\t%.2f\nwobber\t%.2f\nmag\t%.2f\ncycle\t%.4f\n",
-        movef,wobber,mag/10,cycle);
-  printf("fast\t%i\nmarks\t%i\nwait\t%i\n",fastch,maxk,timewait);
+        st->movef,st->wobber,st->mag/10,st->cycle);
+  printf("fast\t%i\nmarks\t%i\nwait\t%i\n",st->fastch,st->maxk,st->timewait);
 #endif
  
 }
 
-static void fill_kugel(int i, Pixmap buf, int setcol);
+static void fill_kugel(struct state *st, int i, Pixmap buf, int setcol);
 
 
 /*------------------------------------------------------------------*/
 static void 
-init_kugel(void)
+init_kugel(struct state *st)
 {
   
 #ifdef FASTDRAW
   int i;
 
-  for(i=0; i<fastch; i++)
+  for(i=0; i<st->fastch; i++)
     {
 #      ifdef FASTCOPY
-      kugeln[i].r1=-((double) i)/2 -1;
-      kugeln[i].x1=sum1ton(i);
-      kugeln[i].y1=((double) i)/2 +1;
+      st->kugeln[i].r1=-((double) i)/2 -1;
+      st->kugeln[i].x1=sum1ton(i);
+      st->kugeln[i].y1=((double) i)/2 +1;
       
-      fill_kugel(i,fastcircles,1);
-      setink((1<<MIN(24,xgwa.depth))-1);
-      fill_kugel(i,fastmask,0);
+      fill_kugel(st,i,st->fastcircles,1);
+      setink((1<<MIN(24,st->xgwa.depth))-1);
+      fill_kugel(st,i,st->fastmask,0);
 #      else
-      kugeln[i].r1=-((double) i)/2 -1;
-      kugeln[i].x1=kugeln[i].y1=((double) i)/2 +1;
+      st->kugeln[i].r1=-((double) i)/2 -1;
+      st->kugeln[i].x1=st->kugeln[i].y1=((double) i)/2 +1;
       
-      fill_kugel(i,buffer,1);
-      fastcircles[i]=XGetImage(dpy,buffer,0,0,i+2,i+2,(1<<planes)-1,ZPixmap);
+      fill_kugel(i,st->buffer,1);
+      st->fastcircles[i]=XGetImage(st->dpy,st->buffer,0,0,i+2,i+2,(1<<st->planes)-1,ZPixmap);
       
-      setink((1<<MIN(24,xgwa.depth))-1);
-      fill_kugel(i,buffer,0);
-      fastmask[i]=XGetImage(dpy,buffer,0,0,i+2,i+2,(1<<planes)-1,ZPixmap);
+      setink((1<<MIN(24,st->xgwa.depth))-1);
+      fill_kugel(i,st->buffer,0);
+      st->fastmask[i]=XGetImage(st->dpy,st->buffer,0,0,i+2,i+2,(1<<st->planes)-1,ZPixmap);
       
       setink(0);
-      XFillRectangle (dpy, buffer     , gc, 0, 0, scrnWidth, scrnHeight);      
+      XFillRectangle (st->dpy, st->buffer     , st->gc, 0, 0, st->scrnWidth, st->scrnHeight);  
 #      endif
     }
-  fastdraw=1;
+  st->fastdraw=1;
 #endif
 }
 
 /* Zeiger zeichnen */
 
 static void
-zeiger(double dist,double rad, double z, double sec, int *q)
+zeiger(struct state *st, double dist,double rad, double z, double sec, int *q)
 {
   int i,n;
   double gratio=sqrt(2.0/(1.0+sqrt(5.0)));
@@ -411,10 +426,10 @@ zeiger(double dist,double rad, double z, double sec, int *q)
   
   for(i=0;i<3;i++)
     {
-      kugeln[n].x=dist*cos(sec);
-      kugeln[n].y=-dist*sin(sec);
-      kugeln[n].z=z;
-      kugeln[n].r=rad;
+      st->kugeln[n].x=dist*cos(sec);
+      st->kugeln[n].y=-dist*sin(sec);
+      st->kugeln[n].z=z;
+      st->kugeln[n].r=rad;
       n++;
 
       dist += rad;
@@ -428,7 +443,7 @@ zeiger(double dist,double rad, double z, double sec, int *q)
  *-----------------------------------------------------------------*/
 
 static void
-manipulate(double k)
+manipulate(struct state *st, double k)
 {
   double i,l,/*xs,*/ys,zs,mod;
   double /*persec,*/sec,min,hour;
@@ -443,102 +458,102 @@ manipulate(double k)
   for (n=0;n<kmax;n++)
     {
       
-      kugeln[n].x=4.0*sin(i);
-      kugeln[n].y=4.0*cos(i);
-      kugeln[n].z=wobber* /* (sin(floor(2+2*l/(PI))*i)*sin(2*l)); */
+      st->kugeln[n].x=4.0*sin(i);
+      st->kugeln[n].y=4.0*cos(i);
+      st->kugeln[n].z=st->wobber* /* (sin(floor(2+2*l/(PI))*i)*sin(2*l)); */
        cos((i-sec)*floor(2+5*l/(PI)))*sin(5*l);
-      if(minutes)
+      if(st->minutes)
        {
-         kugeln[n].r=/* (1.0+0.3*cos(floor(2+2*l/(PI))*i)*sin(2*l))* */
+         st->kugeln[n].r=/* (1.0+0.3*cos(floor(2+2*l/(PI))*i)*sin(2*l))* */
            ((n % 5!=0) ? 0.3 : 0.6)*
              ((n % 15 ==0) ? 1.25 : .75);
        }
       else
        {
-         kugeln[n].r=/* (1.0+0.3*cos(floor(2+2*l/(PI))*i)*sin(2*l))* */
+         st->kugeln[n].r=/* (1.0+0.3*cos(floor(2+2*l/(PI))*i)*sin(2*l))* */
            ((n & 1) ? 0.5 : 1.0)*
              ((n % 6==0) ? 1.25 : .75);
        }
       i+=TWOPI/kmax;
     }
 
-  kugeln[n].x=0.0;
-  kugeln[n].y=0.0;
-  kugeln[n].z=0.0;
-  kugeln[n].r=2.0+cos(TWOPI*modf(k,&mod))/2;
+  st->kugeln[n].x=0.0;
+  st->kugeln[n].y=0.0;
+  st->kugeln[n].z=0.0;
+  st->kugeln[n].r=2.0+cos(TWOPI*modf(k,&mod))/2;
   n++;
   
-  zeiger(2.0,0.75,-2.0,sec,&n);
-  zeiger(1.0,1.0,-1.5,min,&n);
-  zeiger(0.0,1.5,-1.0,hour,&n);
+  zeiger(st,2.0,0.75,-2.0,sec,&n);
+  zeiger(st,1.0,1.0,-1.5,min,&n);
+  zeiger(st,0.0,1.5,-1.0,hour,&n);
   
-  for(n=0;n<maxk;n++)
+  for(n=0;n<st->maxk;n++)
     {
-      ys=kugeln[n].y*cos(movef*sin(cycle*sec))+
-       kugeln[n].z*sin(movef*sin(cycle*sec));
-      zs=-kugeln[n].y*sin(movef*sin(cycle*sec))+
-       kugeln[n].z*cos(movef*sin(cycle*sec));
-      kugeln[n].y=ys;
-      kugeln[n].z=zs;
+      ys=st->kugeln[n].y*cos(st->movef*sin(st->cycle*sec))+
+       st->kugeln[n].z*sin(st->movef*sin(st->cycle*sec));
+      zs=-st->kugeln[n].y*sin(st->movef*sin(st->cycle*sec))+
+       st->kugeln[n].z*cos(st->movef*sin(st->cycle*sec));
+      st->kugeln[n].y=ys;
+      st->kugeln[n].z=zs;
     }
 }
 /*------------------------------------------------------------------*/
 static void
-t3d_sort(int l, int r)
+t3d_sort(struct state *st, int l, int r)
 {
   int i,j;
   kugeldat ex;
   double x;
   
   i=l;j=r;
-  x=kugeln[(l+r)/2].d;
+  x=st->kugeln[(l+r)/2].d;
   while(1)
     {
-      while(kugeln[i].d>x) i++;
-      while(x>kugeln[j].d) j--;
+      while(st->kugeln[i].d>x) i++;
+      while(x>st->kugeln[j].d) j--;
       if (i<=j)
        {
-         ex=kugeln[i];kugeln[i]=kugeln[j];kugeln[j]=ex;
+         ex=st->kugeln[i];st->kugeln[i]=st->kugeln[j];st->kugeln[j]=ex;
          i++;j--;
        }
       if (i>j) break;
     }
-  if (l<j) t3d_sort(l,j);
-  if (i<r) t3d_sort (i,r);
+  if (l<j) t3d_sort(st,l,j);
+  if (i<r) t3d_sort(st,i,r);
 }
 
 /*------------------------------------------------------------------*/
 static void
-fill_kugel(int i, Pixmap buf, int setcol)
+fill_kugel(struct state *st, int i, Pixmap buf, int setcol)
 {
   double ra;
   int m,col,inc=1,inr=3,d;
-  d=(int)((ABS(kugeln[i].r1)*2));
+  d=(int)((ABS(st->kugeln[i].r1)*2));
   if (d==0) d=1;
   
 #ifdef FASTDRAW
-  if(fastdraw && d<fastch)
+  if(st->fastdraw && d<st->fastch)
     {
 #      ifdef FASTCOPY
-      XCopyArea(dpy, fastmask, buf, andgc, sum1ton(d)-(d+1)/2, 1,d,d,
-               (int)(kugeln[i].x1)-d/2, (int)(kugeln[i].y1)-d/2);
-      XCopyArea(dpy, fastcircles, buf, orgc, sum1ton(d)-(d+1)/2, 1,d,d,
-               (int)(kugeln[i].x1)-d/2, (int)(kugeln[i].y1)-d/2);
+      XCopyArea(st->dpy, st->fastmask, buf, st->andgc, sum1ton(d)-(d+1)/2, 1,d,d,
+               (int)(st->kugeln[i].x1)-d/2, (int)(st->kugeln[i].y1)-d/2);
+      XCopyArea(st->dpy, st->fastcircles, buf, st->orgc, sum1ton(d)-(d+1)/2, 1,d,d,
+               (int)(st->kugeln[i].x1)-d/2, (int)(st->kugeln[i].y1)-d/2);
 #      else
-      XPutImage(dpy, buf, andgc, fastmask[d-1], 0, 0,
-               (int)(kugeln[i].x1)-d/2, (int)(kugeln[i].y1)-d/2, d, d);
-      XPutImage(dpy, buf, orgc, fastcircles[d-1], 0, 0,
-               (int)(kugeln[i].x1)-d/2, (int)(kugeln[i].y1)-d/2, d, d);
+      XPutImage(st->dpy, buf, st->andgc, st->fastmask[d-1], 0, 0,
+               (int)(st->kugeln[i].x1)-d/2, (int)(st->kugeln[i].y1)-d/2, d, d);
+      XPutImage(st->dpy, buf, st->orgc, st->fastcircles[d-1], 0, 0,
+               (int)(st->kugeln[i].x1)-d/2, (int)(st->kugeln[i].y1)-d/2, d, d);
 #      endif
     }
   else
 #endif
     {
-      if(ABS(kugeln[i].r1)<6.0) inr=9;
+      if(ABS(st->kugeln[i].r1)<6.0) inr=9;
       
       for (m=0;m<=28;m+=inr)
        {
-         ra=kugeln[i].r1*sqrt(1-m*m/(28.0*28.0));
+         ra=st->kugeln[i].r1*sqrt(1-m*m/(28.0*28.0));
 #ifdef PRTDBX
          printf("Radius: %f\n",ra);
 #endif
@@ -552,7 +567,7 @@ fill_kugel(int i, Pixmap buf, int setcol)
              else
                col=(int)(m);
              if (col>33) col=33;       col/=3;
-             setink(colors[col].pixel);
+             setink(st->colors[col].pixel);
            }
 
 #ifdef USE_POLYGON
@@ -560,15 +575,15 @@ fill_kugel(int i, Pixmap buf, int setcol)
             int n, nr;
          for (n=0,nr=0;n<=sines-1;n+=inc,nr++)
            {
-             track[nr].x=kugeln[i].x1+(int)(ra*sinus[n])+(kugeln[i].r1-ra)/2;
-             track[nr].y=kugeln[i].y1+(int)(ra*cosinus[n])+(kugeln[i].r1-ra)/2;
+             track[nr].x=st->kugeln[i].x1+(int)(ra*st->sinus[n])+(st->kugeln[i].r1-ra)/2;
+             track[nr].y=st->kugeln[i].y1+(int)(ra*st->cosinus[n])+(st->kugeln[i].r1-ra)/2;
            }
-         XFillPolygon(dpy,buf,gc,track,nr,Convex,CoordModeOrigin);
+         XFillPolygon(st->dpy,buf,st->gc,track,nr,Convex,CoordModeOrigin);
           }
 #else /* Use XFillArc */
-         XFillArc(dpy, buf, gc,
-                  (int)(kugeln[i].x1+(kugeln[i].r1+ra)/2),
-                  (int)(kugeln[i].y1+(kugeln[i].r1+ra)/2),
+         XFillArc(st->dpy, buf, st->gc,
+                  (int)(st->kugeln[i].x1+(st->kugeln[i].r1+ra)/2),
+                  (int)(st->kugeln[i].y1+(st->kugeln[i].r1+ra)/2),
                   (int)-(2*ra+1), (int)-(2*ra+1), 0, 360*64);
 #endif
        }
@@ -578,31 +593,31 @@ fill_kugel(int i, Pixmap buf, int setcol)
 /*------------------------------------------------------------------*/
 
 static void
-init_3d(void)
+init_3d(struct state *st)
 {
   double i;
   int n=0;
   
-  a[0]=0.0;
-  a[1]=0.0;
-  a[2]=-10.0;
+  st->a[0]=0.0;
+  st->a[1]=0.0;
+  st->a[2]=-10.0;
   
-  x[0]=10.0;
-  x[1]=0.0;
-  x[2]=0.0;
+  st->x[0]=10.0;
+  st->x[1]=0.0;
+  st->x[2]=0.0;
   
-  y[0]=0.0;
-  y[1]=10.0;
-  y[2]=0.0;
+  st->y[0]=0.0;
+  st->y[1]=10.0;
+  st->y[2]=0.0;
   
   
-  zoom=-10.0;
-  speed=.0;
+  st->zoom=-10.0;
+  st->speed=.0;
   
   for (i=0.0;n<sines;i+=TWOPI/sines,n++)
     {
-      sinus[n]=sin(i);
-      cosinus[n]=cos(i);
+      st->sinus[n]=sin(i);
+      st->cosinus[n]=cos(i);
     }
 }
 /*------------------------------------------------------------------*/
@@ -615,6 +630,8 @@ vektorprodukt(double feld1[], double feld2[], double feld3[])
   feld3[1]=feld1[2]*feld2[0]-feld1[0]*feld2[2];
   feld3[2]=feld1[0]*feld2[1]-feld1[1]*feld2[0];
 }
+
+
 /*------------------------------------------------------------------*/
 static void
 turn(double feld1[], double feld2[], double winkel)
@@ -639,149 +656,283 @@ turn(double feld1[], double feld2[], double winkel)
 /* 1: Blickrichtung v;3:Ebenenmittelpunkt m 
    double feld1[],feld3[]; */
 static void 
-viewpoint(void)
+viewpoint(struct state *st)
 {
-  am[0]=-zoom*v[0];
-  am[1]=-zoom*v[1];
-  am[2]=-zoom*v[2];
+  st->am[0]=-st->zoom*st->v[0];
+  st->am[1]=-st->zoom*st->v[1];
+  st->am[2]=-st->zoom*st->v[2];
   
-  zaehler=norm*norm*zoom;
+  st->zaehler=norm*norm*st->zoom;
 }
+
 /*------------------------------------------------------------------*/
 static void 
-projektion(void)
+projektion(struct state *st)
 {
   double c1[3],c2[3],k[3],x1,y1;
   double cno,cnorm/*,magnit*/;
   int i;
   
-  for (i=0;i<maxk;i++)
+  for (i=0;i<st->maxk;i++)
     {
-      c1[0]=kugeln[i].x-a[0];
-      c1[1]=kugeln[i].y-a[1];
-      c1[2]=kugeln[i].z-a[2];
+      c1[0]=st->kugeln[i].x-st->a[0];
+      c1[1]=st->kugeln[i].y-st->a[1];
+      c1[2]=st->kugeln[i].z-st->a[2];
       cnorm=sqrt(c1[0]*c1[0]+c1[1]*c1[1]+c1[2]*c1[2]);
       
       c2[0]=c1[0];
       c2[1]=c1[1];
       c2[2]=c1[2];
       
-      cno=c2[0]*v[0]+c2[1]*v[1]+c2[2]*v[2];
-      kugeln[i].d=cnorm;
-      if (cno<0) kugeln[i].d=-20.0;
+      cno=c2[0]*st->v[0]+c2[1]*st->v[1]+c2[2]*st->v[2];
+      st->kugeln[i].d=cnorm;
+      if (cno<0) st->kugeln[i].d=-20.0;
       
       
-      kugeln[i].r1=(mag*zoom*kugeln[i].r/cnorm);
+      st->kugeln[i].r1=(st->mag*st->zoom*st->kugeln[i].r/cnorm);
       
-      c2[0]=v[0]/cno;
-      c2[1]=v[1]/cno;
-      c2[2]=v[2]/cno;
+      c2[0]=st->v[0]/cno;
+      c2[1]=st->v[1]/cno;
+      c2[2]=st->v[2]/cno;
       
       vektorprodukt(c2,c1,k);
 
       
-      x1=(startx+(x[0]*k[0]+x[1]*k[1]+x[2]*k[2])*mag);
-      y1=(starty-(y[0]*k[0]+y[1]*k[1]+y[2]*k[2])*mag);
+      x1=(st->startx+(st->x[0]*k[0]+st->x[1]*k[1]+st->x[2]*k[2])*st->mag);
+      y1=(st->starty-(st->y[0]*k[0]+st->y[1]*k[1]+st->y[2]*k[2])*st->mag);
       if(   (x1>-2000.0)
-        && (x1<scrnWidth+2000.0)
+        && (x1<st->scrnWidth+2000.0)
         && (y1>-2000.0)
-        && (y1<scrnHeight+2000.0))
+        && (y1<st->scrnHeight+2000.0))
        {
-         kugeln[i].x1=(int)x1;
-         kugeln[i].y1=(int)y1;
+         st->kugeln[i].x1=(int)x1;
+         st->kugeln[i].y1=(int)y1;
        }
       else
        {
-         kugeln[i].x1=0;
-         kugeln[i].y1=0;
-         kugeln[i].d=-20.0;
+         st->kugeln[i].x1=0;
+         st->kugeln[i].y1=0;
+         st->kugeln[i].d=-20.0;
        }
     }
 }
 
-/*---------- event-handler ----------------*/
-static void
-event_handler(void)
+
+static void *
+t3d_init (Display *dpy, Window window)
 {
-  while (XEventsQueued (dpy, QueuedAfterReading))
-    {
-      XEvent event;
-      
-      XNextEvent (dpy, &event);
-      switch (event.type)
-       {
-       case ConfigureNotify:
-         if (event.xconfigure.width != scrnWidth ||
-             event.xconfigure.height != scrnHeight)
-           {
-             XFreePixmap (dpy, buffer); 
-             scrnWidth = event.xconfigure.width;
-             scrnHeight = event.xconfigure.height;
-             buffer = XCreatePixmap (dpy, win, scrnWidth, scrnHeight,
-                                      xgwa.depth);
-             
-             startx=scrnWidth/2;
-             starty=scrnHeight/2;
-             scrnH2=startx;
-             scrnW2=starty;
-           };
-          break;
+  struct state *st = (struct state *) calloc (1, sizeof(*st));
+  st->dpy = dpy;
+  st->window = window;
+  st->dpy = dpy;
+  st->window = window;
+  initialize(st);
+  
+  initColor(st,st->r,st->g,st->b);
+  init_3d(st);
+  st->zeit=(struct tm *)malloc(sizeof(struct tm));
+  init_kugel(st);
+  
+  st->startx=st->scrnWidth/2;
+  st->starty=st->scrnHeight/2;
+  st->scrnH2=st->startx;
+  st->scrnW2=st->starty;
+  st->vspeed=0;
+  
+  
+  vektorprodukt(st->x,st->y,st->v);
+  viewpoint(st/*m,v*/);
+  
+  setink (BlackPixelOfScreen(st->xgwa.screen));
+  XFillRectangle (st->dpy, st->window, st->gc, 0, 0, st->scrnWidth, st->scrnHeight);
+  XQueryPointer (st->dpy, st->window, &st->junk_win, &st->junk_win, &st->junk, &st->junk,
+                &st->px, &st->py, &st->kb);
+  
+  return st;
+}
 
-       case KeyPress:
-         {
-           KeySym kpr=XKeycodeToKeysym(dpy,event.xkey.keycode,0);
-
-            switch (kpr)
-              {
-              case 's': case 'S':
-                vspeed = 0.5;
-                break;
-              case 'a': case 'A':
-                vspeed = -0.3;
-                break;
-
-              case '0':
-                speed = 0;
-                vspeed = 0;
-                break;
-
-              case 'z': case 'Z':
-                mag *= 1.02;
-                break;
-
-              case 'x': case 'X':
-                mag /= 1.02;
-                break;
-
-              default:
-                screenhack_handle_event (dpy, &event);
-                break;
-              }
-          }
+static unsigned long
+t3d_draw (Display *d, Window w, void *closure)
+{
+  struct state *st = (struct state *) closure;
+  double dtime;
+  double vnorm;
 
-        case ButtonPress: case ButtonRelease:
-          break;
+       
+  /*--------------- Zeichenteil --------------*/
 
-       default:
-          screenhack_handle_event (dpy, &event);
-         break;
-       }
+  vektorprodukt(st->x,st->y,st->v);
+       
+  vnorm=sqrt(st->v[0]*st->v[0]+st->v[1]*st->v[1]+st->v[2]*st->v[2]);
+  st->v[0]=st->v[0]*norm/vnorm;
+  st->v[1]=st->v[1]*norm/vnorm;
+  st->v[2]=st->v[2]*norm/vnorm;
+  vnorm=sqrt(st->x[0]*st->x[0]+st->x[1]*st->x[1]+st->x[2]*st->x[2]);
+  st->x[0]=st->x[0]*norm/vnorm;
+  st->x[1]=st->x[1]*norm/vnorm;
+  st->x[2]=st->x[2]*norm/vnorm;
+  vnorm=sqrt(st->y[0]*st->y[0]+st->y[1]*st->y[1]+st->y[2]*st->y[2]);
+  st->y[0]=st->y[0]*norm/vnorm;
+  st->y[1]=st->y[1]*norm/vnorm;
+  st->y[2]=st->y[2]*norm/vnorm;
+       
+  projektion(st);
+  t3d_sort (st,0,st->maxk-1);
+       
+  dtime=gettime(st);
+       
+  if(st->cycl)
+    {
+      st->draw_color=(int)(64.0*(dtime/60-floor(dtime/60)))-32;
+           
+      if(st->draw_color<0)
+        st->draw_color=-st->draw_color;
+           
+      setink(st->colors[st->draw_color/3].pixel);
     }
-  /*nap(40);-Ersatz*/ 
+  else
+    setink(BlackPixelOfScreen (st->xgwa.screen));
+       
+  XFillRectangle(st->dpy,st->buffer,st->gc,0,0,st->scrnWidth,st->scrnHeight);
+       
   {
-    struct timeval timeout;
-    timeout.tv_sec=timewait/1000000;
-    timeout.tv_usec=timewait%1000000;
-    (void)select(0,0,0,0,&timeout);
+    int i;
+         
+    manipulate(st,dtime);
+         
+    for (i=0;i<st->maxk;i++)
+      {
+        if (st->kugeln[i].d>0.0)
+          fill_kugel(st,i,st->buffer,1);
+      }
   }
+
+  /* manipulate(gettime());
+     var+=PI/500;
+     if (var>=TWOPI) var=PI/500; */
+       
+  if(st->hsvcycl!=0.0)
+    {
+      dtime=st->hsvcycl*dtime/10.0+st->hue/360.0;
+      dtime=360*(dtime-floor(dtime));
+           
+      hsv2rgb(dtime,st->sat,st->val,&st->r,&st->g,&st->b);
+      changeColor(st,st->r,st->g,st->b);
+    }
+
+  XCopyArea (st->dpy, st->buffer, st->window, st->gc, 0, 0, st->scrnWidth, st->scrnHeight, 0, 0);
+       
+       
+  /*-------------------------------------------------*/
+       
+  XQueryPointer (st->dpy, st->window, &st->junk_win, &st->in_win, &st->junk, &st->junk,
+                        &st->px, &st->py, &st->kb);
+       
+  if ((st->px>0)&&(st->px<st->scrnWidth)&&(st->py>0)&&(st->py<st->scrnHeight) )                
+    {
+      if ((st->px !=st->startx)&&(st->kb&Button2Mask))
+        {
+          /* printf("y=(%f,%f,%f)",y[0],y[1],y[2]);*/
+          turn(st->y,st->x,((double)(st->px-st->startx))/(8000*st->mag));
+          /* printf("->(%f,%f,%f)\n",y[0],y[1],y[2]);*/
+        }
+      if ((st->py !=st->starty)&&(st->kb&Button2Mask)) 
+        {
+          /* printf("x=(%f,%f,%f)",x[0],x[1],x[2]);*/
+          turn(st->x,st->y,((double)(st->py-st->starty))/(-8000*st->mag));
+          /* printf("->(%f,%f,%f)\n",x[0],x[1],x[2]);*/
+        }
+      if ((st->kb&Button1Mask)) 
+        {
+          if (st->vturn==0.0) st->vturn=.005; else if (st->vturn<2)  st->vturn+=.01;
+          turn(st->x,st->v,.002*st->vturn);
+          turn(st->y,st->v,.002*st->vturn); 
+        }
+      if ((st->kb&Button3Mask)) 
+        {
+          if (st->vturn==0.0) st->vturn=.005; else if (st->vturn<2) st->vturn+=.01;
+          turn(st->x,st->v,-.002*st->vturn);
+          turn(st->y,st->v,-.002*st->vturn);
+        }
+    }
+  if (!(st->kb&Button1Mask)&&!(st->kb&Button3Mask)) 
+    st->vturn=0;
+       
+  st->speed=st->speed+st->speed*st->vspeed;
+  if ((st->speed<0.0000001) &&(st->vspeed>0.000001)) st->speed=0.000001;
+  st->vspeed=.1*st->vspeed;
+  if (st->speed>0.01) st->speed=.01;
+  st->a[0]=st->a[0]+st->speed*st->v[0];
+  st->a[1]=st->a[1]+st->speed*st->v[1];
+  st->a[2]=st->a[2]+st->speed*st->v[2];
+
+  return st->timewait;
+}
+
+static void
+t3d_reshape (Display *dpy, Window window, void *closure, 
+                 unsigned int w, unsigned int h)
+{
+  struct state *st = (struct state *) closure;
+  if (w != st->scrnWidth ||
+      h != st->scrnHeight)
+    {
+      XFreePixmap (st->dpy, st->buffer); 
+      st->scrnWidth = w;
+      st->scrnHeight = h;
+      st->buffer = XCreatePixmap (st->dpy, st->window, st->scrnWidth, st->scrnHeight, st->xgwa.depth);
+             
+      st->startx=st->scrnWidth/2;
+      st->starty=st->scrnHeight/2;
+      st->scrnH2=st->startx;
+      st->scrnW2=st->starty;
+    }
+}
+
+static Bool
+t3d_event (Display *dpy, Window window, void *closure, XEvent *event)
+{
+  struct state *st = (struct state *) closure;
+  if (event->type == KeyPress)
+    {
+      KeySym kpr=XKeycodeToKeysym(st->dpy,event->xkey.keycode,0);
+
+      switch (kpr)
+        {
+        case 's': case 'S':
+          st->vspeed = 0.5;
+          return True;
+        case 'a': case 'A':
+          st->vspeed = -0.3;
+          return True;
+        case '0':
+          st->speed = 0;
+          st->vspeed = 0;
+          return True;
+        case 'z': case 'Z':
+          st->mag *= 1.02;
+          return True;
+        case 'x': case 'X':
+          st->mag /= 1.02;
+          return True;
+        default:
+          break;
+        }
+    }
+  return False;
+}
+
+static void
+t3d_free (Display *dpy, Window window, void *closure)
+{
 }
 
 
-/*-------------------------------------------------*/
 
-char *progclass = "T3D";
 
-char *defaults [] = {
+/*-------------------------------------------------*/
+
+static const char *t3d_defaults [] = {
   ".background:        black",
   ".foreground:        white",
   "*move:      0.5",
@@ -791,12 +942,14 @@ char *defaults [] = {
   "*minutes:   False",
   "*delay:      40000",
   "*fast:      50",
-  "*ccycle:    False",
+  "*colcycle:  False",
   "*hsvcycle:  0.0",
+  "*rgb:        ",
+  "*hsv:        ",
   0
 };
 
-XrmOptionDescRec options [] = {
+static XrmOptionDescRec t3d_options [] = {
   { "-move",           ".move",        XrmoptionSepArg, 0 },
   { "-wobble",         ".wobble",      XrmoptionSepArg, 0 },
   { "-cycle",          ".cycle",       XrmoptionSepArg, 0 },
@@ -813,159 +966,4 @@ XrmOptionDescRec options [] = {
 };
 
 
-void
-screenhack (Display *d, Window w)
-{
-  Window junk_win,in_win;
-  
-  int px,py,junk/*,wai*/;
-  unsigned int kb;
-/*  int act,act1,tc;*/
-  double vnorm;
-  /* double var=0.0; */
-  int color=0/*, dir=1*/;
-  
-  dpy = d;
-  win = w;
-  initialize();
-  
-  initColor(r,g,b);
-  init_3d();
-  zeit=(struct tm *)malloc(sizeof(struct tm));
-  init_kugel();
-  
-  startx=scrnWidth/2;
-  starty=scrnHeight/2;
-  scrnH2=startx;
-  scrnW2=starty;
-  vspeed=0;
-  
-  
-  vektorprodukt(x,y,v);
-  viewpoint(/*m,v*/);
-  
-  setink (BlackPixel (dpy, screen));
-  XFillRectangle (dpy, win, gc, 0, 0, scrnWidth, scrnHeight);
-  XQueryPointer (dpy, win, &junk_win, &junk_win, &junk, &junk,
-                &px, &py, &kb);
-  
-  for (;;)
-    {  double dtime;
-       
-       /*--------------- Zeichenteil --------------*/
-
-       event_handler();
-       
-       vektorprodukt(x,y,v);
-       
-       vnorm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
-       v[0]=v[0]*norm/vnorm;
-       v[1]=v[1]*norm/vnorm;
-       v[2]=v[2]*norm/vnorm;
-       vnorm=sqrt(x[0]*x[0]+x[1]*x[1]+x[2]*x[2]);
-       x[0]=x[0]*norm/vnorm;
-       x[1]=x[1]*norm/vnorm;
-       x[2]=x[2]*norm/vnorm;
-       vnorm=sqrt(y[0]*y[0]+y[1]*y[1]+y[2]*y[2]);
-       y[0]=y[0]*norm/vnorm;
-       y[1]=y[1]*norm/vnorm;
-       y[2]=y[2]*norm/vnorm;
-       
-       projektion();
-       t3d_sort (0,maxk-1);
-       
-       dtime=gettime();
-       
-       if(cycl)
-         {
-           color=(int)(64.0*(dtime/60-floor(dtime/60)))-32;
-           
-           if(color<0)
-             color=-color;
-           
-           setink(colors[color/3].pixel);
-         }
-       else
-         setink(BlackPixel (dpy, screen));
-       
-       XFillRectangle(dpy,buffer,gc,0,0,scrnWidth,scrnHeight);
-       
-       {
-         int i;
-         
-         manipulate(dtime);
-         
-         for (i=0;i<maxk;i++)
-           {
-             if (kugeln[i].d>0.0)
-               fill_kugel(i,buffer,1);
-           }
-       }
-
-       XSync(dpy,0);
-       
-       /* manipulate(gettime());
-          var+=PI/500;
-          if (var>=TWOPI) var=PI/500; */
-       
-       /*event_handler();*/
-       
-       if(hsvcycl!=0.0)
-         {
-           dtime=hsvcycl*dtime/10.0+hue/360.0;
-           dtime=360*(dtime-floor(dtime));
-           
-           hsv2rgb(dtime,sat,val,&r,&g,&b);
-           changeColor(r,g,b);
-         }
-
-       XCopyArea (dpy, buffer, win, gc, 0, 0, scrnWidth, scrnHeight, 0, 0);
-       
-       
-       /*-------------------------------------------------*/
-       XSync(dpy,0);
-       
-       event_handler();
-       
-       (void)(XQueryPointer (dpy, win, &junk_win, &in_win, &junk, &junk,
-                             &px, &py, &kb));
-       
-       if ((px>0)&&(px<scrnWidth)&&(py>0)&&(py<scrnHeight) )           
-         {
-           if ((px !=startx)&&(kb&Button2Mask))
-             {
-               /* printf("y=(%f,%f,%f)",y[0],y[1],y[2]);*/
-               turn(y,x,((double)(px-startx))/(8000*mag));
-               /* printf("->(%f,%f,%f)\n",y[0],y[1],y[2]);*/
-             }
-           if ((py !=starty)&&(kb&Button2Mask)) 
-             {
-               /* printf("x=(%f,%f,%f)",x[0],x[1],x[2]);*/
-               turn(x,y,((double)(py-starty))/(-8000*mag));
-               /* printf("->(%f,%f,%f)\n",x[0],x[1],x[2]);*/
-             }
-           if ((kb&Button1Mask)) 
-             {
-               if (vturn==0.0) vturn=.005; else if (vturn<2)  vturn+=.01;
-               turn(x,v,.002*vturn);
-               turn(y,v,.002*vturn); 
-             }
-           if ((kb&Button3Mask)) 
-             {
-               if (vturn==0.0) vturn=.005; else if (vturn<2) vturn+=.01;
-               turn(x,v,-.002*vturn);
-               turn(y,v,-.002*vturn);
-             }
-         }
-       if (!(kb&Button1Mask)&&!(kb&Button3Mask)) 
-         vturn=0;
-       
-       speed=speed+speed*vspeed;
-       if ((speed<0.0000001) &&(vspeed>0.000001)) speed=0.000001;
-       vspeed=.1*vspeed;
-       if (speed>0.01) speed=.01;
-       a[0]=a[0]+speed*v[0];
-       a[1]=a[1]+speed*v[1];
-       a[2]=a[2]+speed*v[2];
-      }
-}
+XSCREENSAVER_MODULE ("T3D", t3d)