home *** CD-ROM | disk | FTP | other *** search
- /*
-
-
-
- ***** ***** ***** *****
- * * * * * * * *
- * * * * * * *
- ** ***** * * * * * * ****** * *
- * * * ******* ** ** ****** * ******
- ** * * * * * * * * * * *
- * * * * * * * * * * * *
- * * * * * * * * * ***** * *
- ***** * * * * * * * * *
- * * * *
- * * * * *
- ***** * * ******
-
-
-
- by Ian Palmer
-
- at
-
- Imperial College of Science, Technology and Medicine
- University of London
-
-
-
-
- --------------------------------------------------------------------------------
- | Scamper is supplied "as is", without express or implied warranty. |
- | |
- | Permission to use, copy, modify and distribute this software, and any |
- | documentation, for any non-commercial purpose is hereby granted without fee, |
- | provided that all copyright messages, and permission notices, remain intact. |
- | |
- | Copyright 1991 by Ian Palmer of Imperial College of Science, Technology |
- | and Medicine, University of London. |
- --------------------------------------------------------------------------------
-
- _____
- /_ _/ Let Total Chaos reign forever ! I.J.Palmer,
- / / ___ ______________ Department of Computing,
- / / / __\ | _ Imperial College,
- /_/ / / | <> | /-\ |_ 180 Queen's Gate,
- \ \__ / _ London SW7 2BZ.
- \___/ \ |-| /-\ <> <
- ______________> ijp@doc.ic.ac.uk
- PANIC NOW
- and avoid 23. Add to Celt's pub meal and produce utter turmoil. (6,8)
- the rush. -----------------------------------------------------------
-
-
- */
-
- /*
- Program Segment : automata.c
-
- Task : Provide the main finctions of Scamper, including :
- - Main loop
- - X Event handling
- - Displaying domain
- - Scrolling and resizing the domain
- - Main menu (display and option selection)
- - Handling file options' selection
- - Cell allocation and user actions on domain
- */
-
- #include <stdlib.h>
- #include <stdio.h>
- #include <X11/Xlib.h>
- #include "windows.h"
- #include "domain.h"
- #include "calscan.h"
- #include "automata.h"
- #include "stats.h"
- #include "colour.h"
- #include "rules.h"
- #define offset 28
-
- struct box boxes[MaxBoxes] ;
- struct abox askbox[8] ;
- struct state states[max_states];
- CELL array[MAX_X][MAX_Y] ;
-
- int running , generation , display , update , start_x , update , updateX ;
- int updateC , fnamel , shape, stopat , displaychange , torus ;
- int max_x , max_y , new, old , mode , start_y , Asking , greyscale ;
- int scale , size_x , end_x , end_y , size_y, updatesmall ;
- int old_x , old_y , counter, old_op, dscale , tscale , cropX =0 , cropY =0 ;
- int step , Exit = 0 , updown = 0 , AskVal , AskOp, mk[max_neigh] ;
- int sccol , bycol , scnum , numdir , numloop , dirtype , loopnum , change ;
-
- float hscale , wscale ;
-
- char FileName[110] , message[100] ;
- char theauthor[] ="b y I. J. P a l m e r"; /* The author, to be placed at the top of the main menu */
-
- struct button {
- int value ;
- int state ;
- } buttons[3];
-
- /* ------------------------------------------------------------------------- */
-
- void change_domain(change_to) int change_to ;
- /* Toggles the logical handling of the domain between a torus and a flat plane.
-
- Status changes : torus
- */
- {
- torus = change_to ; /* Set the new value of torus */
- if (torus)
- link_cells(shape,0); /* If we now have a torus domain, link the cells */
- else {
- setup_array(0,0,max_x+1,max_y+1,1); /* Otherwise, enlarge the domain by 1 in each direction */
- link_cells(shape,0); /* and then link the cells */
- };
- }
-
- /* ------------------------------------------------------------------------- */
-
- void setup_array ( sx,sy,fx,fy,clear ) int sx,sy,fx,fy,clear ;
- /* Allocates space for unallocated cells in the domain. Called when expanding the size of the domain.
-
- Pre : sx < fx < MAX_X & sy < fy < MAX_Y
- Post: for all x,y : sx <= x < fx & sy <= y < fy then array[x][y] exists
-
- Status changes : none
- */
- {
-
- int x,y;
- if (!torus) {
- ++fx ;
- ++fy ;
- };
- XSetForeground( dpy,smallgc,colours[states[0].colour].mapno); /* Set the colour to black */
- for( x=sx ; x<fx ; x+=1 )
- for( y=sy ; y < fy ; y+=1) /* Go through all new cell positions */
- if (array[x][y] == NULL) { /* If the cell is unallocated */
- array[x][y] = (CELL) malloc(sizeof(struct cell)); /* then allocate it some space */
- if ((clear) && updatesmall)
- XDrawPoint( dpy, small, smallgc, x, y ); /* Make sure it starts off dead */
- array[x][y] -> state[1] = 0 ;
- array[x][y] -> state[0] = 0 ;
- };
- }
-
- /* ------------------------------------------------------------------------- */
-
- void resize()
- /* Sets global variables dictating start and end cells for displayed domain.
- If using hexagonal neighbourhood then a template hexagon is set up to speed up drawing.
-
- Status changes : none
- */
- {
- int z ;
- if (shape == 2) {
- end_y = start_y + (size_y = (DispY/scale/3.4)+2); /* If using hexagonal cells, work out the last cells to */
- end_x = start_x + (size_x = (DispX/scale/3)+2); /* which can be displayed when viewing the domain */
- z = 1.7320508*scale+1 ;
- hexagon[1].x = 2 * scale ; /* Create the right size of hexagon for drawing */
- hexagon[1].y = 0 ;
- hexagon[2].x = scale ;
- hexagon[2].y = -z ;
- hexagon[3].x = - scale ;
- hexagon[3].y = -z ;
- hexagon[4].x = -2*scale ;
- hexagon[4].y = 0 ;
- hexagon[5].x = -scale ;
- hexagon[5].y = z ;
- }
- else {
- end_y = start_y + (size_y = (DispY/scale/2)+2); /* If square cells, work out the last cells to */
- end_x = start_x + (size_x = (DispX/scale/2)+2); /* which can be displayed when viewing the domain */
- };
- if (size_x > max_x) { /* Check for overflow (wrap around) on the above numbers */
- size_x = max_x ;
- end_x = start_x - 1;
- if (end_x == -1)
- end_x = max_x -1;
- };
- if (end_x > max_x)
- end_x -= max_x ;
- if (size_y > max_y) {
- size_y = max_y ;
- end_y = start_y - 1;
- if (end_y == -1)
- end_y = max_y -1;
- };
- if (end_y > max_y)
- end_y -= max_y ;
- dscale = scale*2 ; /* Work out some useful `constants' for this size of cell */
- tscale = scale*3 ;
- hscale = scale*1.73205808 ;
- wscale = 3.4641016*scale ;
- }
-
- /* ------------------------------------------------------------------------- */
-
- void link_cells ( n , all) int n, all;
- /* Links cells to their neighbours for a given neighbourhood :
- 1 - 4 square
- 2 - hexagonal
- 3 - 8 square
-
- Status changes : shape
- */
- {
- shape = n ;
- cropX = cropY = 0;
- resize();
- switch (n) {
- case 1: init4(all); break;
- case 2: init6(all); break;
- case 3: init8(all); break;
- default: init8(all);
- };
- }
-
- /* ------------------------------------------------------------------------- */
-
- void init8 (all) int all ;
- /* Links up neighbours for an 8 square arrangement */
- {
-
- int x,y,mx,my;
- mx = max_x + 1 - torus ;
- my = max_y + 1 - torus ;
-
- for( x=0 ; x<mx ; x+=1 ) {
- for( y=0 ; y< my ; y+=1 ) {
- array[x][y]->dir[0] = get(x,y-1); /* North */
- array[x][y]->dir[4] = get(x+1,y-1); /* North East */
- array[x][y]->dir[1] = get(x+1,y); /* East */
- array[x][y]->dir[5] = get(x+1,y+1); /* South East */
- array[x][y]->dir[2] = get(x,y+1); /* South */
- array[x][y]->dir[6] = get(x-1,y+1); /* South West */
- array[x][y]->dir[3] = get(x-1,y); /* West */
- array[x][y]->dir[7] = get(x-1,y-1); /* North West */
- if ((y==0) && (x < mx-2) && (x>0) && !all)
- y = my-3 ;
- };
- };
- }
-
- /* ------------------------------------------------------------------------- */
-
- void init4 (all) int all ;
- /* Links up neighbours for a 4 square arrangement */
- {
-
- int x,y,mx,my ;
- mx = max_x + 1 - torus ;
- my = max_y + 1 - torus ;
-
- for( x=0 ; x<mx ; x+=1 ) {
- for( y=0 ; y< my ; y+=1 ) {
- array[x][y] -> dir[0] = get(x,y-1); /* North */
- array[x][y] -> dir[1] = get(x+1,y); /* East */
- array[x][y] -> dir[2] = get(x,y+1); /* South */
- array[x][y] -> dir[3] = get(x-1,y); /* West */
- if ((y==0) && (x < mx-2) && (x>0) && !all)
- y = my-3 ;
- };
- };
- }
-
- /* ------------------------------------------------------------------------- */
-
- void init6 (all) int all ;
- /* Links up neighbours for a hexagonal arrangement */
- {
-
- int x,y,mx,my ;
- mx = max_x + 1 - torus ;
- my = max_y + 1 - torus ;
-
- for( x=0 ; x<mx ; x+=1 ) {
- for( y=0 ; y< my ; y+=1 ) {
- array[x][y] -> dir[0] = get(x,y-1); /* North */
- array[x][y] -> dir[1] = get(x+1,y-even(x)); /* North East-ish */
- array[x][y] -> dir[2] = get(x+1,y+odd(x)); /* South East-ish */
- array[x][y] -> dir[3] = get(x,y+1); /* South */
- array[x][y] -> dir[4] = get(x-1,y+odd(x)); /* South West-ish */
- array[x][y] -> dir[5] = get(x-1,y-even(x)); /* North West-ist */
- if ((y==0) && (x < mx-2) && (x > 0) && !all)
- y = my-3 ;
- };
- };
- }
-
- /* ------------------------------------------------------------------------- */
-
- int odd (x)
- /*
-
- Pre : x >= 0
- Post: 1 if x is odd
- 0 otherwise
- */
- int x ;
-
- {
- return ((x % 2) == 1);
- }
-
- /* ------------------------------------------------------------------------- */
-
- int even (x)
- /*
-
- Pre : x >= 0
- Post: 1 if x is even
- 0 otherwise
- */
- int x;
-
- {
- return ((x % 2) == 0);
- }
-
- /* ------------------------------------------------------------------------- */
-
- CELL get( x,y )
- /* Given an x,y coordinate, returns a pointer to that cells structure, checking for overflow and underflow. */
-
- int x,y ;
-
- {
- int mx,my ;
- mx = max_x + 1 - torus ;
- my = max_y + 1 - torus ;
-
- if (x == -1) /* X underflow */
- x = mx-1 ;
-
- if (x == mx) /* X overflow */
- x = 0 ;
-
- if (y == -1) /* Y underflow */
- y = my-1 ;
-
- if (y == my) /* Y overflow */
- y = 0 ;
-
- return array[x][y];
- }
-
- /* ------------------------------------------------------------------------- */
-
- int test_inside ( x,y )
- /* Tests to see if a given X,Y coordinate is inside the displayable domain, returns true if it is, false otherwise */
-
- int x,y ;
-
- {
-
- int sx,sy,ex,ey ;
-
- sx = start_x ;
- sy = start_y ;
- ex = end_x ;
- ey = end_y ;
-
- if (ex < sx) {
- sx = sx - ex ;
- if ( x > ex )
- x = x - ex ;
- else
- x = max_x - (ex - x) ;
- ex = max_x ;
- };
-
- if (ey < sy) {
- sy = sy - ey ;
- if ( y > ey )
- y = y - ey ;
- else
- y = max_y - (ey - y) ;
- ey = max_y ;
- };
-
- if ((x >= sx) && (x <= ex) && (y >= sy) && (y <= ey))
- return 1 ;
- else
- return 0 ;
-
- }
-
- /* ------------------------------------------------------------------------- */
-
- void display_cells ()
- /* Displays the displayable cells of the domain in the `display' window (only if the Status variable `display' = 1).
-
- Status changes : update updateX updateC
- */
- {
- int cx,cy,x,y,d ;
- update = 1;
- if (display == 1) { /* Check we are supposed to draw the cells (check status) */
- SetWindow(Display_Window); /* Select the correct window */
- x = updateX ; /* Start off where left off */
- for( cx = updateC ; cx < size_x ; ++cx) {
- y = start_y ;
- for( cy = 0 ; cy < size_y ; ++cy ) {
- draw_cell(x,y);
- y = (y+1)%max_y ;
- };
- x = (x+1)%max_x ;
- if (EventPending()) { /* Check for any X events */
- updateX = x; /* If there are any, make a note of where you are */
- updateC = cx+1; /* and stop it */
- return ;
- };
- };
- FlushQueue();
- };
- updateX = start_x; /* If you managed to finish the display, make a note of it */
- updateC = 0;
- update = 0;
- }
-
- /* ------------------------------------------------------------------------- */
-
- void draw_cell(x,y)
- /* Given an X,Y coordinate, displays the cell for that coordinate.
-
- Pre : display window selected
-
- Status changes : cropX cropY
- */
- int x,y;
- {
- int dx,dy ;
- dx = x ;
- dy = y ;
-
- if (array[x][y]) {
- SetColour(states[array[x][y] -> state[new]].colour); /* Set the correct colour */
- if (x < start_x) /* Check for wrap around */
- dx += max_x ;
- if (y < start_y)
- dy += max_y ;
- if (shape != 2) { /* If 4 or 8 neighbours, draw a box */
- dx = (dx-start_x)*dscale ;
- dy = (dy-start_y)*dscale ;
- XFillRectangle( dpy, win, gc, dx-scale , dy-scale,dscale,dscale);
- if ((dx+dscale)>cropX)
- cropX = dx+dscale ;
- if ((dy+scale)>cropY)
- cropY = dy+scale ;
- }
- else {
- dy = (dy-start_y)*wscale+(1+odd(dx))*hscale ; /* Otherwise a hexagon */
- dx = (dx-start_x)*tscale-scale ;
- hexagon[0].x = dx ;
- hexagon[0].y = dy+1 ;
- XFillPolygon(dpy,win,gc,hexagon,6,Convex,CoordModePrevious);
- if (dy>cropY)
- cropY = dy+1 ;
- if ((dx+dscale)>cropX)
- cropX = dx+tscale ;
- };
- };
- }
-
- /* ------------------------------------------------------------------------- */
-
- void AutoResize()
- /* Tries to resize the domain to just fit inside the `display' window.
-
- Status changes : scale cropX cropY
- */
- {
- cropX = cropY = 0;
- if (shape == 2) {
- scale = DispY/(max_x*3.4) ;
- if (scale > (DispX/(max_x*3)))
- scale = DispX/(max_x*3) ;
- }
- else {
- scale = DispY/(max_x*2) ;
- if (scale > (DispX/(max_x*2)))
- scale = DispX/(max_x*2) ;
- };
- if (scale == 0)
- scale = 1 ;
- resize();
- }
-
- /* ------------------------------------------------------------------------- */
-
- void enlarge()
- /* Enlarges the size of displayed cells
-
- Status changes : scale cropX cropY
- */
- {
- if (display >1)
- return ;
- cropX = cropY = 0;
- scale += 1;
- resize();
- clear_display();
- updateX = start_x;
- updateC = 0;
- display_cells();
- }
-
- /* ------------------------------------------------------------------------- */
-
- void decrease()
- /* Decreases the size of displayed cells
-
- Status changes : scale cropX cropY
- */
- {
- if (display >1)
- return ;
- cropX = cropY = 0;
- if (scale > 1) {
- scale -= 1;
- resize();
- clear_display();
- updateX = start_x;
- updateC = 0;
- display_cells();
- }
- else
- Message("Can't shrink any more");
- }
-
- /* ------------------------------------------------------------------------- */
-
- void move_left()
- /* Scrolls the display window to the left
-
- Status changes : start_x
- */
- {
- int y,cy,x2 ;
- if (display >1) {
- if (display == 4)
- ColourLeft();
- return ;
- };
- if (start_x > 0)
- start_x -= 1 ;
- else
- start_x = max_x-1 ;
- resize();
- SetWindow(Display_Window);
- if (shape != 2)
- XCopyArea(dpy,win,win,gc,0,0,cropX-dscale,cropY,dscale,0);
- else
- XCopyArea(dpy,win,win,gc,0,0,cropX-tscale+1,cropY,tscale,0);
- y = start_y ;
- x2 = (start_x+1)%max_x ;
- for( cy = 0 ; cy < size_y ; ++cy ) {
- draw_cell(start_x,y);
- draw_cell(x2,y);
- y = (y+1)%max_y ;
- };
- }
-
- /* ------------------------------------------------------------------------- */
-
- void move_right()
- /* Scrolls the display window to the right
-
- Status changes : start_x
- */
- {
- int y,x,cy,cx ;
- if (display >1) {
- if (display == 4)
- ColourRight();
- return ;
- };
- start_x += 1;
- if (start_x == max_x)
- start_x = 0 ;
- resize();
- SetWindow(Display_Window);
- if (shape != 2)
- XCopyArea(dpy,win,win,gc,dscale,0,cropX,cropY,0,0);
- else
- XCopyArea(dpy,win,win,gc,tscale,0,cropX+1,cropY,0,0);
- x = end_x;
- if (x==-1)
- x = max_x-1 ;
- for( cx=0 ; cx<4 ; ++cx) {
- y = start_y ;
- for( cy = 0 ; cy < size_y ; ++cy ) {
- draw_cell(x,y);
- y = (y+1)%max_y ;
- };
- if ((x = x-1)==-1)
- x = max_x -1 ;
- };
- }
-
- /* ------------------------------------------------------------------------- */
-
- void move_up()
- /* Scrolls the display window up
-
- Status changes : start_y
- */
- {
- int x,y2,cx ;
- if (display >1) {
- if (display == 4)
- ColourUp();
- return ;
- };
- if (start_y > 0)
- start_y -= 1 ;
- else
- start_y = max_y -1 ;
- resize();
- SetWindow(Display_Window);
- if (shape !=2)
- XCopyArea(dpy,win,win,gc,0,0,cropX,cropY-dscale,0,dscale);
- else
- XCopyArea(dpy,win,win,gc,0,0,cropX,cropY- (int) wscale,0,(int) wscale);
- y2 = (start_y+1)%max_y ;
- x = start_x ;
- for( cx=0 ; cx < size_x ; ++cx ) {
- draw_cell(x,start_y);
- draw_cell(x,y2);
- x = (x+1)%max_x ;
- };
- }
-
- /* ------------------------------------------------------------------------- */
-
- void move_down()
- /* Scrolls the display window down
-
- Status changes : start_y
- */
- {
- int y,x,cy,cx ;
- if (display >1) {
- if (display == 4)
- ColourDown();
- return ;
- };
- start_y += 1;
- if (start_y == max_y)
- start_y = 0;
- resize();
- SetWindow(Display_Window);
- if (shape !=2)
- XCopyArea(dpy,win,win,gc,0,dscale,cropX,cropY,0,0);
- else
- XCopyArea(dpy,win,win,gc,0,(int) wscale,cropX,cropY+1,0,0);
- y = end_y ;
- for( cy=0 ; cy<4 ; ++cy ) {
- x = start_x ;
- for( cx=0 ; cx < size_x ; ++cx ) {
- draw_cell(x,y);
- x = (x+1)%max_x ;
- };
- if ((y = y-1) == -1)
- y = max_y ;
- };
- }
-
- /* ------------------------------------------------------------------------- */
-
- void clear_display()
- /* Clears the `display' window
- */
- {
- SetWindow(Display_Window);
- ClearScreen();
- }
-
- /* ------------------------------------------------------------------------- */
-
- void InitMulti(n) int n ;
- /* Sets the labels of the boxes (3 to 8) for the bottom row, depending on display type
-
- Pre : n = 0 or 1
- Post: n = 0 - normal setup
- n = 1 - built in Cal program setup
- */
- {
- if (n) {
- sprintf(boxes[3].text,"Grey");
- sprintf(boxes[4].text,"Sharp");
- sprintf(boxes[5].text,"Soft");
- sprintf(boxes[6].text,"Apply");
- sprintf(boxes[7].text,"Update");
- sprintf(boxes[8].text,"Undo");
- } else {
- sprintf(boxes[3].text,"+");
- sprintf(boxes[4].text,"-");
- sprintf(boxes[5].text,"Left");
- sprintf(boxes[6].text,"Right");
- sprintf(boxes[7].text,"Up");
- sprintf(boxes[8].text,"Down");
- };
- }
-
- /* ------------------------------------------------------------------------- */
-
- void InitBoxes()
- /* Initializes all main menu `boxes', positions and labels
- */
- {
- int x,y ;
- for (x=0;x<max_x;++x)
- for (y=0;y<max_y;++y)
- array[x][y] = NULL ;
- sprintf(message,"Scamper message window");
- for (x=0 ; x<max_states ; ++x)
- states[x].rules = NULL ;
- for ( x = 0 ; x<MaxBoxes ; ++x )
- boxes[x].draw = 0 ;
- for ( x=0 ; x<10 ; ++x ) {
- boxes[x].draw = 1 ;
- boxes[x].sx = 10+(x*70) ;
- boxes[x].sy = DispY+60 ;
- boxes[x].fx = 60+(x*70) ;
- boxes[x].fy = DispY+90 ;
- };
- for ( x=10 ; x<16 ; ++x ) {
- boxes[x].draw = 1 ;
- boxes[x].sx = 80 ;
- boxes[x].fx = 180 ;
- boxes[x].sy = 80+50*(x-10+(x>12)) ;
- boxes[x].fy = 110+50*(x-10+(x>12)) ;
- };
- for ( x=16 ; x<22 ; ++x ) {
- boxes[x].draw = 1 ;
- boxes[x].sx = 200 ;
- boxes[x].fx = 300 ;
- boxes[x].sy = 80+50*(x-16+(x>18)) ;
- boxes[x].fy = 110+50*(x-16+(x>18)) ;
- };
- for ( x=22 ; x<28 ; ++x ) {
- boxes[x].draw = 1 ;
- boxes[x].sx = 320 ;
- boxes[x].fx = 420 ;
- boxes[x].sy = 80+50*(x-22+(x>24)) ;
- boxes[x].fy = 110+50*(x-22+(x>24)) ;
- };
- for ( x=28 ; x<34 ; ++x ) {
- boxes[x].draw = 1 ;
- boxes[x].sx = 440 ;
- boxes[x].fx = DispX+20 ;
- boxes[x].sy = 80+50*(x-28+(x>30)) ;
- boxes[x].fy = 110+50*(x-28+(x>30)) ;
- if (x < 31) {
- buttons[x-28].value = x-28 ;
- buttons[x-28].state = 1 ;
- };
- };
-
- for( x=0 ; x<8 ; ++x) {
- askbox[x].draw = 0 ;
- askbox[x].set = 0 ;
- askbox[x].reset = 0 ;
- };
-
- for( x= 0 ; x<3 ; ++x ) {
- askbox[x].draw = 1 ;
- askbox[x].sx = 158 ;
- askbox[x].fx = 226 ;
- askbox[x].sy = 35 + x*50 ;
- askbox[x].fy = 60 + x*50 ;
- };
-
- for(x=3 ; x<8 ; ++x) {
- askbox[x].draw = 1 ;
- askbox[x].sx = 20 ;
- askbox[x].fx = 35 ;
- askbox[x].sy = 10 + 40*(x-3) ;
- askbox[x].fy = 25 + 40*(x-3) ;
- };
-
- sprintf(askbox[1].text,"Cancel");
- sprintf(askbox[2].text,"Clear");
-
- sprintf(boxes[0].text,"Run");
- sprintf(boxes[1].text,"Stop");
- sprintf(boxes[2].text,"Step");
- InitMulti(0);
- sprintf(boxes[9].text,"Swap");
- sprintf(boxes[10].text,"4 neighbours");
- sprintf(boxes[11].text,"6 neighbours");
- sprintf(boxes[12].text,"8 neighbours");
- sprintf(boxes[13].text,"Home");
- sprintf(boxes[14].text,"Set Home");
- sprintf(boxes[15].text,"QUIT");
- sprintf(boxes[16].text,"Load Domain");
- sprintf(boxes[17].text,"Insert Domain");
- sprintf(boxes[18].text,"Save Domain");
- sprintf(boxes[19].text,"Auto Resize");
- sprintf(boxes[20].text,"View Small");
- sprintf(boxes[21].text,"View Stats");
- sprintf(boxes[22].text,"Load Bitmap");
- sprintf(boxes[23].text,"Save Bitmap");
- sprintf(boxes[24].text,"Clear Domain");
- sprintf(boxes[25].text,"Load Rules");
- sprintf(boxes[26].text,"Clear Rules");
- sprintf(boxes[27].text,"Reset Time");
- sprintf(boxes[28].text,"Left Button");
- sprintf(boxes[29].text,"Middle Button");
- sprintf(boxes[30].text,"Right Button");
- sprintf(boxes[31].text,"Change Colours");
- sprintf(boxes[32].text,"");
- sprintf(boxes[33].text,"");
- }
-
- /* ------------------------------------------------------------------------- */
-
- void DrawBox(x,invert) int x,invert ;
- /* Draws a givan box. If invert = 0 - normal, otherwise inverted colours.
- */
- {
- char string[25];
-
- SetWindow(Main_Window); /* Select main menu window */
- SelectFont(Small_Font); /* and small font */
- SetColour(cols[fore]);
- if ((x>27) && (x<31))
- SetColour(states[buttons[x-28].value].colour);
- FillRectangle(boxes[x].sx,boxes[x].sy,boxes[x].fx,boxes[x].fy);
- FillRectangle(boxes[x].sx-1,boxes[x].sy+1,boxes[x].fx+1,boxes[x].fy-1); /* Bounding box */
- FillRectangle(boxes[x].sx+1,boxes[x].sy-1,boxes[x].fx-1,boxes[x].fy+1);
- FillRectangle(boxes[x].sx-2,boxes[x].sy+2,boxes[x].fx+2,boxes[x].fy-2);
- FillRectangle(boxes[x].sx+2,boxes[x].sy-2,boxes[x].fx-2,boxes[x].fy+2);
- SetColour(cols[back]);
- if (! invert) {
- FillRectangle(boxes[x].sx+3,boxes[x].sy+3,boxes[x].fx-3,boxes[x].fy-3); /* Clear the inside (if not invert) */
- FillRectangle(boxes[x].sx+2,boxes[x].sy+4,boxes[x].fx-2,boxes[x].fy-4);
- FillRectangle(boxes[x].sx+4,boxes[x].sy+2,boxes[x].fx-4,boxes[x].fy-2);
- FillRectangle(boxes[x].sx+1,boxes[x].sy+5,boxes[x].fx-1,boxes[x].fy-5);
- FillRectangle(boxes[x].sx+5,boxes[x].sy+1,boxes[x].fx-5,boxes[x].fy-1);
- SetColour(cols[fore]);
- };
- if ((x<28) || (x==31))
- Centre(boxes[x].text,boxes[x].sx,boxes[x].sy,boxes[x].fx,boxes[x].fy); /* Place text */
- else {
- if (x==32)
- sprintf(string,"X = %d",max_x);
- if (x==33)
- sprintf(string,"Y = %d",max_y);
- if ((x>27) && (x<31))
- if (buttons[x-28].state)
- sprintf(string,"%d - %s",buttons[x-28].value,ColourName(states[buttons[x-28].value].colour));
- else
- sprintf(string,boxes[x].text);
- Centre(string,boxes[x].sx,boxes[x].sy,boxes[x].fx,boxes[x].fy);
- };
- }
-
- /* ------------------------------------------------------------------------- */
-
- void MainScreen()
- /* Draws the main menu
- */
- {
- int x,y,sx,sy ;
-
- change = 1 ;
- SelectFont(Small_Font);
- for( x=0 ; x<MaxBoxes ; ++x ) {
- if (boxes[x].draw)
- DrawBox(x,0);
- };
- }
-
- /* ------------------------------------------------------------------------- */
-
- void DisplayFileName(clear) int clear ;
- /* Displays the current file name in the file name window */
- {
- if (display == 0) {
- SetWindow(File_Window);
- SetBackColour(cols[filebg]);
- if (clear) {
- SetColour(cols[filefg]);
- ClearScreen();
- Centre("File name :",0,0,256,40);
- }
- else {
- SetColour(cols[filebg]) ;
- FillRectangle(0,40,256,80) ;
- SetColour(cols[filefg]);
- };
- FileName[fnamel] = '_' ;
- FileName[fnamel+1] = 0 ;
- Centre(FileName,0,40,256,80);
- };
- }
-
- /* ------------------------------------------------------------------------- */
-
- void Centre( text , sx,sy,fx,fy ) char *text ; int sx,sy,fx,fy ;
- /* Given some text and a bounding box, places the text in the centre of the bounding box. If the text is too large from the
- bounding box, then it is right justified to the right hand side of the box.
- */
- {
- int x,y ;
- TextSize(text,&x,&y);
- if (sx == fx)
- x = fx + 10 ;
- else if (x>(fx-sx))
- x = fx - x ;
- else
- x = sx + ((fx-sx-x)/2) ;
- y = (fy+sy+y-4)/2 ;
- PrintString(x,y,text) ;
- }
-
- /* ------------------------------------------------------------------------- */
-
- void service()
- /* Given that there is an X11 event pending, this procedure reads the event and takes necessary action.
- */
- {
- int x,y,b,w ;
- EventType ev ;
- char c ;
-
- GetNextEvent(&ev,&c,&x,&y,&b,&w);
-
- if ( ev == EventExpose) { /* Expose event, a window needs redisplaying */
- if (w==0)
- MainScreen();
- if (w==1) {
- updateX = start_x;
- updateC = 0;
- display_cells();
- if (display == 4)
- ColourEvent(ev,c,x,y,b);
- };
- if (w==2)
- Message(message);
- if (w == 3)
- DisplayFileName(1);
- if ((w == 4) && (Asking == 1))
- AskBoxes();
- if ((w == 4) && (Asking == 2))
- DrawGreyScale();
- if ((w == 5) && error)
- Error(errormess[0],errormess[1]);
- if (w == 6)
- change = 1 ;
- };
-
- if (ev == EventMouseDown) { /* A mouse button has been pressed down */
- updown = b+1 ;
- old_x = x ;
- old_y = y ;
- counter = 0;
- if (w==2)
- Message("");
- };
-
- if (ev == EventMouseUp) { /* A mouse button has been released */
- updown = 0 ;
- old_op = 0 ;
- if (Asking == 2)
- GreyScaleMouseUp();
- };
-
- if (ev == EventKeypress) { /* A key has been pressed */
- if ((c > 31) && (c != 127) && (fnamel < 100))
- FileName[fnamel++] = c ;
- else if (((c == 127) || (c == 8)) && (fnamel > 0))
- --fnamel ;
- else if (c == 13)
- CallAsk();
- else if (c == 21)
- fnamel = 0;
- else if (c == 18)
- Total_Refresh();
- DisplayFileName(0);
- };
-
- if (updown && (w==1))
- cellop(x,y,updown-1);
- if (updown && (w==0))
- operation(old_x,old_y,updown-1);
- if (updown && (w==4) && (Asking == 1))
- ButtonAsk(x,y);
- if (updown && (w==4) && (Asking == 2))
- GreyScaleMove(x,y);
- if (updown && (w==5) && error)
- ErrorWindow( error = 0 );
- }
-
- /* ------------------------------------------------------------------------- */
-
- void Total_Refresh()
- /* Refresh all windows that are visible */
- {
- SetWindow(Main_Window);
- ClearScreen();
- if (display) {
- SetWindow(Display_Window);
- ClearScreen();
- };
- if (Asking) {
- SetWindow(Multi_Window);
- ClearScreen();
- };
- if (error) {
- SetWindow(Error_Window);
- ClearScreen();
- };
- SetWindow(Title_Window);
- ClearScreen();
- if (! display) {
- SetWindow(Message_Window);
- ClearScreen();
- SetWindow(File_Window);
- ClearScreen();
- };
- MainScreen();
- Message(message);
- DisplayFileName(1);
- updateX = start_x;
- updateC = 0;
- display_cells();
- if (display == 4)
- ColourEvent(EventExpose,' ',0,0,0);
- if (display == 3)
- display_stats(0,1);
- if (display == 2)
- SmallView();
- if (Asking == 1)
- AskBoxes();
- if (Asking == 2)
- DrawGreyScale();
- if (error)
- Error(errormess[0],errormess[1]);
- change = 1 ;
- }
-
- /* ------------------------------------------------------------------------- */
-
- void StartRun(n) int n ;
- /* Force a higlight of option box n
- */
- {
- DrawBox(n,1);
- FlushQueue();
- }
-
- /* ------------------------------------------------------------------------- */
-
- void operation(x,y,b)
- /* Given an x,y coordinate of the mouse pointer, and the button number pressed this procedure works out which menu option
- was selected, and acts accordingly.
- */
- int x,y,b ;
- {
- int n,op,cx,cy = -1 ;
-
- if (error) return ;
-
- op = -1;
- for( n=0 ; n<MaxBoxes ; ++n )
- if ((x >= boxes[n].sx) && (x <= boxes[n].fx) && (y >= boxes[n].sy) && (y <= boxes[n].fy))
- op = n ;
-
- SetWindow(Main_Window);
- DrawBox(op,1);
- FlushQueue();
-
- if (op==15) { /* Quit */
- Exit = 1 ;
- Message("Goodbye");
- };
-
- if ((op >9) && (op<13)) { /* 4, 6, or 8 neighbours */
- link_cells(op-9,1) ;
- };
-
- if (op==13) { /* Home */
- start_x = 0;
- start_y = 0;
- resize();
- };
-
- if (op==14) /* Set Home */
- SetHome();
-
- if (op==19) /* Auto Resize */
- AutoResize();
-
- if (op==21) { /* Stats */
- InitMulti(1);
- for(cy = 3; cy < 9 ; ++cy)
- DrawBox(cy,0);
- SetWindow(Display_Window);
- display_stats(0,1);
- };
-
- if (op == 26) /* Clear Rules */
- ClearRules();
-
- if (op == 27) { /* Reset Time */
- generation = 0;
- Shift = 0 ;
- reset_stats();
- Message("Time Reset");
- };
-
- if (AskVal) { /* Don't allow any of the below when file operation initiated */
- if (op != AskOp)
- DrawBox(op,0);
- return ;
- };
-
- if (op == 0) { /* Run */
- stopnum = 0 ;
- running = 1 ;
- };
-
- if (op == 1) /* Stop */
- running = 0 ;
-
- if (op == 2) /* Step */
- step = 1 ;
-
- if ((display != 2) && (display != 3)) {
- if (op == 3) /* Enlarge `+' */
- enlarge();
- if (op == 4) /* Decrease `-' */
- decrease();
- if (op == 5) /* Scroll Left */
- move_left();
- if (op == 6) /* Scroll Right */
- move_right();
- if (op == 7) /* Scroll Up */
- move_up();
- if (op == 8) /* Scroll Down */
- move_down();
- }
- else if ((op > 2) && (op < 9)) /* Built in Cal program */
- AlternateRun(op-2) ;
-
- if (op == 9) { /* Swap */
- DrawBox(28,0);
- DrawBox(29,0);
- DrawBox(30,0);
- if (Asking == 2) {
- AskOff();
- Asking = 0 ;
- };
- if ((display == 2) || (display == 3)) {
- InitMulti(0);
- for(cy = 3; cy < 9 ; ++cy)
- DrawBox(cy,0);
- };
- display = 1 - display ;
- if (display < 0)
- display = 0 ;
- if (display == 1) {
- DisplayOn();
- update = 1;
- updateX = start_x;
- updateC = 0;
- }
- else {
- DisplayOff();
- };
- };
-
- if (op==16) /* Load Domain */
- Ask(4);
-
- if (op==17) /* Insert Domain */
- Ask(6);
-
- if (op==18) /* Save Domain */
- Ask(5);
-
- if (op==20) { /* View Small */
- InitMulti(1);
- for(cy = 3; cy < 9 ; ++cy)
- DrawBox(cy,0);
- SmallView();
- };
-
- if (op==22) { /* Load Bitmap */
- Ask(2);
- };
-
- if (op==23) /* Save Bitmap */
- Ask(3);
-
- if (op==24) { /* Clear Domain */
- XSetForeground( dpy,smallgc,colours[states[0].colour].mapno);
- for( cy=0 ; cy<max_y ; ++cy )
- for( cx=0 ; cx<max_x ; ++cx) {
- array[cx][cy]->state[new] = array[cx][cy]->state[old] = 0 ;
- if (updatesmall)
- XDrawPoint( dpy, small, smallgc, cx, cy );
- };
- };
-
- if (op == 25) /* Load Rules */
- Ask(1);
-
- if (((op<28) && ((op<5) || (op>8))) || (display == 2) || (display == 3))
- updown=0 ;
- else {
- counter = 0 ; /* Decide if repeat allowed if button held down long enough */
- old_op = op ;
- };
-
- if ((op>27) && (op<31)) { /* Mouse Buttons' Options */
- if (b==1) {
- --buttons[op-28].value ;
- if (buttons[op-28].value == -1)
- buttons[op-28].value = max_states-1 ;
- };
- if (b==3) {
- ++buttons[op-28].value ;
- if (buttons[op-28].value == max_states)
- buttons[op-28].value = 0 ;
- };
- if (b==2)
- buttons[op-28].state = 1 - buttons[op-28].state ;
- };
-
- if (op == 31) { /* Change Colours */
- ColourOps();
- };
-
- if (op==32) { /* X size of domain */
- if ((b==1) && (max_x >5))
- --max_x ;
- if ((b==3) && (max_x < MAX_X)) {
- ++max_x ;
- setup_array(max_x-2,0,max_x,max_y,1);
- };
- link_cells(shape,0);
- };
-
- if (op==33) { /* Y size of domain */
- if ((b==1) && (max_y >5))
- --max_y ;
- if ((b==3) && (max_y < MAX_Y)) {
- ++max_y ;
- setup_array(0,max_y-2,max_x,max_y,1);
- };
- link_cells(shape,0);
- };
-
- if ((op != 0) && (op != 2) && (AskVal == 0))
- DrawBox(op,0); /* Un highlight box, if necessary */
- if (AskVal) /* Set file operation selected (if any) */
- AskOp = op ;
- if (op == 1) /* If `Stop' unhighlight `Run' */
- DrawBox(0,0);
- FlushQueue(); /* Make sure X is up to date */
-
- }
-
- /* ------------------------------------------------------------------------- */
-
- void cellop(px,py,b) int px,py,b ;
- /* Given the x,y coordinate of the mouse pointer, and the button pressed, works out which cell to change the state of, and
- sets the state accordind to which button was pressed.
- */
- {
-
- int cx,cy,x,y,fx,fy,dx,dy ;
- unsigned long td,md = 100000000 ;
-
- if (display == 3)
- StatButton(px,py);
-
- if ((display != 1) || (px > cropX) || (py > cropY)) return ;
- SetWindow(Display_Window);
- if (shape == 2)
- x = start_x + (px/tscale) -1 ; /* Calculate the coordinates of the cell clicked on */
- else
- x = start_x + (px/dscale) -1 ;
- if (x < start_x)
- x = start_x ;
- if (x >= max_x)
- x -= max_x ;
- if (x >= max_x) {
- Message("Outside cell area");
- return ;
- };
- for( cx = 0 ; cx < 4 ; ++cx ) {
- if (shape == 2)
- y = start_y + (py/wscale) -1 ;
- else
- y = start_y + (py/dscale) -1 ;
- if (y < start_y)
- y = start_y ;
- if (y >= max_y)
- y -= max_y ;
- if (y >= max_y) {
- Message("Outside cell area");
- return ;
- };
- for( cy = 0 ; cy < 4 ; ++cy ) {
- dx = x ;
- dy = y ;
- if (x < start_x)
- dx += max_x ;
- if (y < start_y)
- dy += max_y ;
- if (shape != 2) {
- dx = (dx-start_x)*dscale ;
- dy = (dy-start_y)*dscale ;
- }
- else {
- dy = (dy-start_y)*wscale+(odd(dx))*hscale ;
- dx = (dx-start_x)*tscale ;
- };
- td = (dx-px)*(dx-px) + (dy-py)*(dy-py) ;
- if (td < md) {
- md = td ;
- fx = x ;
- fy = y ;
- };
- y = (y+1)%max_y ;
- };
- x = (x+1)%max_x ;
- };
- (array[fx][fy]->state[old]) = buttons[b-1].value ; /* Set it's state */
- (array[fx][fy]->state[new]) = buttons[b-1].value ;
- draw_cell(fx,fy);
- if (updatesmall) {
- XSetForeground( dpy,smallgc,colours[states[array[fx][fy] -> state[new]].colour].mapno);
- XDrawPoint( dpy, small, smallgc, fx, fy );
- }; /* Update Small View Image */
- }
-
- /* ------------------------------------------------------------------------- */
-
- void Message( mess ) char* mess ;
- /* Place message `mess' in the message window */
- {
- SetWindow(Message_Window);
- SetColour(cols[verbfg]);
- ClearScreen();
- Centre(mess,0,0,256,80);
- sprintf(message,mess);
- FlushQueue();
- }
-
- /* ------------------------------------------------------------------------- */
-
- void SetHome()
- /* Set the `Home' position to the current start_x start_y position */
- {
- int x,y,X,Y ;
-
- x = start_x ;
- for( X=0 ; X<max_x ; ++X) {
- y = start_y ;
- for(Y=0 ; Y<max_y ; ++Y) {
- array[X][Y] -> state[old] = array[x][y] -> state[new] ;
- y = (y+1)%max_y ;
- };
- x = (x+1)%max_x ;
- };
- new = old ;
- old = 1-old ;
- start_x = 0 ;
- start_y = 0 ;
- resize();
- }
-
- /* ------------------------------------------------------------------------- */
-
- void Ask(n) int n ;
- /* Set up the boxes for file operations.
- 1 -> Read File (Cal program)
- 2 -> Load Bitmap
- 3 -> Save Bitmap
- 4 -> Load domain
- 5 -> Save domain
- 6 -> Insert domain
- */
- {
- int x ;
-
- for(x = 3 ; x<8 ; ++x ) {
- askbox[x].draw = 0 ;
- askbox[x].set = 0 ;
- askbox[x].reset = 0 ;
- };
-
- switch(n) {
- case 1 : sprintf(askbox[0].text,"Read");
- sprintf(askbox[3].text,"Display On"); askbox[3].draw = 1 ;
- sprintf(askbox[4].text,"Display Off"); askbox[4].draw = 1 ;
- askbox[3].set = 1 ;
- askbox[3].reset = 4 ;
- askbox[4].reset = 3 ;
- break ;
- case 2 : sprintf(askbox[0].text,"Load");
- sprintf(askbox[3].text,"Full Size"); askbox[3].draw = 1 ;
- sprintf(askbox[4].text,"Half Size"); askbox[4].draw = 1 ;
- sprintf(askbox[5].text,"Double Size"); askbox[5].draw = 1 ;
- sprintf(askbox[6].text,"Invert"); askbox[6].draw = 1 ;
- sprintf(askbox[7].text,"Normal"); askbox[7].draw = 1 ;
- askbox[3].set = 1 ;
- askbox[7].set = 1 ;
- askbox[3].reset = 4 ;
- askbox[4].reset = 5 ;
- askbox[5].reset = 3 ;
- askbox[6].reset = 7 ;
- askbox[7].reset = 6 ;
- break ;
- case 3 : sprintf(askbox[0].text,"Save");
- sprintf(askbox[3].text,"Sub-directory"); askbox[3].draw = 1 ;
- sprintf(askbox[4].text,"Current directory"); askbox[4].draw = 1 ;
- askbox[3].set = 1 ;
- askbox[3].reset = 4 ;
- askbox[4].reset = 3 ;
- break ;
- case 4 : sprintf(askbox[0].text,"Load");
- sprintf(askbox[3].text,"Full Size"); askbox[3].draw = 1 ;
- sprintf(askbox[4].text,"Half Size"); askbox[4].draw = 1 ;
- sprintf(askbox[5].text,"Double Size"); askbox[5].draw = 1 ;
- askbox[3].set = 1 ;
- askbox[3].reset = 4 ;
- askbox[4].reset = 5 ;
- askbox[5].reset = 3 ;
- break ;
- case 5 : sprintf(askbox[0].text,"Save");
- sprintf(askbox[3].text,"Sub-directory"); askbox[3].draw = 1 ;
- sprintf(askbox[4].text,"Current directory"); askbox[4].draw = 1 ;
- sprintf(askbox[5].text,"Scamper format"); askbox[5].draw = 1 ;
- sprintf(askbox[6].text,"Postscript"); askbox[6].draw = 1 ;
- askbox[3].set = 1 ;
- askbox[5].set = 1 ;
- askbox[3].reset = 4 ;
- askbox[4].reset = 3 ;
- askbox[5].reset = 6 ;
- askbox[6].reset = 5 ;
- break ;
- case 6 : sprintf(askbox[0].text,"Insert");
- sprintf(askbox[3].text,"Add"); askbox[3].draw = 1 ;
- sprintf(askbox[4].text,"And"); askbox[4].draw = 1 ;
- sprintf(askbox[5].text,"Or"); askbox[5].draw = 1 ;
- sprintf(askbox[6].text,"Not"); askbox[6].draw = 1 ;
- askbox[3].set = 1 ;
- askbox[3].reset = 4 ;
- askbox[4].reset = 5 ;
- askbox[5].reset = 6 ;
- askbox[6].reset = 3 ;
- break ;
- default: ;
- };
- AskOn(1);
- Asking = 1 ;
- FlushQueue();
- AskVal = n ;
- SetWindow(Multi_Window);
- SetBackColour(cols[filebg]);
- ClearScreen();
- SetColour(cols[filefg]);
- }
-
- /* ------------------------------------------------------------------------- */
-
- void CallAsk()
- /* Either `Return' has been pressed or the commit option for a file operation selected. So activate the
- file operation which is selected */
- {
- int n , op , on , off, temp;
-
- AskOff();
- Asking = 0 ;
- BusyCursor();
- FlushQueue();
- temp = AskVal ;
- AskVal = 0 ;
- switch(temp) {
- case 1 : displaychange = askbox[3].set ; /* Read File */
- ReadFile(); break ;
- case 2 : for( op=3 ; op<6 ; ++op) /* Load Bitmap */
- if (askbox[op].set)
- n = op - 2 ;
- on = askbox[7].set ;
- off = askbox[6].set ;
- LoadBitmap(n,on,off);
- break ;
- case 3 : if (askbox[3].set) /* Save Bitmap */
- SaveBitmap(1);
- else
- SaveBitmap(2);
- break ;
- case 4 : for( op=3 ; op<6 ; ++op) /* Load Domain */
- if (askbox[op].set)
- n = op - 2 ;
- LoadScreen(n); break ;
- case 5 : n = 1 + askbox[4].set ; /* Save Domain */
- if (askbox[5].set)
- SaveScreen(n);
- else
- SavePS(n);
- break ;
- case 6 : for( op=3 ; op<7 ; ++op) /* Insert Domain */
- if (askbox[op].set)
- n = op - 2 ;
- InsertScreen(n); break ;
- default: ;
- };
- SetWindow(Main_Window);
- DrawBox(AskOp,0);
- OnCursor();
- }
-
- /* ------------------------------------------------------------------------- */
-
- void UpdateButtons( n ) int n ;
- /* A state colour has been changed (state = n), see if any of the `Mouse Button' options needs updating, if so update them
- */
- {
- int b ;
-
- for(b = 0 ; b<3 ; ++b)
- if (buttons[b].value == n)
- DrawBox(28+b,0);
- }
-
- /* ------------------------------------------------------------------------- */
-
- void AskBoxes()
- /* Draw all the Ask Boxes (those of file operations)
- */
- {
- int x ;
- SetWindow(Multi_Window);
- for( x=0 ; x < 8 ; ++x )
- if (askbox[x].draw)
- DrawAskBox(x);
- }
-
- /* ------------------------------------------------------------------------- */
-
- void DrawAskBox(x) int x ;
- /* Given the number of an Ask Box, draw it in the Multi_Window
- */
- {
-
- SetWindow(Multi_Window);
- SetColour(cols[filefg]);
- FillRectangle(askbox[x].sx,askbox[x].sy,askbox[x].fx,askbox[x].fy);
- FillRectangle(askbox[x].sx-1,askbox[x].sy+1,askbox[x].fx+1,askbox[x].fy-1);
- FillRectangle(askbox[x].sx+1,askbox[x].sy-1,askbox[x].fx-1,askbox[x].fy+1);
- if (x<3) {
- FillRectangle(askbox[x].sx-2,askbox[x].sy+2,askbox[x].fx+2,askbox[x].fy-2);
- FillRectangle(askbox[x].sx+2,askbox[x].sy-2,askbox[x].fx-2,askbox[x].fy+2);
- };
- if ((x<3) || (askbox[x].set==0)) {
- SetColour(cols[filebg]);
- FillRectangle(askbox[x].sx+3,askbox[x].sy+3,askbox[x].fx-3,askbox[x].fy-3);
- FillRectangle(askbox[x].sx+2,askbox[x].sy+4,askbox[x].fx-2,askbox[x].fy-4);
- FillRectangle(askbox[x].sx+4,askbox[x].sy+2,askbox[x].fx-4,askbox[x].fy-2);
- if (x<3) {
- FillRectangle(askbox[x].sx+1,askbox[x].sy+5,askbox[x].fx-1,askbox[x].fy-5);
- FillRectangle(askbox[x].sx+5,askbox[x].sy+1,askbox[x].fx-5,askbox[x].fy-1);
- };
- };
- SetColour(cols[filefg]);
- if (x<3)
- Centre(askbox[x].text,askbox[x].sx,askbox[x].sy,askbox[x].fx,askbox[x].fy);
- else
- Centre(askbox[x].text,askbox[x].fx,askbox[x].sy,askbox[x].fx,askbox[x].fy);
- }
-
- /* ------------------------------------------------------------------------- */
-
- void ButtonAsk(x,y) int x,y ;
- /* A button has been pressed in the Multi-Window whilst a file operation has been initiated. Act on the
- button press...
- */
- {
- int n , op;
-
- updown = 0;
- op = -1 ;
- for( n=0 ; n<8 ; ++n )
- if ((x >= askbox[n].sx) && (x <= askbox[n].fx) && (y >= askbox[n].sy) && (y <= askbox[n].fy))
- op = n ;
- if (op == 0)
- CallAsk();
- if (op == 1) {
- AskVal = 0 ;
- Asking = 0 ;
- AskOff();
- DrawBox(AskOp,0);
- FlushQueue();
- };
- if (op == 2) {
- fnamel = 0;
- DisplayFileName(0);
- };
- if (op > 2) {
- askbox[op].set = 1 ; DrawAskBox(op) ;
- n = op ;
- do {
- n = askbox[n].reset ;
- if ((n != 0) && (n != op)) {
- askbox[n].set = 0 ; DrawAskBox(n) ;
- };
- } while ((n != 0) && (n != op));
- };
- }
-
- /* ------------------------------------------------------------------------- */
-
- void SmallView()
- /* Display the `Small View' image
- */
- {
- int sx,sy ;
-
- DisplayOn();
- SetWindow(Display_Window);
- display = 2 ;
- sx = (DispX - max_x) / 2 ;
- sy = (DispY - max_y) / 2 ;
- XCopyArea(dpy,small,win,gc,0,0,max_x,max_y,sx,sy);
- }
-
- /* ------------------------------------------------------------------------- */
-
- void Initialise()
- /* Initialise the program, operation include :
-
- Open windows
- Initialise the main menu options
- Set up status
- Set all states colours to either balck or white
- Create initial domain
- Draw main menu
- */
- {
- int s ;
-
- InitialiseWindows();
- MakeWindows();
- InitBoxes();
- max_x = 20 ;
- max_y = 20 ;
- start_x = 0;
- start_y = 0;
- new = 0 ;
- old = 1 ;
- scale = 30;
- shape = 1;
- Shift = 0 ;
- mode = 0 ;
- stopat = 1 ;
- torus = 1 ;
- stopnum = 0 ;
- displaychange = 1 ;
- fnamel = 0 ;
- AskVal = 0 ;
- Asking = 0 ;
- generation = 0;
- error = 0 ;
- display = 0;
- updateX = start_x;
- updateC = 0;
- updatesmall = 1 ;
-
- for( s=0 ; s<max_states ; ++s)
- states[s].colour = AllocColour(s % 2,-1,-1) ;
- setup_array(0,0,max_x,max_y,1);
- link_cells(1,1);
- init_stats();
- InitGreyScale();
- FlushQueue();
- MainScreen();
- AutoResize();
- ClearRules();
-
- sccol = cols[title] ;
- scnum = 0 ;
- numdir = -1 ;
- numloop = 0 ;
- dirtype = 1 ;
- change = 1 ;
- greyscale = 1 ;
- loopnum = 75 ;
- }
-
- /* ------------------------------------------------------------------------- */
-
- main()
- /* Main loop for Scamper */
- {
-
- Initialise(); /* Initialise ScAmPeR */
-
- do { /* Repeat */
- if (update) /* if domain is still being drawn, then carry on */
- display_cells();
- while (EventPending()) /* While there is an X event waiting, serve it */
- service();
- if (updown) /* If mouse button held down, then repeat selection */
- if ((++counter == 800) && (old_op != 0))
- operation(old_x,old_y,updown-1);
- if (running || step) { /* Perform a generation if required */
- run();
- if (step != 0)
- DrawBox(2,0);
- step = 0;
- }
- else if (greyscale || (scnum != 50)) /* If nothing else to do, update the trendy title bar */
- if (++numloop == 512) {
- if ((scnum == 0) || (scnum == loopnum)) {
- numdir = -numdir ;
- if (scnum == 0) {
- loopnum = 75 ;
- change = 1 ;
- dirtype = 1 - dirtype ;
- if (dirtype == 0)
- loopnum = 256 ;
- };
- };
- scnum += numdir ;
- if ((scnum == 1) && (! greyscale)) {
- scnum = 50 ;
- dirtype = 0 ;
- change = 1 ;
- }
- else if (! greyscale) {
- scnum = 0 ;
- numdir = -1 ;
- };
- if (scnum <= 50) {
- bycol = colours[sccol].mapno ;
- sccol = fade(scnum,sccol);
- if ((bycol != colours[sccol].mapno) || change) {
- change = 0 ;
- SetWindow(Title_Window) ;
- SelectFont(Large_Font);
- SetColour(sccol);
- if (dirtype == 0) {
- PrintString(23+offset,28,"S");
- PrintString(50+offset,33,"C");
- PrintString(80+offset,28,"A");
- PrintString(105+offset,33,"M");
- PrintString(136+offset,28,"P");
- PrintString(163+offset,33,"E");
- PrintString(191+offset,28,"R");
- }
- else
- Centre( theauthor , 0 , 0 , DispX-300 , 35);
- SelectFont(Small_Font);
- };
- };
- numloop = 0 ;
- };
- } while (! Exit); /* Until `Quit' has been selected */
- CloseDownWindows(); /* Close all windows */
- }
-