ftp://ftp.krokus.ru/pub/OpenBSD/distfiles/xscreensaver-4.21.tar.gz
[xscreensaver] / hacks / ifs.c
index 29a72c23144d59f3d0b93e42ee91ba284fc765dd..60d4d9cc503093e329c0e884fd5ea1659fa57069 100644 (file)
-/* -*- Mode: C; tab-width: 4 -*- */
-/* ifs --- modified iterated functions system */
-
-#if 0
-static const char sccsid[] = "@(#)ifs.c        5.00 2000/11/01 xlockmore";
-#endif
-
-/*-
- * Copyright (c) 1997 by Massimino Pascal <Pascal.Massimon@ens.fr>
- *
- * Permission to use, copy, modify, and distribute this software and its
- * documentation for any purpose and without fee is hereby granted,
- * provided that the above copyright notice appear in all copies and that
- * both that copyright notice and this permission notice appear in
- * supporting documentation.
- *
- * This file is provided AS IS with no warranties of any kind.  The author
- * shall have no liability with respect to the infringement of copyrights,
- * trade secrets or any patents by this file or any part thereof.  In no
- * event will the author be liable for any lost revenue or profits or
- * other special, indirect and consequential damages.
- *
- * If this mode is weird and you have an old MetroX server, it is buggy.
- * There is a free SuSE-enhanced MetroX X server that is fine.
- *
- * When shown ifs, Diana Rose (4 years old) said, "It looks like dancing."
- *
- * Revision History:
- * 01-Nov-2000: Allocation checks
- * 10-May-1997: jwz@jwz.org: turned into a standalone program.
- *              Made it render into an offscreen bitmap and then copy
- *              that onto the screen, to reduce flicker.
- */
-
-#ifdef STANDALONE
-#define MODE_ifs
-#define PROGCLASS "IFS"
-#define HACK_INIT init_ifs
-#define HACK_DRAW draw_ifs
-#define ifs_opts xlockmore_opts
-#define DEFAULTS "*delay: 20000 \n" \
- "*ncolors: 100 \n"
-#define SMOOTH_COLORS
-#include "xlockmore.h"         /* in xscreensaver distribution */
-#else /* STANDALONE */
-#include "xlock.h"             /* in xlockmore distribution */
-#endif /* STANDALONE */
-
-#ifdef MODE_ifs
-
-ModeSpecOpt ifs_opts =
-{0, (XrmOptionDescRec *) NULL, 0, (argtype *) NULL, (OptionStruct *) NULL};
-
-#ifdef USE_MODULES
-ModStruct   ifs_description =
-{"ifs", "init_ifs", "draw_ifs", "release_ifs",
- "init_ifs", "init_ifs", (char *) NULL, &ifs_opts,
- 1000, 1, 1, 1, 64, 1.0, "",
- "Shows a modified iterated function system", 0, NULL};
-
-#endif
-
-/*****************************************************/
-
-typedef float DBL;
-typedef int F_PT;
-
-/* typedef float               F_PT; */
-
-/*****************************************************/
-
-#define FIX 12
-#define UNIT   ( 1<<FIX )
-#define MAX_SIMI  6
-
-   /* settings for a PC 120Mhz... */
-#define MAX_DEPTH_2  10
-#define MAX_DEPTH_3  6
-#define MAX_DEPTH_4  4
-#define MAX_DEPTH_5  3
-
-#define DBL_To_F_PT(x)  (F_PT)( (DBL)(UNIT)*(x) )
-
-typedef struct Similitude_Struct SIMI;
-typedef struct Fractal_Struct FRACTAL;
-
-struct Similitude_Struct {
-
-       DBL         c_x, c_y;
-       DBL         r, r2, A, A2;
-       F_PT        Ct, St, Ct2, St2;
-       F_PT        Cx, Cy;
-       F_PT        R, R2;
-};
+/*Copyright © Chris Le Sueur (thefishface@gmail.com) February 2005
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Ultimate thanks go to Massimino Pascal, who created the original
+xscreensaver hack, and inspired me with it's swirly goodness. This
+version adds things like variable quality, number of functions and also
+a groovier colouring mode.
+
+*/
+
+#include <assert.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include "screenhack.h"
+
+static float myrandom(float up)
+{
+  return(((float)random()/RAND_MAX)*up);
+}
 
-struct Fractal_Struct {
-
-       int         Nb_Simi;
-       SIMI        Components[5 * MAX_SIMI];
-       int         Depth, Col;
-       int         Count, Speed;
-       int         Width, Height, Lx, Ly;
-       DBL         r_mean, dr_mean, dr2_mean;
-       int         Cur_Pt, Max_Pt;
-       XPoint     *Buffer1, *Buffer2;
-       Pixmap      dbuf;
-       GC          dbuf_gc;
+static int delay;
+static int lensnum;
+static int length;
+static int mode;
+static Bool notranslate, noscale, norotate;
+float ht,wt;
+float hs,ws;
+int width,height;
+float r;
+long wcol;
+int coloffset;
+
+float nx,ny;
+
+int count;
+
+/*X stuff*/
+GC gc;
+Window w;
+Display *dpy;
+Pixmap backbuffer;
+XColor *colours;
+int ncolours;
+int screen_num;
+
+int blackColor, whiteColor;
+
+char *progclass = "IFS";
+
+char *defaults [] = {
+  ".lensnum:    3",
+  ".length:     9",
+  ".mode:     0",
+  ".colors:     200",
+  "*delay:      10000",
+  "*notranslate:  False",
+  "*noscale:    False",
+  "*norotate:   False",
+  0
 };
 
-static FRACTAL *Root = (FRACTAL *) NULL, *Cur_F;
-static XPoint *Buf;
-static int  Cur_Pt;
-
-
-/*****************************************************/
+XrmOptionDescRec options [] = {
+  { "-detail",    ".length",    XrmoptionSepArg, 0 },
+  { "-delay",   ".delay",   XrmoptionSepArg, 0 },
+  { "-mode",    ".mode",    XrmoptionSepArg, 0 },
+  { "-colors",    ".colors",    XrmoptionSepArg, 0 },
+  { "-functions", ".lensnum",   XrmoptionSepArg, 0 },
+  { "-notranslate", ".notranslate", XrmoptionNoArg,  "True" },
+  { "-noscale",   ".noscale",   XrmoptionNoArg,  "True" },
+  { "-norotate",  ".norotate",  XrmoptionNoArg,  "True" },
+  { 0, 0, 0, 0 }
+};
 
-static      DBL
-Gauss_Rand(DBL c, DBL A, DBL S)
+/*Takes the average of two colours, with some nifty bit-shifting*/
+static long blend(long c1, long c2)
 {
-       DBL         y;
-
-       y = (DBL) LRAND() / MAXRAND;
-       y = A * (1.0 - exp(-y * y * S)) / (1.0 - exp(-S));
-       if (NRAND(2))
-               return (c + y);
-       return (c - y);
+  long R1=(c1 & 0xFF0000) >> 16;
+  long R2=(c2 & 0xFF0000) >> 16;
+  long G1=(c1 & 0x00FF00) >> 8;
+  long G2=(c2 & 0x00FF00) >> 8;
+  long B1=(c1 & 0x0000FF);
+  long B2=(c2 & 0x0000FF);
+  
+  return (((R1+R2)/2 << 16) | ((G1+G2)/2 << 8) | ((B1+B2)/2));
 }
 
-static      DBL
-Half_Gauss_Rand(DBL c, DBL A, DBL S)
+/*Draw a point on the backbuffer*/
+static void sp(float x, float y, long c)
 {
-       DBL         y;
-
-       y = (DBL) LRAND() / MAXRAND;
-       y = A * (1.0 - exp(-y * y * S)) / (1.0 - exp(-S));
-       return (c + y);
+  x+=16;    x*=wt;
+  y=16.5-y; y*=ht;
+  if(x<0 || x>=width || y<0 || y>=height) return;
+  XSetForeground(dpy, gc, c);
+  XDrawPoint(dpy, backbuffer, gc, (int)x, (int)y);
 }
 
-static void
-Random_Simis(FRACTAL * F, SIMI * Cur, int i)
+/*Copy backbuffer to front buffer and clear backbuffer*/
+static void draw(void)
 {
-       while (i--) {
-               Cur->c_x = Gauss_Rand(0.0, .8, 4.0);
-               Cur->c_y = Gauss_Rand(0.0, .8, 4.0);
-               Cur->r = Gauss_Rand(F->r_mean, F->dr_mean, 3.0);
-               Cur->r2 = Half_Gauss_Rand(0.0, F->dr2_mean, 2.0);
-               Cur->A = Gauss_Rand(0.0, 360.0, 4.0) * (M_PI / 180.0);
-               Cur->A2 = Gauss_Rand(0.0, 360.0, 4.0) * (M_PI / 180.0);
-               Cur++;
-       }
+  XCopyArea(  dpy,
+              backbuffer, w,
+              gc,
+              0, 0,
+              width, height,
+              0, 0);
+  
+  XSetForeground(dpy, gc, blackColor);
+  XFillRectangle( dpy,
+                  backbuffer,
+                  gc,
+                  0, 0,
+                  width, height);
 }
 
-static void
-free_ifs_buffers(FRACTAL *Fractal)
+typedef struct {
+  float r,s,tx,ty;
+  /*Rotation, Scale, Translation X & Y*/
+  float ra,raa,sa,txa,tya;
+  
+  int co;
+} Lens; 
+
+
+static void CreateLens(float nr, 
+        float ns, 
+        float nx, 
+        float ny, 
+        int nco,
+        Lens *newlens)
 {
-       if (Fractal->Buffer1 != NULL) {
-               (void) free((void *) Fractal->Buffer1);
-               Fractal->Buffer1 = (XPoint *) NULL;
-       }
-       if (Fractal->Buffer2 != NULL) {
-               (void) free((void *) Fractal->Buffer2);
-               Fractal->Buffer2 = (XPoint *) NULL;
-       }
+  newlens->ra=newlens->raa=newlens->sa=newlens->txa=newlens->tya=0;
+  if(!norotate) newlens->r=nr;
+  else newlens->r=0;
+    
+  if(!noscale) newlens->s=ns;
+  else newlens->s=0.5;
+    
+  if(!notranslate) {
+    newlens->tx=nx;
+    newlens->ty=ny;
+  } else {
+    newlens->tx=nx;
+    newlens->tx=ny;
+  }
+    
+  newlens->co=nco;
 }
-
-
-static void
-free_ifs(Display *display, FRACTAL *Fractal)
+  
+static float stepx(float x, float y, Lens *l)
 {
-       free_ifs_buffers(Fractal);
-       if (Fractal->dbuf != None) {
-               XFreePixmap(display, Fractal->dbuf);
-               Fractal->dbuf = None;
-       }
-       if (Fractal->dbuf_gc != None) {
-               XFreeGC(display, Fractal->dbuf_gc);
-               Fractal->dbuf_gc = None;
-       }
+  return l->s*cos(l->r)*x+l->s*sin(l->r)*y+l->tx;
 }
 
-/***************************************************************/
-
-void
-init_ifs(ModeInfo * mi)
+static float stepy(float x, float y, Lens *l)
 {
-       Display    *display = MI_DISPLAY(mi);
-       Window      window = MI_WINDOW(mi);
-       GC          gc = MI_GC(mi);
-       int         i;
-       FRACTAL    *Fractal;
-
-       if (Root == NULL) {
-               Root = (FRACTAL *) calloc(
-                                      MI_NUM_SCREENS(mi), sizeof (FRACTAL));
-               if (Root == NULL)
-                       return;
-       }
-       Fractal = &Root[MI_SCREEN(mi)];
-
-       free_ifs_buffers(Fractal);
-       i = (NRAND(4)) + 2;     /* Number of centers */
-       switch (i) {
-               case 3:
-                       Fractal->Depth = MAX_DEPTH_3;
-                       Fractal->r_mean = .6;
-                       Fractal->dr_mean = .4;
-                       Fractal->dr2_mean = .3;
-                       break;
-
-               case 4:
-                       Fractal->Depth = MAX_DEPTH_4;
-                       Fractal->r_mean = .5;
-                       Fractal->dr_mean = .4;
-                       Fractal->dr2_mean = .3;
-                       break;
-
-               case 5:
-                       Fractal->Depth = MAX_DEPTH_5;
-                       Fractal->r_mean = .5;
-                       Fractal->dr_mean = .4;
-                       Fractal->dr2_mean = .3;
-                       break;
-
-               default:
-               case 2:
-                       Fractal->Depth = MAX_DEPTH_2;
-                       Fractal->r_mean = .7;
-                       Fractal->dr_mean = .3;
-                       Fractal->dr2_mean = .4;
-                       break;
-       }
-       /* (void) fprintf( stderr, "N=%d\n", i ); */
-       Fractal->Nb_Simi = i;
-       Fractal->Max_Pt = Fractal->Nb_Simi - 1;
-       for (i = 0; i <= Fractal->Depth + 2; ++i)
-               Fractal->Max_Pt *= Fractal->Nb_Simi;
-
-       if ((Fractal->Buffer1 = (XPoint *) calloc(Fractal->Max_Pt,
-                       sizeof (XPoint))) == NULL) {
-               free_ifs(display, Fractal);
-               return;
-       }
-       if ((Fractal->Buffer2 = (XPoint *) calloc(Fractal->Max_Pt,
-                       sizeof (XPoint))) == NULL) {
-               free_ifs(display, Fractal);
-               return;
-       }
-       Fractal->Speed = 6;
-       Fractal->Width = MI_WIDTH(mi);
-       Fractal->Height = MI_HEIGHT(mi);
-       Fractal->Cur_Pt = 0;
-       Fractal->Count = 0;
-       Fractal->Lx = (Fractal->Width - 1) / 2;
-       Fractal->Ly = (Fractal->Height - 1) / 2;
-       Fractal->Col = NRAND(MI_NPIXELS(mi) - 1) + 1;
-
-       Random_Simis(Fractal, Fractal->Components, 5 * MAX_SIMI);
-
-#ifndef NO_DBUF
-       if (Fractal->dbuf != None)
-               XFreePixmap(display, Fractal->dbuf);
-       Fractal->dbuf = XCreatePixmap(display, window,
-                                     Fractal->Width, Fractal->Height, 1);
-       /* Allocation checked */
-       if (Fractal->dbuf != None) {
-               XGCValues   gcv;
-
-               gcv.foreground = 0;
-               gcv.background = 0;
-               gcv.graphics_exposures = False;
-               gcv.function = GXcopy;
-
-               if (Fractal->dbuf_gc != None)
-                       XFreeGC(display, Fractal->dbuf_gc);
-               if ((Fractal->dbuf_gc = XCreateGC(display, Fractal->dbuf,
-                               GCForeground | GCBackground | GCGraphicsExposures | GCFunction,
-                               &gcv)) == None) {
-                       XFreePixmap(display, Fractal->dbuf);
-                       Fractal->dbuf = None;
-               } else {
-                       XFillRectangle(display, Fractal->dbuf,
-                           Fractal->dbuf_gc, 0, 0, Fractal->Width, Fractal->Height);
-                       XSetBackground(display, gc, MI_BLACK_PIXEL(mi));
-                       XSetFunction(display, gc, GXcopy);
-               }
-       }
-#endif
-       MI_CLEARWINDOW(mi);
-
-       /* don't want any exposure events from XCopyPlane */
-       XSetGraphicsExposures(display, gc, False);
-
+  return l->s*sin(l->r)*-x+l->s*cos(l->r)*y+l->ty;
 }
 
-
-/***************************************************************/
-
-/* Should be taken care of already... but just in case */
-#if !defined( __GNUC__ ) && !defined(__cplusplus) && !defined(c_plusplus)
-#undef inline
-#define inline                 /* */
-#endif
-static inline void
-Transform(SIMI * Simi, F_PT xo, F_PT yo, F_PT * x, F_PT * y)
+static void mutate(Lens *l)
 {
-       F_PT        xx, yy;
-
-       xo = xo - Simi->Cx;
-       xo = (xo * Simi->R) / UNIT;
-       yo = yo - Simi->Cy;
-       yo = (yo * Simi->R) / UNIT;
-
-       xx = xo - Simi->Cx;
-       xx = (xx * Simi->R2) / UNIT;
-       yy = -yo - Simi->Cy;
-       yy = (yy * Simi->R2) / UNIT;
-
-       *x = ((xo * Simi->Ct - yo * Simi->St + xx * Simi->Ct2 - yy * Simi->St2) / UNIT) + Simi->Cx;
-       *y = ((xo * Simi->St + yo * Simi->Ct + xx * Simi->St2 + yy * Simi->Ct2) / UNIT) + Simi->Cy;
+  if(!norotate) {
+    l->raa+=myrandom(0.002)-0.001;
+    l->ra+=l->raa;
+    l->r +=l->ra;
+    if(l->ra>0.07  || l->ra<-0.07)  l->ra/=1.4;
+    if(l->raa>0.005 || l->raa<-0.005) l->raa/=1.2;
+  }
+  if(!noscale) {
+    l->sa+=myrandom(0.01)-0.005;
+    l->s +=l->sa;
+    if(l->s>0.4) l->sa -=0.004;
+    if(l->s<-0.4) l->sa +=0.004;
+    if(l->sa>0.07  || l->sa<-0.07)  l->sa/=1.4;
+  }
+  if(!notranslate) {
+    l->txa+=myrandom(0.004)-0.002;
+    l->tya+=myrandom(0.004)-0.002;
+    l->tx+=l->txa;
+    l->ty+=l->tya;
+    if(l->tx>6)  l->txa-=0.004;
+    if(l->ty>6)  l->tya-=0.004;
+    if(l->tx<-6)  l->txa+=0.004;
+    if(l->ty<-6)  l->tya+=0.004;
+    if(l->txa>0.05 || l->txa<-0.05) l->txa/=1.7;
+    if(l->tya>0.05 || l->tya<-0.05) l->tya/=1.7;
+  }
+  
+  /*Groovy, colour-shifting functions!*/
+  l->co++;
+  l->co %= ncolours;
 }
 
-/***************************************************************/
+Lens **lenses;
 
-static void
-Trace(FRACTAL * F, F_PT xo, F_PT yo)
+/* Calls itself <lensnum> times - with results from each lens/function.  *
+ * After <length> calls to itself, it stops iterating and draws a point. */
+static void iterate(float x, float y, long curcol, int length)
 {
-       F_PT        x, y, i;
-       SIMI       *Cur;
-
-       Cur = Cur_F->Components;
-       for (i = Cur_F->Nb_Simi; i; --i, Cur++) {
-               Transform(Cur, xo, yo, &x, &y);
-               /* Buf->x = F->Lx + (x * F->Lx / (UNIT * 2)); */
-               /* Buf->y = F->Ly - (y * F->Ly / (UNIT * 2)); */
-        Buf->x = (UNIT * 2 + x) * F->Lx / (UNIT * 2);
-        Buf->y = (UNIT * 2 - y) * F->Ly / (UNIT * 2);
-               Buf++;
-               Cur_Pt++;
-
-               if (F->Depth && ((x - xo) >> 4) && ((y - yo) >> 4)) {
-                       F->Depth--;
-                       Trace(F, x, y);
-                       F->Depth++;
-               }
-       }
+  int i;
+  if(length == 0) {
+    sp(x,y,curcol);
+  } else {
+    /*iterate(lenses[0].stepx(x,y),lenses[0].stepy(x,y),length-1);
+      iterate(lenses[1].stepx(x,y),lenses[1].stepy(x,y),length-1);
+      iterate(lenses[2].stepx(x,y),lenses[2].stepy(x,y),length-1);*/
+    for(i=0;i<lensnum;i++) {
+      switch(mode) {
+      case 0 : iterate(stepx( x, y, lenses[i]), stepy( x, y, lenses[i]), blend( curcol,colours[(int)lenses[i]->co].pixel ), length-1); break;
+      case 1 : iterate(stepx( x, y, lenses[i]), stepy( x, y, lenses[i]), colours[(int)lenses[i]->co].pixel, length-1); break;
+      case 2 : iterate(stepx( x, y, lenses[i]), stepy( x, y, lenses[i]), curcol, length-1); break;
+      default: exit(0);
+      }
+    }
+  }
+  count++;
 }
 
-static void
-Draw_Fractal(ModeInfo * mi)
+/* Come on and iterate, iterate, iterate and sing... *
+ * Yeah, this function just calls iterate, mutate,   *
+ * and then draws everything.                        */
+static void step(void)
 {
-       Display    *display = MI_DISPLAY(mi);
-       Window      window = MI_WINDOW(mi);
-       GC          gc = MI_GC(mi);
-       FRACTAL    *F = &Root[MI_SCREEN(mi)];
-       int         i, j;
-       F_PT        x, y, xo, yo;
-       SIMI       *Cur, *Simi;
-
-       for (Cur = F->Components, i = F->Nb_Simi; i; --i, Cur++) {
-               Cur->Cx = DBL_To_F_PT(Cur->c_x);
-               Cur->Cy = DBL_To_F_PT(Cur->c_y);
-
-               Cur->Ct = DBL_To_F_PT(cos(Cur->A));
-               Cur->St = DBL_To_F_PT(sin(Cur->A));
-               Cur->Ct2 = DBL_To_F_PT(cos(Cur->A2));
-               Cur->St2 = DBL_To_F_PT(sin(Cur->A2));
-
-               Cur->R = DBL_To_F_PT(Cur->r);
-               Cur->R2 = DBL_To_F_PT(Cur->r2);
-       }
-
-
-       Cur_Pt = 0;
-       Cur_F = F;
-       Buf = F->Buffer2;
-       for (Cur = F->Components, i = F->Nb_Simi; i; --i, Cur++) {
-               xo = Cur->Cx;
-               yo = Cur->Cy;
-               for (Simi = F->Components, j = F->Nb_Simi; j; --j, Simi++) {
-                       if (Simi == Cur)
-                               continue;
-                       Transform(Simi, xo, yo, &x, &y);
-                       Trace(F, x, y);
-               }
-       }
-
-       /* Erase previous */
-       if (F->Cur_Pt) {
-               XSetForeground(display, gc, MI_BLACK_PIXEL(mi));
-               if (F->dbuf != None) {
-                       XSetForeground(display, F->dbuf_gc, 0);
-                       /* XDrawPoints(display, F->dbuf, F->dbuf_gc, F->Buffer1, F->Cur_Pt,
-                               CoordModeOrigin); */
-                       XFillRectangle(display, F->dbuf, F->dbuf_gc, 0, 0,
-                                      F->Width, F->Height);
-               } else
-                       XDrawPoints(display, window, gc, F->Buffer1, F->Cur_Pt, CoordModeOrigin);
-       }
-       if (MI_NPIXELS(mi) < 2)
-               XSetForeground(display, gc, MI_WHITE_PIXEL(mi));
-       else
-               XSetForeground(display, gc, MI_PIXEL(mi, F->Col % MI_NPIXELS(mi)));
-       if (Cur_Pt) {
-               if (F->dbuf != None) {
-                       XSetForeground(display, F->dbuf_gc, 1);
-                       XDrawPoints(display, F->dbuf, F->dbuf_gc, F->Buffer2, Cur_Pt,
-                                   CoordModeOrigin);
-               } else
-                       XDrawPoints(display, window, gc, F->Buffer2, Cur_Pt, CoordModeOrigin);
-       }
-       if (F->dbuf != None)
-               XCopyPlane(display, F->dbuf, window, gc, 0, 0, F->Width, F->Height, 0, 0, 1);
-
-       F->Cur_Pt = Cur_Pt;
-       Buf = F->Buffer1;
-       F->Buffer1 = F->Buffer2;
-       F->Buffer2 = Buf;
+  int i;
+  if(mode == 2) {
+    wcol++;
+    wcol %= ncolours;
+    iterate(0,0,colours[wcol].pixel,length);
+  } else {
+    iterate(0,0,0xFFFFFF,length);
+  }
+  
+  
+  count=0;
+  
+  for(i=0;i<lensnum;i++) {
+    mutate(lenses[i]);
+  }
+  draw();
 }
 
-
-void
-draw_ifs(ModeInfo * mi)
+static void init_ifs(void)
 {
-       int         i;
-       DBL         u, uu, v, vv, u0, u1, u2, u3;
-       SIMI       *S, *S1, *S2, *S3, *S4;
-       FRACTAL    *F;
-
-       if (Root == NULL)
-               return;
-       F = &Root[MI_SCREEN(mi)];
-       if (F->Buffer1 == NULL)
-               return;
-
-       u = (DBL) (F->Count) * (DBL) (F->Speed) / 1000.0;
-       uu = u * u;
-       v = 1.0 - u;
-       vv = v * v;
-       u0 = vv * v;
-       u1 = 3.0 * vv * u;
-       u2 = 3.0 * v * uu;
-       u3 = u * uu;
-
-       S = F->Components;
-       S1 = S + F->Nb_Simi;
-       S2 = S1 + F->Nb_Simi;
-       S3 = S2 + F->Nb_Simi;
-       S4 = S3 + F->Nb_Simi;
-
-       for (i = F->Nb_Simi; i; --i, S++, S1++, S2++, S3++, S4++) {
-               S->c_x = u0 * S1->c_x + u1 * S2->c_x + u2 * S3->c_x + u3 * S4->c_x;
-               S->c_y = u0 * S1->c_y + u1 * S2->c_y + u2 * S3->c_y + u3 * S4->c_y;
-               S->r = u0 * S1->r + u1 * S2->r + u2 * S3->r + u3 * S4->r;
-               S->r2 = u0 * S1->r2 + u1 * S2->r2 + u2 * S3->r2 + u3 * S4->r2;
-               S->A = u0 * S1->A + u1 * S2->A + u2 * S3->A + u3 * S4->A;
-               S->A2 = u0 * S1->A2 + u1 * S2->A2 + u2 * S3->A2 + u3 * S4->A2;
-       }
-
-       MI_IS_DRAWN(mi) = True;
-
-       Draw_Fractal(mi);
-
-       if (F->Count >= 1000 / F->Speed) {
-               S = F->Components;
-               S1 = S + F->Nb_Simi;
-               S2 = S1 + F->Nb_Simi;
-               S3 = S2 + F->Nb_Simi;
-               S4 = S3 + F->Nb_Simi;
-
-               for (i = F->Nb_Simi; i; --i, S++, S1++, S2++, S3++, S4++) {
-                       S2->c_x = 2.0 * S4->c_x - S3->c_x;
-                       S2->c_y = 2.0 * S4->c_y - S3->c_y;
-                       S2->r = 2.0 * S4->r - S3->r;
-                       S2->r2 = 2.0 * S4->r2 - S3->r2;
-                       S2->A = 2.0 * S4->A - S3->A;
-                       S2->A2 = 2.0 * S4->A2 - S3->A2;
-
-                       *S1 = *S4;
-               }
-               Random_Simis(F, F->Components + 3 * F->Nb_Simi, F->Nb_Simi);
-
-               Random_Simis(F, F->Components + 4 * F->Nb_Simi, F->Nb_Simi);
-
-               F->Count = 0;
-       } else
-               F->Count++;
-
-       F->Col++;
+  Window rw;
+  int i;
+  XWindowAttributes xgwa;
+  
+  delay = get_integer_resource("delay", "Delay");
+  length = get_integer_resource("length", "Detail");
+  mode = get_integer_resource("mode", "Mode");
+
+  norotate    = get_boolean_resource("norotate", "NoRotate");
+  noscale     = get_boolean_resource("noscale", "NoScale");
+  notranslate = get_boolean_resource("notranslate", "NoTranslate");
+
+  lensnum = get_integer_resource("lensnum", "Functions");
+  
+  lenses = malloc(sizeof(Lens)*lensnum);
+  
+  for(i=0;i<lensnum;i++) {
+    lenses[i]=malloc(sizeof(Lens));
+  }
+  
+  /*Thanks go to Dad for teaching me how to allocate memory for struct**s . */
+  
+  XGetWindowAttributes (dpy, w, &xgwa);
+  width=xgwa.width;
+  height=xgwa.height;
+  
+  /*Initialise all this X shizzle*/
+  blackColor = BlackPixel(dpy, DefaultScreen(dpy));
+  whiteColor = WhitePixel(dpy, DefaultScreen(dpy));
+  rw = RootWindow(dpy, screen_num);
+  screen_num = DefaultScreen(dpy);
+  gc = XCreateGC(dpy, rw, 0, NULL);
+  
+  /* Do me some colourmap magic. If we're using blend mode, this is just   *
+   * for the nice colours - we're still using true/hicolour. Screw me if   *
+   * I'm going to work out how to blend with colourmaps - I'm too young to *
+   * die!! On a sidenote, this is mostly stolen from halftone because I    *
+   * don't really know what the hell I'm doing, here.                      */
+  ncolours = get_integer_resource("colors", "Colors");
+  if(ncolours < lensnum) ncolours=lensnum; /*apparently you're allowed to do this kind of thing...*/
+  colours = (XColor *)calloc(ncolours, sizeof(XColor));
+  make_smooth_colormap (  dpy,
+                          xgwa.visual,
+                          xgwa.colormap,
+                          colours,
+                          &ncolours,
+                          True, 0, False);
+  /*No, I didn't have a clue what that really did... hopefully I have some colours in an array, now.*/
+  wcol = (int)myrandom(ncolours);
+    
+  /*Double buffering - I can't be bothered working out the XDBE thingy*/
+  backbuffer = XCreatePixmap(dpy, w, width, height, XDefaultDepth(dpy, screen_num));
+  
+  /*Scaling factor*/
+  wt=width/32;
+  ht=height/24;
+  
+  ws=400;
+  hs=400;
+
+  /*Colourmapped colours for the general prettiness*/
+  for(i=0;i<lensnum;i++) {
+    CreateLens( myrandom(1)-0.5,
+                myrandom(1),
+                myrandom(4)-2,
+                myrandom(4)+2,
+                myrandom(ncolours),
+                lenses[i]);
+  }
 }
 
-
-/***************************************************************/
-
 void
-release_ifs(ModeInfo * mi)
+screenhack (Display *display, Window window)
 {
-       if (Root != NULL) {
-               int         screen;
-
-               for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
-                       free_ifs(MI_DISPLAY(mi), &Root[screen]);
-               (void) free((void *) Root);
-               Root = (FRACTAL *) NULL;
-       }
+  dpy = display;
+  w   = window;
+  
+  init_ifs();
+  
+  while (1) {
+    step();
+    screenhack_handle_events(dpy);
+    if (delay) usleep(delay);
+  }
 }
-
-#endif /* MODE_ifs */