A Sample X Program

/*  xifs  */

/* by Thomas Colthurst.  Version 1.0.  Started April 7, 1990. */

/* Displays the IFS attractor whose codes are stored in a file of the following format:

   numpixels
   xsize ysize
   xposition yposition
   numtransformations
   p1 a1 b1 c1 d1 e1 f1
   ...
   pn an bn cn dn en fn

   where size and position are based upon a window size of [500 x 500], 
         p is the probability of the transformation,
         and a .. f determine the transformation
	 x = [ a b ] x + [ e ]
             [ c d ]     [ f ]

   At present, numpixels is not supported and the image will be generated until the
   program stops.  The program can be stopped by pressing a mouse button in the
   window or by typing a 'q' in the window.  The image can be saved by typing a 's'
   in the window, and then entering a filename.

*/


/* External functions and information */

#include 
#include 
#include 
#include 

long random();


/* Global functions and variables */

#define irint(x)  ( (int) rint(x) )

typedef struct {
  double x, y;
} point;

char xifs[] = "tc's xifs";

point nextpoint();

/* X variables */

Display *mydisplay;
Window  mywindow;
GC      mygc;
XEvent  myevent;
KeySym  mykey;
XSizeHints myhint;
XSetWindowAttributes my_window_attributes;

int myscreen;
unsigned long myforeground, mybackground;
unsigned long my_win_values_mask;


/* file IFS information */

typedef struct {
  int stop;
  double xsize, ysize;
  double x0, y0;
  int wnum;
  double w[1000][7];
} IFS;

IFS theifs;


/* Function Declarations */

void readifs( char *fname, IFS *theifs );
void openifswindow ( int height, int width, char **argv, int argc );
point nextpoint ( point old, IFS *theifs );
void closeifswindow();

/* The Program */

int main(int argc,char **argv)
{

  char fname[128];

  int count, start;

  point pt;

  int height, width;

  char text[10];
  int k, i;
  int done;
  double maxx, maxy, minx, miny;


  /* Read in IFS codes from a file */

  if ( argc == 1 ) {
    printf ( "Enter filename: " );
    scanf ( "%s", fname );
  }
  else {
    strcpy ( fname, argv[1] );
  }

  readifs ( fname, &theifs );

  /* Set up window info */

  height = 500; width = 500;
  openifswindow ( height, width, argc, argv );

  /* Initialize ifs variables */

  start = 25;
  count = 0;
  pt.x = 0.5; pt.y = 0.5;

  /* Main Event Loop */

  done = 0;
  while ( done == 0 ) {

     while ( ( XEventsQueued ( mydisplay, QueuedAfterReading ) == 0 )
	    /*  && ( count < theifs.stop ) */ )
       {
	 /* Get next IFS Point */
	 pt = nextpoint ( pt, &theifs );

	 /* Draw it */
	 if ( count++ > start ) 
	   XDrawPoint ( mydisplay, mywindow, mygc,
		        irint( ( pt.x*theifs.xsize + theifs.x0)*width ),
		        irint( ( pt.y*theifs.ysize + theifs.y0)*height ) );

	 XFlush ( mydisplay );
       }

     XNextEvent ( mydisplay, &myevent );
     
     switch ( myevent.type ) {

     case Expose:
       if ( myevent.xexpose.count == 0 )
	 { };
       break;

     case MappingNotify:
       XRefreshKeyboardMapping ( &myevent );
       break;

     case ButtonPress:
       done = 1;
       break;

     case KeyPress:
       i = XLookupString ( &myevent, text, 10, &myevent, 0 );
       if ( i == 1 && text[0] == 'q' ) done = 1;
       else if ( i ==1 && text[0] == 's' ) {
	 printf ( "Enter filename for bitmap: " );
	 scanf ( "%s", fname );
	 XWriteBitmapFile ( mydisplay, fname, mywindow, width, height, -1, -1 );
	 printf ( "%s saved.\n", fname );
       }
       else if ( i == 1 && text[0] == 'p ) {
	 printf( "Current point is (%f, %f)\n", pt.x, pt.y );
	 }
       else
	 printf ( "Type q to quit, s to save.\n" );

       break;

     case ConfigureNotify:
       if ( ( height != myevent.xconfigure.height ) ||
	    ( width != myevent.xconfigure.width   ) ) {
	 height = myevent.xconfigure.height;
	 width = myevent.xconfigure.width;
	 count = 0;
	 XClearArea ( mydisplay, mywindow, 0, 0, height, width, 0 );
       }
       break;

     } /* switch ( myevent.type ) */
   
   } /* while ( done == 0 ) */

  /* Bye, bye */

  closeifswindow();

  exit ( 0 );
 
} /* main */



void readifs( char *fname, IFS *theifs )

/* Read in ifs code from file with name fname into theifs */

{

  FILE *ifsfile;
  int i;

  ifsfile = fopen ( fname, "r" );
  /* printf ( "%s opened ... \n", fname ); */

  fscanf ( ifsfile, "%d", &theifs->stop );
  fscanf ( ifsfile, "%lf%lf", &theifs->xsize, &theifs->ysize );
  fscanf ( ifsfile, "%lf%lf", &theifs->x0, &theifs->y0 );
  fscanf ( ifsfile, "%d", &theifs->wnum );

  for ( i = 0; i < theifs->wnum; i++ ) {
    fscanf ( ifsfile, "%lf %lf %lf %lf %lf %lf %lf",
	    &theifs->w[i][0],
	    &theifs->w[i][1], &theifs->w[i][2],
	    &theifs->w[i][3], &theifs->w[i][4],
	    &theifs->w[i][5], &theifs->w[i][6] );
  }

  /* printf ( "Done reading.\n" ); */
  fclose ( ifsfile );

}			 


void openifswindow ( int height, int width, char **argv, int argc )
{
  /* Set up display */

  mydisplay = XOpenDisplay("");
  myscreen = DefaultScreen ( mydisplay );
  mybackground = WhitePixel ( mydisplay, myscreen );
  myforeground = BlackPixel ( mydisplay, myscreen );
  
  myhint.x = 200;  myhint.y = 300;
  myhint.width = width;  myhint.height = height;
  myhint.flags = PPosition | PSize;

  /* Create Window */

  mywindow = XCreateSimpleWindow ( mydisplay,
      DefaultRootWindow ( mydisplay ),
      myhint.x, myhint.y, myhint.width, myhint.height,
      5, myforeground, mybackground );

  XSetStandardProperties ( mydisplay, mywindow, xifs, xifs,
			  None, argv, argc, &myhint );

  /* Create Graphic Context */

  mygc = XCreateGC ( mydisplay, mywindow, 0, 0 );
  XSetBackground ( mydisplay, mygc, mybackground );
  XSetForeground ( mydisplay, mygc, myforeground );

  /* Solicit press and exposure events */

  XSelectInput ( mydisplay, mywindow,
		ButtonPressMask | KeyPressMask | ExposureMask | StructureNotifyMask );

  /* Map window */

  XMapRaised ( mydisplay, mywindow );

  /* Set backing store */

  my_window_attributes.backing_store = Always;
  XChangeWindowAttributes ( mydisplay, mywindow, CWBackingStore,
			   &my_window_attributes );

  while ( XCheckWindowEvent( mydisplay, mywindow, ExposureMask, &myevent ) == 0 )
    ;

}



point nextpoint ( point old, IFS *theifs )

{
  point new;
  double prob;
  int k;

  /* Generate random number between 0 and 1 */

  prob = fmod ( (double) random() / 32768.0, 1.0 );

  /* Find transformation based upon probabilites and prob */

  k = 0;	 while ( prob > theifs->w[k][0] ) k++;

  /* Generate new point */

  new.x = theifs->w [ k][ 1 ] * old.x + theifs->w [ k][ 2 ] * old.y + theifs->w [ k][ 5 ];
  new.y = theifs->w [ k][ 3 ] * old.x + theifs->w [ k][ 4 ] * old.y + theifs->w [ k][ 6 ];


  return new;

}


void closeifswindow()
{

  XFreeGC ( mydisplay, mygc );
  XDestroyWindow ( mydisplay, mywindow );
  XCloseDisplay ( mydisplay );

}