/*
 Copyright (C) Andrew Wuensche
 
 This file is part of DDLab (Discrete Dynamics Lab) <www.ddlab.org>
 
 DDLab is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.
 
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with DDLab.  If not, see <http://www.gnu.org/licenses/>.
 */

/************************* save_load_image ****************************/
#include "edecfunc.h"

#if __WATCOM__
   #include <sys\types.h>
#elif __UNIX__
   #include <unistd.h>
   #include <fcntl.h>
   #include <dirent.h>
#  ifndef __LINUX__
      //#include <sys/dirent.h> /*linux 5.1 didnt like this*/
     #include <dirent.h>
#  endif
#endif

#if __DARWIN__
  #include<sys/stat.h>
#endif


/***************  list of functions in this file *************/
/*
char select_filename(char *load_save,char *title,
			  char *extention,char *defname)
signed int myopen(char *this_filename, char write, char append)
void file_error(char *this_filename)
void load_save_exhaustive(char load_save)
unsigned int load_save_nhoodmix(char load_save)
void save_data(char *buf)
void save_binary_data(unsigned char *buf,unsigned long sizeofbuf)
void save_screen(void)
void load_screen(void)
unsigned char load_save_wrs
	 (char load_save,char* wrsbuf,char wrstype) \\or seed*/
signed int get_unsigned_value(unsigned char *array, 
			      unsigned int ct_count, char this_value_bits);
char locate_small_net(char dim,unsigned int *poss3d,unsigned int thislineL,
   signed int thisi2d,signed int thisj2d,signed int thish3d);
char locate_big_net(char dim,char file_dim,unsigned int thislineL,
   signed int thisi2d,signed int thisj2d,signed int thish3d);
/*
void save_last_rule(char* rule,char thisnhood)
char load_last_rule(char* rule,char thisnhood)
unsigned int load_save_ascii_rule_seed(char load_save, char rule_seed,
              char* base_buf,unsigned int base_size)
unsigned int load_Golly_seed(char load_save,char *seed,unsigned int lineL)
void load_glider_buf(signed int no_of_glider_rules)
char select_list_files(char* filespec,
	     signed int leftbox,signed int topbox)
void change_drive_dir(char which)
*/
/************** select filename, drive, dir ***************************/
char select_filename(char *load_save,char *title,
			  char *extention,char *defname){
 unsigned int xbox,leftbox,topbox;
 char len;
 unsigned char tempcolor;
#if __UNIX__
 char  path[1024];
# endif
  
  tempcolor=getcolor();
  setcolor(white);
  get_prompt_box(0,3); /*get the prompt box with basin data*/

 startfilename:

  getcwd(path, 81);
  sprintf(textb[0],
        "%s %s-filename (no ext) %s will be added",
					 load_save,title,extention+1);
  sprintf(textb[1],"change dir-d, now: %s:", path);
  sprintf(textb[2],"list-?, quit-q, default %s:",defname);

  xbox=draw_prompt_box(3);
  outtext(textb[0]);
  moveto(xbox,gety+CHeight);
  outtext(textb[1]);
  moveto(xbox,gety+CHeight);
  outtext(textb[2]);
  len=input_string(8,0);


     if (is[0]=='d' && is[1]==13){
	change_drive_dir(is[0]);
	goto startfilename;
     }

  if (is[0]=='?'){
	leftbox=Maxx-vgax(75);
	topbox=vgay(40);
	len=select_list_files(extention,leftbox,topbox);
	if (len==0) goto startfilename;
	else{
		/*sprintf(filename,"%s%s",is,extention+1);*/
		memmove(filename,is,len);
		memmove(filename+len,extention+1,4);
		filename[len+4]='\0';
	}
  }
  else if (is[0]=='q'){
	/*restore basin data in prompt box*/
        uncover_free_prompt_box(0);
        setcolor(tempcolor);
	return('q');
  }
  else if (is[0]==13 || isdigit(is[0]))
			 sprintf(filename,"%s%s",defname,extention+1);
  else{
	memmove(filename,is,len);
	memmove(filename+len,extention+1,4);
	filename[len+4]='\0';
  }

  /*confirm filename*/
  moveto(xbox,gety);
  setfillstyle(SOLID_FILL,black);
  bar(getx,gety+vgay(2),Maxx-vgax(3),gety+CHeight+vgay(2));
  sprintf(textb[0],"filename=%s",filename);
  outtext(textb[0]);
  if (memcmp(load_save,"LOAD",4)==0 && memcmp(extention,"*.nat",5)==0)
		       outtext(" REVISE-q keepscreen-k cont-ret:");
  else outtext(" REVISE-q cont-ret:");
  input_string(1,0);
  if (is[0]=='q') goto startfilename;

  uncover_free_prompt_box(0);
  setcolor(tempcolor);
  return(0);
}
/****************** open file to read or write  ********************/
signed int myopen(char *this_filename, char write, char append){
   signed int fid;
   char  cmd[1024]; 
/*load*/
  if (write==0){
#    if __WATCOM__  
        fid=open(this_filename,O_RDWR|O_BINARY);
#    elif __UNIX__
        fid=open(this_filename,O_RDWR);
        /*if (fid==-1) fprintf(stderr,
	  "fid=%d this_filename=%s write=%d\n",fid,this_filename,write);*/ 
#    endif
  }
/*save*/
  else if (write==1){

     
#    if __WATCOM__
        if (append==1) fid=open(this_filename,
	     O_RDWR|O_CREAT| O_APPEND|O_BINARY,S_IREAD|S_IWRITE);
	else  fid=open(this_filename,
	     O_RDWR|O_CREAT|O_TRUNC|O_BINARY,S_IREAD|S_IWRITE);  
#    elif __UNIX__
	if (append==1) fid=open(this_filename,
	     O_RDWR | O_CREAT | O_APPEND,S_IREAD | S_IWRITE);
	else  fid=open(this_filename,
	     O_RDWR | O_CREAT | O_TRUNC,S_IREAD | S_IWRITE);
        /*make sure file name is read write to all
         permissions  -rw------- ?? */
	
        XFlush(D);	
        sprintf(cmd,"chmod 644 %s",this_filename);
        system(cmd);
        XFlush(D);	
        if (fid==-1) fprintf(stderr,
	  "\nfid=%d this_filename=%s write=%d\n",fid,this_filename,write);	
#    endif 
  }
  return fid;
}

/****************** file access error  ********************/
void file_error(char *this_filename){

     get_prompt_box(6,1); 
     draw_prompt_box(1);   
#    if __WATCOM__	
	sprintf(textb[0],"file error %s, %s, cont-ret:",
                               this_filename,sys_errlist[errno]);
#    elif __UNIX__
        sprintf(textb[0],"file error %s, cont-ret:",
                               this_filename);
#    endif
     outtext(textb[0]);
     input_string(1,0);
     uncover_free_prompt_box(6);   
}

/********************* save exhaustive map, sept 93 ********************/
void load_save_exhaustive(char load_save){

  signed int tempx,tempy,fid;
  char file_ret,wrong_file=0;
  unsigned long state_space,memreq,filebytes;

  tempx=getx;
  tempy=gety;

  if (load_save=='l') sprintf(textb[4],"LOAD ");
  if (load_save=='s') sprintf(textb[4],"SAVE ");
  sprintf(textb[3],"myexh_v%d",value_range);
  file_ret=select_filename(textb[4],"EXHAUSTIVE","*.exh",textb[3]);

  if (file_ret=='q'){
	moveto(tempx,tempy);
	is[0]='q';
	return;
  }
  state_space=(unsigned long)(pow(value_range,(double)lineL));
  memreq=state_space*bytesL*sizeof(char);

  if (load_save=='l'){
     fid=myopen(filename,0,0);
     filebytes= filelength(fid);
     if (fid != -1){
	if (filebytes!=memreq){
	   sprintf(textb[1],"file n=%d != network n=%d",
              (unsigned int)log(filebytes),(unsigned int)log(memreq));
	   wrong_file=1;
	   fid=-1;
	}
     }
  }
  if (load_save=='s') fid=myopen(filename,1,0);     
  if (fid==-1 || (filebytes!=memreq && load_save=='l')){	
	if (wrong_file==1){
	   sprintf(textb[0],"%s (wrong file) cont-ret:",textb[1]);
           draw_prompt_box(1);
           outtext(textb[0]);
           input_string(1,0);
	}
        else file_error(filename);
	is[0]='q';
	close(fid);
	return;
  }
  if (load_save=='s') vret=write(fid,exh_pairs,memreq);
  if (load_save=='l') vret=read(fid,exh_pairs,memreq);

  close(fid);
  moveto(tempx,tempy);
}

/********************* save screen image, sept 93 ********************/
unsigned int load_save_nhoodmix(char load_save){

  signed int tempx,tempy,fid;
  char file_ret;
  unsigned int memreq,filebytes;

  tempx=getx;
  tempy=gety;

  if (load_save=='l') sprintf(textb[4],"LOAD ");
  if (load_save=='s') sprintf(textb[4],"SAVE ");  
  file_ret=select_filename(textb[4],
                  "K-MIX","*.mix","my_mix"); 
  if (file_ret=='q'){
	moveto(tempx,tempy);
	is[0]='q';
	return(0);
  }
  memreq=lineL*sizeof(char);

  if (load_save=='l' || load_save=='L'){
     fid=myopen(filename,0,0);
     filebytes= filelength(fid);
  }
  if (load_save=='s') fid=myopen(filename,1,0);
  if (fid==-1){
        file_error(filename);
	is[0]='q';
	close(fid);
	return(0);
  }
  if (load_save=='s') vret=write(fid,nhoodm,memreq);
  if (load_save=='l'){
     if (filebytes<=memreq) vret=read(fid,nhoodm,filebytes);
     else vret=read(fid,nhoodm,memreq);
  }
  close(fid);
  moveto(tempx,tempy);
  return(filebytes);
}

/**************** save subtree/basin/field *************************/
void save_data(char *buf){

  signed int tempx,tempy,fid;

  tempx=getx;
  tempy=gety;

  fid=myopen(filename_data,1,1);

  if (fid==-1){
     file_error(filename_data);
     close(fid);
     moveto(tempx,tempy);
     return;
  }
  vret=write(fid, buf, strlen(buf));
                          
  close(fid);
  moveto(tempx,tempy);
}

/**************** save subtree/basin/field *************************/
void save_binary_data(unsigned char *buf,unsigned long sizeofbuf){

  signed int tempx,tempy,fid;

  tempx=getx;
  tempy=gety;

  fid=myopen(filename,1,1);
  
  if (fid==-1){
     file_error(filename);
     close(fid);
     moveto(tempx,tempy);
     return;
  }
  vret=write(fid, buf, sizeofbuf);
                          
  close(fid);
  moveto(tempx,tempy);
}

/** save screen image, sept 93 (rev Oct 2012, Max_ushort) ****/
void save_screen(void){

  unsigned short tempx,tempy,
      slice,/*screenx,screeny,*/
      zz,divscreeny,last_divscreen,yup,
      thisMaxx,thisMaxy,c_old,
      pixcount,
      startpix, /*no of color groups*/
      i,z,
      bi;  /*buffer index*/
  signed short fid;
  char sliceno,
       file_ret;

  unsigned char *ypix,*cpix,*repeat,*buf;
       
# if __UNIX__
     XImage *ScreenImage;
     Pixmap *offscreen_pixmap;
     unsigned long pxc/*backc_lu*/;
     unsigned char oldback;
# elif __WATCOM__
     unsigned char pxc,backc;
# endif

# if __UNIX__
     setviewport(0,0,Maxx,WinMaxy,1);
     /*allocate mem for pixmap*/
     if ((offscreen_pixmap = 
          (Pixmap *)malloc(sizeof(Pixmap *))) == NULL)
		outof_memory("Pixmap pointer");
     getimage(0,0,Maxx+1,WinMaxy+1,offscreen_pixmap);
     ScreenImage=XGetImage(D,*offscreen_pixmap,
                0,0,Maxx+1,WinMaxy+1,AllPlanes,XYPixmap);
                              
     if (bground=='b'){ 
        /*backc_lu=0;*/  /*black background*/
        oldback=1;
     }
     else{
        /*backc_lu=Max_ushort;*/  /*white background=65535*/
        oldback=0;
     }
# elif __WATCOM__
     setviewport(0,0,Maxx,getmaxy(),1);
     backc=black;    /*both black and white background*/
# endif

  tempx=getx;
  tempy=gety;

  file_ret=select_filename("SAVE","SCREEN","*.nat","myimage");

  if (file_ret=='q'){
#       if __UNIX__
           freeimage(offscreen_pixmap);
           free(offscreen_pixmap);
           free(ScreenImage);
#       endif
        setviewport(0,0,Maxx,Maxy,1);
	moveto(tempx,tempy);
	is[0]='q';
	return;
  }

  if ((ypix=(unsigned char *)calloc(241,sizeof(unsigned char)))
				  ==NULL) outof_memory("ypix");  
  if ((cpix=(unsigned char *)calloc(241,sizeof(unsigned char)))
				  ==NULL) outof_memory("cpix");
  if ((repeat=(unsigned char *)calloc(241,sizeof(unsigned char)))
				  ==NULL) outof_memory("repeat");
  /*max buffer to store bytes*/
  if ((buf=(unsigned char *)
           calloc(Max_ushort+1,sizeof(unsigned char)))
		   ==NULL) outof_memory("save screen buf");

     fid=myopen(filename,1,0);
     if (fid==-1){
	file_error(filename);
	free(ypix);
	free(cpix);
	free(repeat);
	free(buf);
	close(fid);
#       if __UNIX__
           free(ScreenImage);
#       endif
	return;
  }
  thisMaxx=getmaxx();
  thisMaxy=getmaxy();

  /*for compatability with early ddlab*/
  if (thisMaxx==640-1 && thisMaxy==480-1){
      buf[0]='l';
      vret=write(fid,buf,1); /*first char in file - old vga*/
  }
  else if (thisMaxx==800-1 && thisMaxy==600-1){
       buf[0]='m';	
       vret=write(fid,buf,1); /*first char in file - old 800x600*/
  }
  else if (thisMaxx==1024-1 && thisMaxy==768-1){
       buf[0]='h';	
       vret=write(fid,buf,1); /*first char in file - old svga*/
  }
  else{
       buf[0]='o';  /*for other*/
       vret=write(fid,buf,1); /*first char in file - old svga*/
  }
  /*fprintf (stderr,"\n %d",thisMaxx);*/
  /* otherwize save sceen x,y first 4 chars*/
  if (buf[0]=='o'){     
     buf[0]=(unsigned char)((thisMaxx+1) & 0x00ff); /*low byte  */
     buf[1]=(unsigned char)((thisMaxx+1) >> 8);     /*high byte */
     /*screenx=buf[0]+(((unsigned int)buf[1])<<8);*/
     buf[2]=(unsigned char)((thisMaxy+1) & 0x00ff); /*low byte  */
     buf[3]=(unsigned char)((thisMaxy+1) >> 8);     /*high byte */
     /*screeny=buf[2]+(((unsigned int)buf[3])<<8);*/
     /*fprintf (stderr,"\n buf[0]=%d buf[1]=%d temp=%d",buf[0],buf[1],screenx);
       fprintf (stderr,"\n buf[2]=%d buf[3]=%d temp=%d",buf[2],buf[3],screeny);*/
     vret=write(fid,buf,4);
  }

  if (thisMaxy<=479) sliceno=4;
  else sliceno=8;
  /*divide screen horizontally into sliceno slices*/
  divscreeny=(thisMaxy+1)/sliceno;
  last_divscreen=divscreeny+(thisMaxy+1)%sliceno;
  /*fprintf (stderr,"\n div=%d last=%d",divscreeny,last_divscreen);*/

  for (i=0;i<=sliceno-1;i++){
     bi=2; /*buffer index: 0&1=buffsize*/
     yup=divscreeny*i;
     if (i==sliceno-1) divscreeny=last_divscreen; 
     for (slice=0;slice<=thisMaxx;slice++){ /*scan across->*/
	startpix=0;
	pixcount=0;        
	for (zz=0;zz<=divscreeny-1;zz++){
#           if __WATCOM__
	       pxc=getpixel(slice,zz+yup);
               if (pxc==backc){
		   startpix=0;
		   continue;
	       }   
#           elif __UNIX__
	       pxc=XGetPixel(ScreenImage,slice,zz+yup);
               /*if (pxc!=backc_lu) fprintf(stderr,"\n %lu ",pxc);*/
               for (c_old=0;c_old<=15;c_old++){
		     if (Color_Table[oldcolor[c_old]]==pxc){ 
                        pxc=oldcolor[c_old];
                        /*if (pxc!=oldback) fprintf(stderr,"%d ",pxc);*/
		        break;
	             }
	       }
               if (pxc==oldback){
		   startpix=0;
		   continue;
	       } 
               
#           endif
	    
	    if (startpix==1){
		if (cpix[pixcount]==pxc){
			repeat[pixcount]+=1;
			continue;
		}
		else startpix=0;
	    }
	    pixcount++;  /*max divscreeny*/
	    ypix[pixcount]=zz;  /*start y co-ord*/
	    repeat[pixcount]=0; /*set repeat to 0*/
	    cpix[pixcount]=pxc; /*color*/
	    startpix=1;
	}
        if (bi>=Max_ushort && bi%Max_ushort==0){
              if ((buf=(unsigned char *)realloc(buf,
                 (bi+Max_ushort)*sizeof(unsigned char)))
		      ==NULL) outof_memory("save screen buf");
        }
	buf[bi]=pixcount;
	bi++;
	/*if the whole slice was black*/
	if (pixcount==0) continue;
	/*pixcount=no of continuous color segments*/
	for (z=1;z<=pixcount;z++){
		buf[bi]=ypix[z];
		bi++;
		if (repeat[z]==0) buf[bi-1]+=128;/*set highest bit on, ypix*/
		else{
			buf[bi]=repeat[z];
			bi++;
		}
		buf[bi]=cpix[z];
		bi++;
	}
     }
     
     /*save buf size in first 2 bytes*/
     /*fprintf (stderr,"\n bi%d",bi)*/;
     buf[0]=(unsigned char)(bi/256);
     buf[1]=(unsigned char)(bi%256);
     vret=write(fid, buf, bi);
  }
  close(fid);

  free(ypix);
  free(cpix);
  free(repeat);
  free(buf);
  # if __UNIX__
     freeimage(offscreen_pixmap);
     free(offscreen_pixmap);
     free(ScreenImage);
# endif
  moveto(tempx,tempy);

}

/**** load screen image, sept 93 (rev Oct 2012, Max_ushort) *****/
void load_screen(void){

  unsigned short tempx,tempy,
      slice,
      divscreeny,yup,
      thisMaxx,thisMaxy,
      i,zz,z,
      pixcount,
      bi; /*buffer index*/
  signed short fid;
  char keepscreen=0,
       sliceno,file_ret;
  unsigned char ypix,cpix,repeat,*buf;
  unsigned long /*filebytes,*/ maxbuf; /*buffer size*/

# if __UNIX__
     unsigned char tempcolor=nowcolor;
# endif

  tempx=getx;
  tempy=gety;
  setviewport(0, 0, Maxx, Maxy, 0);
  file_ret=select_filename("LOAD","SCREEN","*.nat","myimage");

  if (file_ret=='q'){
	moveto(tempx,tempy);
	is[0]='q';
	return;
  }

  if (is[0]=='k') keepscreen=1;
  fid=myopen(filename,0,0);
  if (fid==-1){
        file_error(filename);
	close(fid);
	moveto(tempx,tempy);      
	return;
  }
  /*filebytes= filelength(fid);*/
  /*fprintf (stderr,"\n filebytes=%lu",filebytes);*/
  /*max buffer to store bytes*/
  if ((buf=(unsigned char *)
         calloc(Max_ushort,sizeof(unsigned char)))
	    ==NULL) outof_memory("load screen buf");

  /*for compatability with early ddlab*/
  vret=read(fid,buf,1); /*read first char in file to check if x=480*/
  if (buf[0]=='l'){ /* old 640 X 480 VGA screen*/
       thisMaxx=640-1;
       thisMaxy=480-1;      
  }
  else if (buf[0]=='m'){ /* old 800 X 600 VGA screen*/
       thisMaxx=800-1;
       thisMaxy=600-1;      
  }
  else if (buf[0]=='h'){ /* old 1024 X 768 SVGA screen*/
       thisMaxx=1024-1;
       thisMaxy=768-1;      
  }
  else if (buf[0]=='o'){ /* none of the above*/       
       vret=read(fid,buf,4); /*else also next char to check x*/
       thisMaxx=buf[0]+(((unsigned short)buf[1])<<8)-1;
       thisMaxy=buf[2]+(((unsigned short)buf[3])<<8)-1;
       /*fprintf (stderr,"\n buf[0]=%d buf[1]=%d x=%d",buf[0],buf[1],thisMaxx);
	 fprintf (stderr,"\n buf[2]=%d buf[3]=%d y=%d",buf[0],buf[1],thisMaxy);*/
  }   

  
  if (thisMaxy<=479) sliceno=4; /*4 slices*/
  else sliceno=8; /*4 slices*/
  /*fprintf(stderr,"\n sliceno=%d",sliceno);*/

  if (keepscreen==0) cleardevice();
  setviewport(0, 0, getmaxx(), getmaxy(), 0);
  /*divide screen horizontally into 4 slices*/
  divscreeny=(thisMaxy+1)/sliceno;
  /*fprintf(stderr,"\n %d/%d=%d",thisMaxy+1,sliceno,divscreeny);*/
  
  for (i=0;i<=sliceno-1;i++){
     vret=read(fid,buf,2); /*first 2 bytes give size-2 to be read from buf*/
     maxbuf=(unsigned long)buf[0]*256+(unsigned long)buf[1];
     vret=read(fid,buf,maxbuf-2); /*read correct no of bytes from buf*/
     bi=0;
     yup=divscreeny*i;
     for (slice=0;slice<=thisMaxx;slice++){
	pixcount=buf[bi];
	bi++;
        if (bi>=Max_ushort && bi%Max_ushort==0){
              if ((buf=(unsigned char *)
                   realloc(buf,(bi+Max_ushort)*
                       sizeof(unsigned char)))
			   ==NULL) outof_memory("load screen buf");
        }
	if (pixcount==0) continue;
	for (z=1;z<=pixcount;z++){
	    ypix=buf[bi];
	    bi++;
	    if (ypix>=128){  /*if high bit in ypix=1, no repeats*/
		ypix-=128;   /*lower bits give +co-ord*/
		repeat=0;
	    }
	    else{
		repeat=buf[bi];
		bi++;
	    }
	    cpix=buf[bi];
	    bi++;

	    for (zz=0;zz<=repeat;zz++){
#               if __WATCOM__
		   putpixel(slice,ypix+zz+yup,cpix);
#               elif __UNIX__
                   putpixel(slice,ypix+zz+yup,cpix);
                   /*XSetForeground(D,Gc,(unsigned long)cpix);
		     XDrawPoint(D, W, Gc,slice,ypix+zz+yup);*/
#               endif
	    }
	}       
    }
  }  
  free(buf);
  close(fid); 
# if __UNIX__
     setcolor(tempcolor);  
# endif
  moveto(tempx,tempy);
}

/********************* save rule or seed, dec 93 ********************/
unsigned char load_save_wrs
	 (char load_save,char *wrsbuf,char wrstype){ /*or seed*/

  signed int tempx,tempy,
    fid,tablemax,rulebytes,thisi2d=0,thisj2d=0,thish3d=0,
    starti,ii,jj,hh,thisii,thisjj,thishh;
  unsigned int  poss,z,thislineL,thisbytesL,wiringposs,notwired;
  char file_ret,
       lead_bytes, /*noting v,k,lineL,i2d,j2d,i3d,j3d -- depends on wrstype and lineL*/
       bigLnet, /*indicates lineL>=65535, file buf[0] has high bit=1*/
       bytes_lineL, /*bytes requires for lineL, 1 if<255, 2 if<65535, 4 if>=65535*/
       bytes_thislineL,
       buf0nhood, /*nhood found in buf[0]*/
       k_changed,
       last_char;
  unsigned char *buf;
  unsigned char wire,wire1,this_k;		
  unsigned long buffreq,buffindex,filebytes;

  /*copy file dimention, size ijh, and startpos ijh
   to global variables to show as block in net graphics,
   only if file net fits into larger base net. Initialise to 0*/
   file_dim=0; /*dimension of (converted?) file array*/
   /*size of file array*/
   file_i=file_j=file_h=0;
   /*start position in base array*/
   file_starti=file_startj=file_starth=0;

  tempx=getx;
  tempy=gety;
  setviewport(0, 0, Maxx, Maxy, 0);
  
  if (load_save=='l') sprintf(textb[4],"LOAD ");
  if (load_save=='s') sprintf(textb[4],"SAVE ");
  if (totalistic==1){
        tablemax=nhood*(value_range-1); /*max index of codetable*/
        rulebytes=(signed int) ceil(value_bits * 
          (double)(tablemax+1)/8);/*bytes for code, min=1*/
        last_char='t';
  }
  else if (totalistic==2){        
        tablemax=v_tablecodemax[nhood];
        rulebytes=(signed int) /*bytes for v_code, min=1*/
             ceil(value_bits * (double)(tablemax+1)/8);
        last_char='v';
  }
  else if (isotropic_set==1){
        tablemax=iso_tablemax;
        rulebytes=(signed int)ceil(value_bits * (double)(tablemax+1)/8);
        last_char='s';
  } 
  else{
        tablemax= (signed int)pow(value_range,(double)nhood)-1;
        rulebytes=(signed int)ceil(value_bits * (double)(tablemax+1)/8);
        last_char='s';
  } 
  
  /* seed: wrstype='s'
     single rule=0, wiring only=1, rulescheme only=2, wiring-rule scheme=3*/
  if (wrstype==0){
    if (totalistic==0){
        if (isotropic_set==1){
           sprintf(textb[3],"myisr_v%d",value_range);
           file_ret=select_filename(textb[4],"SINGLE ISO-RULE","*.isr",textb[3]);
        }
        else{
           sprintf(textb[3],"myrul_v%d",value_range);
           file_ret=select_filename(textb[4],"SINGLE RULE","*.rul",textb[3]);
        }
    }
    else if (totalistic){
       if (isotropic_set==1){
           sprintf(textb[3],"myisr_v%d",value_range);
           file_ret=select_filename(textb[4],"SINGLE ISO-RULE","*.isr",textb[3]);
       } 
       else if (totalistic==1){
           sprintf(textb[3],"mytco_v%d",value_range);
           file_ret=select_filename(textb[4],"SINGLE T-CODE","*.tco",textb[3]);
       }
       else if (totalistic==2){
           sprintf(textb[3],"myvco_v%d",value_range);
           file_ret=select_filename(textb[4],"SINGLE K-CODE","*.vco",textb[3]);
       }
     }    
  }
  else if (wrstype==1)
     file_ret=select_filename(textb[4],"WIRING ONLY","*.w_s","mywso");

  else if (wrstype==2){
     sprintf(textb[5],"*.r_%c",last_char);
     sprintf(textb[3],"myrso_v%d",value_range);
     file_ret=select_filename(textb[4],"RULE SCHEME ONLY",
                            textb[5],textb[3]);
  }
  else if (wrstype==3){
     sprintf(textb[5],"*.wr%c",last_char);
     sprintf(textb[3],"mywrs_v%d",value_range);
     file_ret=select_filename(textb[4],"WIRING+RULE SCHEME",
                             textb[5],textb[3]);
  }
  /*SEED*/
  else if (wrstype=='s' || wrstype=='x'){
     sprintf(textb[3],"mysee_v%d",value_range); 
     file_ret=select_filename(textb[4],"SEED","*.eed",textb[3]);
  }
  if (file_ret=='q'){
	moveto(tempx,tempy);
	is[0]='q';
	return(0);
  }
  /*-----------------------------------------------------------*/ 
   /*seed*/
  /*byte 0 =value_range*/
  /*old: 5 lead_bytes: 1,2 =lineL, bytes 4,5 = i2d,j2d for twod otherwise 0,0*/
  /*new: 9 lead_bytes: 1,2,3,4 =lineL, bytes 5,6,7,8 = i2d,j2d for twod otherwise 0,0*/
   /*-----------------------------------------------------------*/ 
  /* wrstype=1,2,3 (not for seed)*/
   /*OLD: 5 lead_bytes (0-4) 
    byte 0 =nhood, or max nhood
            if kmix high bit in byte set to 1
    bytes 1,2 =lineL, (Max_ushort-1)=65534
    if twod:  bytes 3,5 = i2d,j2d, 0,0 for oned
    if threed:  bytes 3,5 = i3d,j3d (0,0 for oned) else 2d or 3d, 
                   h3d=lineL/(i3d,j3d), if h3d=0 the 2d else 3d*/
              /*-----------------------------------------------------------*/
    /*for lineL<65535: 6 lead_bytes (0-5)
    
    byte 0=value_range, if byte 0=0 then load old style
    single rule: byte 0=value_range, byte 1=nhood, then value_bits*(lineL-1)
    wiring, rules:
    byte 0 =value_range
    byte 1 =nhood, or max nhood
            if kmix high bit in byte 1 set to 1
    bytes 2,3 =lineL, (Max_ushort-1)=65534 
    if twod:  bytes 4,5 = i2d,j2d, 0,0 for oned (max sides=255-1)
    if threed:  bytes 4,5 = i3d,j3d (0,0 for oned) else 2d or 3d, 
                   h3d=lineL/(i3d*j3d), if h3d>1 then 3d, else 2d*/
             /*-----------------------------------------------------------*/
    /*for lineL>=Max_ushort(65535) Maxu(4294967295): 10 lead_bytes (0-9)
    
    byte 0=value_range, if byte 0=0 then load old style
    single rule: byte 0=value_range, byte 1=nhood, then value_bits*(lineL-1)
    wiring, rules:
    byte 0 =value_range
    byte 1 =nhood, or max nhood
            if kmix high bit in byte 1 set to 1
    bytes 2,3,4,5 =lineL, (Maxu-1)=4294967294
    if twod:  bytes 6,7,8,9 = i2d,j2d, 0,0 for oned (Max_ushort-1 =65534)
    if threed:  bytes 6,7,8,9 = i3d,j3d (0,0 for oned) else 2d or 3d, 
                   h3d=lineL/(i3d*j3d), if h3d>1 then 3d, else 2d*/

  /*lead_bytes for saving (for loading will depend on the file*/
  bigLnet=0;
  if (wrstype==0) lead_bytes=2;
  else if (wrstype=='s' || wrstype=='x'){
    if  (lineL<Max_ushort){
          lead_bytes=5;
    }
    else{
          lead_bytes=9;
          bigLnet=1;
    }
  }
  else{ /*wrstype 1,2,3*/
     if (lineL<255){ 
        bytes_lineL=1;
        lead_bytes=6;
     }
     else if (lineL<Max_ushort){
        bytes_lineL=2;
        lead_bytes=6;
     } 
     else{ /*lineL>=Max_ushort, wire not connected=Maxu=4294967295*/
        bytes_lineL=4;
        lead_bytes=10;
        bigLnet=1;
     }
  }
  if (wrstype==0) buffreq=lead_bytes+rulebytes;/*one rule, byte 0 =value_range, byte 1 =nhood*/
  else if (wrstype==1) buffreq=lead_bytes+lineL*(bytes_lineL*nhood);/*wiring scheme*/
  else if (wrstype==2) buffreq=lead_bytes+lineL*rulebytes;          /*rule scheme  */
  else if (wrstype==3) buffreq=lead_bytes+lineL*(bytes_lineL*nhood+rulebytes); /*wr scheme*/
  else if (wrstype=='s' || wrstype=='x') buffreq=lead_bytes+bytesL; /*seed*/
                                                        /*bytesL is global variable*/
  /*fprintf(stderr,
    "\nload_save=%c lead_bytes=%d buffreq=%lu bytesL=%u",load_save,lead_bytes,buffreq, bytesL);*/

  /*buffer required to store bytes*/
  sprintf(textb[0],"buf, buffreq=%lu, calloc failed",buffreq);
  if ((buf=(unsigned char *)calloc(buffreq,sizeof(unsigned char)))
				 ==NULL) outof_memory(textb[0]);

  /*if(1){ //show the rule (for Ed)
	     int zzz;

              fprintf(stderr,"\nbuffreq=%lu\n",buffreq); //??
              for (zzz=0;zzz<=buffreq-1;zzz++) {
		fprintf(stderr,"%02X ",buf[zzz]);
              }
  }*/
  //?? fprintf(stderr,"\ncalloc done, load_save=%c",load_save);


  /*SAVE anything: seed, 
                   single rule, wiring scheme, rule scheme, or wiring/rule scheme*/
   /*-----------------------------------------------------------------------------*/
   if (load_save=='s'){
      fid=myopen(filename,1,0);
      if (fid==-1){
         file_error(filename);     
         is[0]='q';
         close(fid);
         free(buf);
         return(0);
      }
      /*save seed*/      
      if (wrstype=='s' || wrstype=='x'){          
	  //?? fprintf(stderr,"\nsaving seed: oned=%d twod=%d threed=%d lineL=%u Max_ushort=%d",
	  //	                          oned,twod,threed,lineL,Max_ushort); 
	  if  (lineL<Max_ushort){ /*bigLnet==0*/
              buf[0]=value_range;
	      buf[1]=(unsigned char)(lineL & 0x00ff); /*low byte */
	      buf[2]=(unsigned char)(lineL >> 8);     /*high byte*/
	      if (twod || wrstype=='x'){ /* 'x' changes 1d to 2d (if showbits_1d_as_2d==1)*/
	         wrstype='s';
	         buf[3]=(unsigned char)i2d;
	         buf[4]=(unsigned char)j2d;
	      }
              else if (threed){
	         buf[3]=(unsigned char)i3d;
	         buf[4]=(unsigned char)j3d;
	      }
           }
           else{ /*bigLnet==0 lineL>=Max_ushort, 65535*/
	      buf[0]=value_range+128; /*set high bit to 1 to indicate lineL>65535*/
	      /*save lineL, unsigned int, in 4 bytes*/
	      buf[1] = (unsigned char) ((lineL >> 24) & 0xff);
              buf[2] = (unsigned char) ((lineL >> 16) & 0xff);
	      buf[3] = (unsigned char) ((lineL >> 8) & 0xff);
              buf[4] = (unsigned char) (lineL & 0xff);
	      if (twod || wrstype=='x'){ /* 'x' changes 1d to 2d (if showbits_1d_as_2d==1)*/
	         wrstype='s';
                 /*save i2d<Max_ushort in 2 bytes*/
	         buf[5]=(unsigned char)(i2d & 0x00ff); /*low byte */
                 buf[6]=(unsigned char)(i2d >> 8);     /*high byte*/
                 //?? fprintf(stderr,"\n saving i2d=%d",
		 //          (signed int)(buf[5]+(((signed int)buf[6])<<8)));
                 /*save j2d, unsigned short, in 2 bytes*/
	         buf[7]=(unsigned char)(j2d & 0x00ff); /*low byte */
                 buf[8]=(unsigned char)(j2d >> 8);     /*high byte*/
                 //?? fprintf(stderr,"\n saving j2d=%d",
                 //        (signed int)(buf[7]+(((signed int)buf[6])<<8)));
	      }
              else if (threed){
                 /*save i3d<Max_ushort in 2 bytes*/
	         buf[5]=(unsigned char)(i3d & 0x00ff); /*low byte */
                 buf[6]=(unsigned char)(i3d >> 8);     /*high byte*/
                 /*save j3d, unsigned short, in 2 bytes*/
	         buf[7]=(unsigned char)(j3d & 0x00ff); /*low byte */
                 buf[8]=(unsigned char)(j3d >> 8);     /*high byte*/
	      }              
           }

	   //??fprintf(stderr,"\n");
           //for (z=0;z<=lead_bytes-1;z++){
	   //  fprintf(stderr,"buf[%d]=%d ",z,buf[z]);
           //}

           memmove(buf+lead_bytes,wrsbuf,bytesL);
	   vret=write(fid, buf,lead_bytes +bytesL);
     }

     /*save anything except seed:-------------------------------------/ 
       wrstype: single rule=0, wiring only=1,rulescheme only=2,wiring-rule scheme=3*/
     else{
       if (lineL<Max_ushort){ /*bigLnet==0*/
        buf[0]=value_range;
	buf[1]=nhood;
        /*set high bit to 1 to indicate a k-mix*/
        if (nhood_mixed) buf[1]+=128;

	if (wrstype==0){ /*single rule=0*/
	   memmove(buf+2,wrsbuf,rulebytes);
	   vret=write(fid, buf, 2+rulebytes);
	}
	else{ /*wiring only=1,rulescheme only=2,wiring-rule scheme=3*/
	   buf[2]=(unsigned char)(lineL & 0x00ff); /*low byte  */
	   buf[3]=(unsigned char)(lineL >> 8);     /*high byte */
	   if (twod){
	      buf[4]=(unsigned char)i2d;
	      buf[5]=(unsigned char)j2d;
	   }
           else if (threed){
	      buf[4]=(unsigned char)i3d;
	      buf[5]=(unsigned char)j3d;
	   }
	   buffindex=lead_bytes; 
	   for (poss=0;poss<=lineL-1;poss++){
	      /*rulescheme only=2,wiring-rule scheme=3*/
	      if (wrstype==2 || wrstype==3){ /*write rule*/
		 if (tot_only==0) memmove(buf+buffindex,carule[poss],rulebytes);
                 else{
                   if (totalistic==1)
		      memmove(buf+buffindex,cacode[poss],rulebytes);
                   else if (totalistic==2)
                      memmove(buf+buffindex,v_code[poss],rulebytes);
                 }
		 buffindex+=rulebytes;
	      }
              /*wiring only=1,wiring-rule scheme=3*/
	      if (wrstype==1 || wrstype==3){ /*write wiring*/
		 for (wire=0;wire<=nhood-1;wire++){
		    if (lineL<255){
		       buf[buffindex]=(unsigned char)wiring[poss][wire];
		       buffindex+=1;
		    }
		    else{
		       buf[buffindex]=(unsigned char)
			      (wiring[poss][wire] & 0x00ff); /*low byte */
		       buf[buffindex+1]=(unsigned char)
				 (wiring[poss][wire] >> 8);  /*high byte*/
		       buffindex+=2;
		    }
		 }
	      }
	   }
           vret=write(fid, buf, buffreq);
	  }	  
       } /*end bigLnet==0*/

       else{ /*bigLnet==1, lineL>=Max_ushort, 65535*/
        buf[0]=value_range+128; /*set high bit to 1 to indicate lineL>=Max_ushort, 65535*/
	buf[1]=nhood;
        /*set high bit to 1 to indicate a k-mix*/
        if (nhood_mixed) buf[1]+=128;
	if (wrstype==0){ /*single rule=0*/
	   memmove(buf+2,wrsbuf,rulebytes);
	   vret=write(fid, buf, 2+rulebytes);
	}
	else{ /*wiring only=1,rulescheme only=2,wiring-rule scheme=3*/
           /*save lineL in 4 bytes*/
	   buf[2]=(unsigned char)((lineL >> 24) & 0xff);
	   buf[3]=(unsigned char)((lineL >> 16) & 0xff);
           buf[4] = (unsigned char) ((lineL >> 8) & 0xff);
           buf[5] = (unsigned char) (lineL & 0xff);

	   if (twod){
              /*save i2d<Max_ushort, 65535 in 2 bytes*/
	      buf[6]=(unsigned char)(i2d & 0x00ff); /*low byte */
              buf[7]=(unsigned char)(i2d >> 8);     /*high byte*/
              /*save j2d, unsigned short, in 2 bytes*/
	      buf[8]=(unsigned char)(j2d & 0x00ff); /*low byte */
              buf[9]=(unsigned char)(j2d >> 8);     /*high byte*/
	   }
           else if (threed){
              /*save i3d<Max_ushort,65535 in 2 bytes*/
	      buf[6]=(unsigned char)(i3d & 0x00ff); /*low byte */
              buf[7]=(unsigned char)(i3d >> 8);     /*high byte*/
              /*save j2d, unsigned short, in 2 bytes*/
	      buf[8]=(unsigned char)(j3d & 0x00ff); /*low byte */
              buf[9]=(unsigned char)(j3d >> 8);     /*high byte*/
	   }
	   buffindex=lead_bytes; 
	   for (poss=0;poss<=lineL-1;poss++){
	      /*rulescheme only=2,wiring-rule scheme=3*/
	      if (wrstype==2 || wrstype==3){ /*write rule*/
		 if (tot_only==0) memmove(buf+buffindex,carule[poss],rulebytes);
                 else{
                   if (totalistic==1)
		      memmove(buf+buffindex,cacode[poss],rulebytes);
                   else if (totalistic==2)
                      memmove(buf+buffindex,v_code[poss],rulebytes);
                 }
		 buffindex+=rulebytes;
	      }
              /*wiring only=1,wiring-rule scheme=3*/
	      if (wrstype==1 || wrstype==3){ /*write wiring*/
		 for (wire=0;wire<=nhood-1;wire++){
                    buf[buffindex]=(unsigned char)((wiring[poss][wire] >> 24) & 0xff);
	            buf[buffindex+1]=(unsigned char)((wiring[poss][wire] >> 16) & 0xff);
                    buf[buffindex+2] = (unsigned char) ((wiring[poss][wire] >> 8) & 0xff);
                    buf[buffindex+3] = (unsigned char) (wiring[poss][wire] & 0xff);
		    buffindex+=4;		    
		 }
	      }
	   }
           vret=write(fid, buf, buffreq);
	  }
        }/*end bigLnet==1*/
     }
  }
  
  /*LOAD anything: seed, 
                   single rule, wiring scheme, rule scheme, or wiring/rule scheme*/
  /*-----------------------------------------------------------------------------*/
  if (load_save=='l'){
    char threed_file=0,twod_file=0,oned_file=0,bigLfile=0;
     unsigned char this_value_range;

     fid=myopen(filename,0,0);
     filebytes= filelength(fid);
     //?? fprintf(stderr,"\n myopen, filebytes=%lu",filebytes);
     if (fid==-1 || filelength==0){
        file_error(filename);
	close(fid);
	free(buf); 
	is[0]='q'; //file not found
	moveto(tempx,tempy);
	return(0);
     }
    
     //check the file size, if different realloc
     if (filebytes!=buffreq){
       //?? fprintf(stderr,"\nfilebytes=%lu != buffreq=%lu",filebytes,buffreq);
	   sprintf(textb[0],"filebytes=%lu != buffreq=%lu, realloc failed",
	                                  filebytes,buffreq);
	   if ((buf=(unsigned char*)
		realloc(buf,filebytes*sizeof(unsigned char)))
					==NULL) outof_memory(textb[0]);
     }

     /*first check value range in first byte for all types*/
     vret=read(fid,buf,filebytes);/*read all*/

     /*if(1){ //test the file (for Ed)
	     int zzz;
              fprintf(stderr,"\nfilebytes=%lu\n",filebytes); //??
              for (zzz=0;zzz<=filebytes-1;zzz++) {
		fprintf(stderr,"%02X ",buf[zzz]);
              }
           
     }*/

     bigLfile=0;
     if (buf[0]>=128){ /*high bit=1 indicates lineL>65535*/         
         bigLfile=1;
         //?? fprintf(stderr,"\n initial loading buf[0]=%d bigLfile=%d\n",buf[0],bigLfile);
         buf[0]-=128;
     } 
     //?? fprintf(stderr,"\n buf[0]=%d bigLfile=%d",buf[0],bigLfile);
 
     this_value_range=buf[0];
     if (buf[0]==0) this_value_range=2; /*new to old ok*/
     /*if wiring-only scheme missmatch of value_range doesnt matter*/
     if (wrstype==1) this_value_range=value_range;
     
     /*warn if values not equal -- can still load*/
     else if (wrstype=='s' && this_value_range!=value_range){
          draw_prompt_box(1);          
	  sprintf(textb[0],
           "file-v(%d) != base-v(%d), abort-q, load anyway-ret:",
					    this_value_range,value_range);
          outtext(textb[0]);
          input_string(1,0);
          if (is[0]=='q'){ 
              free(buf);
	      close(fid);
	      moveto(tempx,tempy);
	      return(-1);
          }
     }
     else if (this_value_range!=value_range){ /*abort if dont match, unless wiring only*/
          free(buf);
	  close(fid);
          draw_prompt_box(1);          
	  sprintf(textb[0],
           "file-v(%d) != base-v(%d), can't load, cont-ret:",
					    this_value_range, value_range);
          outtext(textb[0]);
          input_string(1,0); 
	  moveto(tempx,tempy);
	  return(-1);
     }
     /*note: for rules multi->binary ok, binary->multi no good*/
     /*convert new to old*/

     /*initial lead_bytes for loading depends on file (for saving will depend on network*/
     //?? fprintf(stderr,"\n check lead bytes wrstype=%c bigLfile=%d\n",wrstype,bigLfile);
     if (wrstype==0) lead_bytes=2; /*single rule*/
     else if (wrstype=='s' || wrstype=='x') { /*seed*/
       if  (bigLfile==0) lead_bytes=5;
       else lead_bytes=9;
     }
     else{ /*wrstype 1,2,3 wiring/rulemix*/
        if (bigLfile==0) lead_bytes=6; /* wire not connected=Max_ushort=65535*/   
        else lead_bytes=10; /*bigLfile=1, lineL>=Max_ushort, wire not connected=Maxu=4294967295*/
     }

     //?? fprintf(stderr,"\n initial bytes=%d bigLfile=%d\n",lead_bytes,bigLfile);
     //for (z=0;z<=lead_bytes-1;z++){
     //	fprintf(stderr,"buf[%d]=%d ",z,buf[z]);
     //} 
   
     if (buf[0]>=2){/*shift whole buf left by 1, to avoid changing code*/       
       //memmove(buf,buf+1,filebytes-1);
        memmove(buf,buf+1,filebytes-1);
        filebytes-=1;
        lead_bytes-=1; 
        //?? fprintf(stderr,"\n shifting buf, buf[0]=%d filebytes=%lu", buf[0],filebytes);
     }
     //?? else fprintf(stderr,"\n buf not shifted");

     //?? fprintf(stderr,"\nshifted lead_bytes=%d bigLfile=%d\n",lead_bytes,bigLfile);
     // for (z=0;z<=lead_bytes-1;z++){
     //	fprintf(stderr,"buf[%d]=%d ",z,buf[z]);
     //}  

     //?? fprintf(stderr,"\n loading: bigLfile=%d",bigLfile);
     /*load seed-------------------------------------------------------*/
     if (wrstype=='s'){
       char this_value_bits,file_dim=0, base_dim, central_h3d=0;
       signed int file_value;

       /*get file value, reduce it if greater than base-value*/
#      define load_values {\
	      file_value=get_unsigned_value(buf+lead_bytes,z,this_value_bits);\
              if (file_value>value_range-1) file_value=value_range-1;\
	      set_value(wrsbuf,poss,file_value);\
	}

        if (this_value_range==2) this_value_bits=1;
        else if (this_value_range<=4) this_value_bits=2; /* 3 or 4 */
        else if (this_value_range<=8) this_value_bits=3; /* 5 to 8 */

        /*vret=read(fid,buf,4);*/
        if (bigLfile==0){ 
           /*lineL<=65535, changed to short, int was for bigbuf only, Jan 2016*/
	   thislineL=buf[0]+(((unsigned short)buf[1])<<8);
	   /*no of bytes required to contain thislineL bits*/
           thisbytesL=(signed short)ceil(((double)(this_value_bits*lineL))/8);
	   thisi2d=(signed short) buf[2];
	   thisj2d=(signed short) buf[3];
        }
        else{ 
	   thislineL=0;
	   thislineL=buf[0];
	   thislineL=(thislineL << 8)+buf[1];
	   thislineL=(thislineL << 8)+buf[2];
           thislineL=(thislineL << 8)+buf[3];
          /*no of bytes required to contain thislineL bits*/
           thisbytesL=(signed int)ceil(((double)(this_value_bits*lineL))/8);
           
           //fprintf(stderr,"\nbigLfile=%d thislineL=%u thisbytesL=%u",
	                           //bigLfile,thislineL,thisbytesL);
           thisi2d=buf[4]+(((signed int)buf[5])<<8);

           //fprintf(stderr,"\nbuf[4]=%d buf[5]=%d",buf[4],buf[5]);

           thisj2d=buf[6]+(((signed int)buf[7])<<8);
            
           //fprintf(stderr,"\nbuf[6]=%d buf[7]=%d",buf[6],buf[7]);
           //fprintf(stderr,"\n thisi2d=%u thisj2d=%u",thisi2d,thisj2d);
        }

        if (thisi2d>0 && thisj2d>0){
           thish3d=thislineL/(thisi2d*thisj2d);
           /*thish3d could=1 from this point indicating a 2d seed file*/

           if (thish3d>=2) threed_file=1;         
           else twod_file=1; /*flat 3d becomes 2d*/
        }
        else oned_file=1;

        if (threed) base_dim=3;
        else if (twod) base_dim=2;
        else if (oned) base_dim=1;

        if (threed_file==1) file_dim=3;
        else if (twod_file==1) file_dim=2;
        else if (oned_file==1) file_dim=1;

        if (oned==1 && (oned_file==2 || oned_file==3)) oned_file=1; 
                 /*to load 2d picture -> 1d, as in encryption
                    if 3d to load something ?-> 1d*/        

        /*to load smaller file dimension into higher base dimension,
          increase file dimension*/
        if (threed){                
                if (twod_file==1){ /*2d can be loaded if i3d>=thisi2d && j3d>=thisj2d*/
                   twod_file=0;
                   threed_file=1;  /*convert to threed_file*/
                   thish3d=1;
                }                
                else if (oned_file==1){ /*1d can be loaded if i3d>=thislineL*/
                       oned_file=0;
                       threed_file=1;  /*convert to threed_file*/
                       thisi2d=thislineL;
                       thisj2d=1;
                       thish3d=1;		
                }   
        }
        else if (twod){
                 if (file_dim==3){ /*3d -> 2d*/
                   central_h3d=thish3d/2; /*load central slice only*/
                   //thish3d=1;
                }                 
                 if (oned_file==1){ /*1d can also be loaded if i2d>=lineL*/
                       oned_file=0;
                       twod_file=1; /*convert to twod_file*/
                       thisi2d=thislineL;
                       thisj2d=1;
		 } 
        }

        /*load smaller seed file into larger or equal network base,
          (dims are now equal -- if not smaller file dimension were adapted to bigger base above,
          by adding co-ords of value 1) if co-ords fit [i,j,h] inside base.*/

        /*fprintf(stderr,"\n%d:%d, %d)%d:%d, %d)%d:%d %d:%d, %d)%d:%d %d:%d %d:%d",
		file_dim,base_dim, oned_file,lineL,thislineL,
		twod_file,i2d,thisi2d,j2d,thisj2d,
                threed_file,i3d,thisi2d,j3d,thisj2d,h3d,thish3d);*/

	if (file_dim<=base_dim &&
             ((oned_file==1 && lineL>=thislineL) ||
             (twod_file==1 && i2d>=thisi2d && j2d>=thisj2d) ||
             (threed_file==1 && i3d>=thisi2d && 
	      j3d>=thisj2d && h3d>=thish3d)) ){
    
            char abort_loc;

            if (threed){ /*threed base network*/
                unsigned int *poss3d;                
		/*put smaller 3d file pattern somewhere on larger 3d grid*/
		/*default centre*/      
                if ((poss3d=(unsigned int *)
                        calloc(3,sizeof(unsigned int)))
				   ==NULL) outof_memory("(poss3d");
                abort_loc=locate_small_net(3,poss3d,thislineL,thisi2d,thisj2d,thish3d);
                ii=poss3d[0];
		jj=poss3d[1];
                hh=poss3d[2];
                free(poss3d);
                if (abort_loc==-1){ 
                   free(buf);
	           close(fid);
                   erase_prompt_box(2);
	           moveto(tempx,tempy);
	           return(-1);
	        }
		for (z=0;z<=thislineL-1;z++){
                   thisii=z%thisi2d;
	           thisjj=z%(thisi2d*thisj2d)/thisi2d;
                   thishh=z/(thisi2d*thisj2d);
                   poss=(i3d*j3d*(hh+thishh))+(i3d*(jj+thisjj))+(ii+thisii);
                   load_values;
		}
	    }

	    else if (twod){ /*twod base network*/
                unsigned int *poss3d;
                signed int extra_lineL;
	
		 /*put smaller 2d file pattern somewhere
		   on larger grid, default centre*/             
                 if ((poss3d=(unsigned int *)
                        calloc(3,sizeof(unsigned int)))
				   ==NULL) outof_memory("(poss3d");
                 abort_loc=locate_small_net(2,poss3d,thislineL,thisi2d,thisj2d,0);
                 ii=poss3d[0];
		 jj=poss3d[1];
                 free(poss3d);
                 if (abort_loc==-1){ 
                   free(buf);
	           close(fid);
                   erase_prompt_box(2);
	           moveto(tempx,tempy);
	           return(-1);
	         }

                 /*if thislineL does not fill rectangle (showbits_1d_as_2d)
                   fill from the top left so pattern is the same*/
                 extra_lineL=thisi2d*thisj2d - thislineL; /* =0 if full rectangle*/
                 //?? fprintf(stderr,"\n %dx%d-%d=extra_lineL=%d",
		 //             thisi2d,thisj2d,thislineL,extra_lineL);*/
		 for (z=0;z<=thislineL-1;z++){              
                   thisii=(z+extra_lineL) % thisi2d;
                   thisjj=(z+extra_lineL) / thisi2d;
                   poss=i2d*(jj+thisjj) + (ii+thisii);
                   load_values;                   
		}
	    }
        
	    else if (oned){ /*oned base network*/      
               unsigned int *poss3d;
	       /*put smaller 1d file pattern somewhere on larger grid*/
	       /*default centre*/
               starti=0;
	       if (lineL>thislineL){
                   if ((poss3d=(unsigned int *)
                        calloc(3,sizeof(unsigned int)))
				   ==NULL) outof_memory("(poss3d");
                   abort_loc=locate_small_net(1,poss3d,thislineL,thislineL,0,0);
                   starti=poss3d[0];
                   free(poss3d);
                   if (abort_loc==-1){ 
                      free(buf);
	              close(fid);
                      erase_prompt_box(2);
	              moveto(tempx,tempy);
	              return(-1);
	           }
		   for (z=0;z<=thislineL-1;z++){
		      poss=starti+z;
                      load_values;
		   }
	       }
	       
	       else{ /*for equal size copy buf*/
		  if (value_bits==this_value_bits){
		     memmove(wrsbuf,buf+4,bytesL);
		  }
                  else{
                     for (z=0;z<=thislineL-1;z++){
                        poss=z;
                        load_values;
                     }
		  }
	       }
	    }
	}

	else{  /*file bigger: on one or more axes,
                or if dimension bigger (3d->2d)*/
	  char abort_loc;

	  if ((threed || twod) && file_dim==1){ /*just start at 0 and fill up*/
	      abort_loc=locate_big_net(base_dim,file_dim,thislineL,thisi2d,thisj2d,thish3d);
                   if (abort_loc==-1){ 
                      free(buf);
	              close(fid);
                      erase_prompt_box(2);
	              moveto(tempx,tempy);
	              return(-1);
	           }
	           for (z=0;z<=lineL-1;z++){ /*skips if thislineL > lineL*/
                     poss=z;
                     load_values;
                  }
	    }

	   else if (threed){
	     signed int zi,zj,zh,xi,xj,xh,fi,fj,fh;
              signed int filepos,basepos;
      
                /*any file-axis: center file on base, or abort*/             
                abort_loc=locate_big_net(3,file_dim,thislineL,thisi2d,thisj2d,thish3d);
                if (abort_loc==-1){ 
                   free(buf);
	           close(fid);
                   erase_prompt_box(2);
	           moveto(tempx,tempy);
	           return(-1);
	        }
                /*any file-axis: base-axis, center file on base, or abort*/
		
                xi=(thisi2d-i3d)/2;		
                xj=(thisj2d-j3d)/2;
                xh=(thish3d-h3d)/2;

                //fprintf(stderr,"\nxi=%d xj=%d xh=%d",xi,xj,xh);
                fi=fj=fh=-1;
                for (zi=xi;zi<=xi+i3d-1;zi++){
		   if (zi>=0) fi++;
                   fj=-1;
		   if (thisi2d<i3d && (zi<0 || fi>(thisi2d-1))) continue;
		   for (zj=xj;zj<=xj+j3d-1;zj++){
                      if (zj>=0) fj++;
                      fh=-1;
                      if (thisj2d<j3d && (zj<0 || fj>(thisj2d-1))) continue;
                      for (zh=xh;zh<=xh+h3d-1;zh++){
                         if (zh>=0) fh++;
		         if (thish3d<h3d && (zh<0 || fh>(thish3d-1))) continue;
                         /*fprintf(stderr,"\nfile:%d,%d,%d base:%d,%d,%d",
			                     zi,zj,zh,zi-xi,zj-xj,zh-xh);*/
                         filepos=(thisi2d*thisj2d*zh) + (thisi2d*zj) + (zi);
                         file_value=get_unsigned_value(
                                   buf+lead_bytes,filepos,this_value_bits);
                         if (file_value>value_range-1) file_value=value_range-1;
                         basepos=(i3d*j3d*(zh-xh)) + (i3d*(zj-xj)) + (zi-xi);
                         set_value(wrsbuf,basepos,file_value);
                      }
                   }
                }
	    }
	    else if (twod){
	       signed int zi,zj,xi,xj,fi,fj;
               signed int zz,filepos,basepos;

	         abort_loc=locate_big_net(2,file_dim,thislineL,thisi2d,thisj2d,thish3d);
                 if (abort_loc==-1){ 
                   free(buf);
	           close(fid);
                   erase_prompt_box(2);
	           moveto(tempx,tempy);
	           return(-1);
	         }
		/*any file-axis: base-axis, center file on base, or abort*/
		
                xi=(thisi2d-i2d)/2;		
                xj=(thisj2d-j2d)/2;
                //fprintf(stderr,"\nthisi2d=%d thisj2d=%d",thisi2d,thisj2d);
                //fprintf(stderr,"\ni2d=%d j2d=%d",i2d,j2d);
                //fprintf(stderr,"\nxi=%d xj=%d",xi,xj);
		//fprintf(stderr,"\nfile_dim=%d central_h3d=%d",file_dim,central_h3d);
 
                fi=fj=-1;
                for (zi=xi;zi<=xi+i2d-1;zi++){
		   if (zi>=0) fi++;
                   fj=-1;
		   if (thisi2d<i2d && (zi<0 || fi>(thisi2d-1))){
		     //fprintf(stderr,"\nzi=%d fi=%d",zi,fi); 
                          continue;
                   }
                   //else fprintf(stderr,"\n>>zi=%d fi=%d",zi,fi);
		   for (zj=xj;zj<=xj+j2d-1;zj++){
		      if (zj>=0) fj++;
		      if (thisj2d<j2d && (zj<0 || fj>(thisj2d-1))){
			   //fprintf(stderr,"\nzj=%d fj=%d",zj,fj); 
                           continue;
                      }
                      //fprintf(stderr,"\nfile:%d,%d base:%d,%d",zi,zj, zi-xi,zj-xj);
                     
                      if (file_dim==3) /*load 3d central slice only*/ 
                              filepos=(thisi2d*thisj2d*central_h3d) + (thisi2d*zj) + (zi);
		      else filepos=zi + thisi2d*zj;

                      file_value=get_unsigned_value(buf+lead_bytes,filepos,this_value_bits);
                      if (file_value>value_range-1) file_value=value_range-1;
                      basepos=(zi-xi) + i2d*(zj-xj);
                      set_value(wrsbuf,basepos,file_value);
                   }
                }
	    }            
	    else if (oned){ /*just start at 0*/
	      abort_loc=locate_big_net(1,file_dim,thislineL,thisi2d,thisj2d,thish3d);
                   if (abort_loc==-1){ 
                      free(buf);
	              close(fid);
                      erase_prompt_box(2);
	              moveto(tempx,tempy);
	              return(-1);
	           }
	           for (z=0;z<=lineL-1;z++){ /*skips if thislineL > lineL*/
                     poss=z;
                     load_values;
                  }
	    }
	}
	buf0nhood=buf[0];
     } /*end of ... if (wrstype=='s')*/

     /*load anything except seed:-------------------------------------*/ 
     /*wrstype: single rule=0,
                wiring only=1,rulescheme only=2,wiring-rule scheme=3*/
     else{
        char file_kmix=0;

	/*vret=read(fid,buf,1);*/ 
        /*(now) first byte gives nhood size, read into buf*/
        if (buf[0]>=128){ /*for a k-mix highest bit set to 1*/
            buf[0]-=128;
            file_kmix=1;
        }
	buf0nhood=buf[0];
	/*load single rule------------------------------------------------*/
	if (wrstype==0){
	     /*a single rule can only be loaded into 
                 a rulemix or single rule if ks are equal*/
           if (nhood!=buf0nhood){
		  free(buf);
		  close(fid);
		  moveto(tempx,tempy);
		  return(buf0nhood); /*error shown in capara*/ 
	   }
	   
	   /*single rule: read correct no of bytes into buf*/
           if (totalistic==0){ 
              tablemax=(signed int)pow(value_range,
                        (double)nhood)-1;/*max index of ruletable*/
              rulebytes=(signed int)ceil(value_bits * (double)(tablemax+1)/8);
           }
	   else if (totalistic==1){   
              tablemax=nhood*(value_range-1); /*max index of codetable*/
              rulebytes=(signed int) ceil(value_bits * 
                      (double)(tablemax+1)/8);/*bytes for code, min=1*/
           }              
           else if (totalistic==2){ 
              tablemax=v_tablecodemax[nhood];
              rulebytes=(signed int) /*bytes for v_code, min=1*/
                      ceil(value_bits * (double)(tablemax+1)/8);
           }

           //memmove(wrsbuf,buf+1,rulebytes); /*this is all that is needed ??*/
           memmove(wrsbuf,buf+1,rulebytes); /*this is all that is needed ??*/


           /*if(1){ //show the rule (for Ed)
	     int zzz;

              fprintf(stderr,"\nrulebytes=%d\n",rulebytes); //??
              for (zzz=0;zzz<=rulebytes-1;zzz++) {
		fprintf(stderr,"%02X ",wrsbuf[zzz]);
              }

              fprintf(stderr,"\ntablemax=%d\n",tablemax); //??
              for (zzz=tablemax;zzz>=0;zzz--){
	         fprintf(stderr,"%d",get_value(wrsbuf,zzz));
              }
	   }*/
	}

        /*-----------------------------------------------------*/
        /*load (except seed,='s' or single rule,=0) --------------------*/ 
        /*wrstype: wiring only=1,rulescheme only=2,wiring-rule scheme=3*/
	else{
	   char abort_loc=0;
           char abort_load=0;
           char threed_file=0,twod_file=0,oned_file=0;
           signed int tablemax_file,rulebytes_file;
           
	   /*vret=read(fid,buf+1,4);*/
           if (bigLfile==0){ /*lineL<=65535*/
	      thislineL=buf[1]+(((unsigned int)buf[2])<<8);
           }
	   else{ /*bigLfile==1*/ 
              thislineL=0;
	      thislineL=buf[1];
	      thislineL=(thislineL << 8)+buf[2];
	      thislineL=(thislineL << 8)+buf[3];
              thislineL=(thislineL << 8)+buf[4];
           }
	   if (thislineL<255) bytes_thislineL=1;
           else if (thislineL<65535) bytes_thislineL=2;
           else bytes_thislineL=4; /**bigLfile==1 if lineL>=Max_ushort, 65535*/          

           if (bigLfile==0){ /*lineL<=65535*/
	      thisi2d=(signed int) buf[3];
	      thisj2d=(signed int) buf[4];
           }
           else{
              thisi2d=buf[5]+(((signed int)buf[6])<<8);
              //?? fprintf(stderr,"\nbuf[5]=%d buf[6]=%d",buf[5],buf[6]);
              thisj2d=buf[7]+(((signed int)buf[8])<<8);
              //?? fprintf(stderr,"\nbuf[7]=%d buf[8]=%d",buf[6],buf[7]);
              //?? fprintf(stderr,"\n thisi2d=%u thisj2d=%u",thisi2d,thisj2d);
           }
 
           if (thisi2d>0 && thisj2d>0){
              thish3d=thislineL/(thisi2d*thisj2d);
              if (thish3d>1) threed_file=1;
              else twod_file=1;
           }
           else oned_file=1;

           //?? fprintf(stderr,
           //"\n bigLfile=%d thislineL=%u bytes_thislineL=%u thisi2d=%u thisj2d=%u thish3d=%u",
	   //	   bigLfile,thislineL,bytes_thislineL,thisi2d,thisj2d,thish3d);	   
           
           /*filenetsize<=netsize*/ 
           if (thislineL>lineL && (wrstype==1 || wrstype==3)){ 
              free(buf);
	      close(fid);
              draw_prompt_box(1); 
              sprintf(textb[0],
	       "file-n(%d) > base-n(%d), can't load, cont-ret:",
					     thislineL,lineL );
              outtext(textb[0]);    
              input_string(1,0);	
	      moveto(tempx,tempy);
	      erase_prompt_box(1);
	      return(-1);
	   }
           /*if dimensions dont match - convert file to match base dimensions*/
           /*threed base*/
           if (threed){   
              /*twod_file: if it fits in, convert to three_file*/
              if (twod_file==1 && i3d>=thisi2d && j3d>=thisj2d){
                   twod_file=0;
                   threed_file=1;
                   thish3d=1;
	      }
              /*oned_file: if it fits in, lineL<=i3d convert to three_file*/ 
              else if (oned_file==1 && i3d>=thislineL){
                   oned_file=0;
                   threed_file=1;
                   thisi2d=thislineL;
                   thisj2d=1;
                   thish3d=1;
              }
           }
           else if (twod){
              /*oned_file: if it fills in, lineL<=i3d convert to twod_file*/ 
	      if (oned_file==1 && i2d>=thislineL){
                   oned_file=0;
                   twod_file=1;  /*convert to twod_file*/
                   thisi2d=thislineL;
                   thisj2d=1;
              }
           }
	   /*file max-k can be smaller or equal to base net max-k (not bigger)
                 size can not be bigger, can be smaller, n 1d, i and j 2d*/
	   if (wrstype!=2 && (  
		   (oned_file && (thislineL>lineL)) 
                || (twod && (thisi2d>i2d || thisj2d>j2d)) 
                || ((twod_file || threed_file) && 
                      threed && (thisi2d>i3d || thisj2d>j3d || thish3d>h3d)) )){
               abort_load=1;
               draw_prompt_box(1); 
              
	       if (thislineL>lineL)
		       sprintf(textb[0],"file-n(%d) >  base-n(%d), can't load, cont-ret:",
                                                 thislineL,lineL);
               else{
                  if ((twod || threed) && thisi2d>i2d)
                       sprintf(textb[0],"file-i(%d) >  base-i(%d), load anyway-l, abort-ret:",
                                                 thisi2d,i2d);
                  else if ((twod || threed) && thisj2d>j2d)
                       sprintf(textb[0],"file-j(%d) > base-j(%d), load anyway-l, abort-ret:",
                                                 thisj2d,j2d); 
                  else if (threed && thish3d>h3d)
                       sprintf(textb[0],"file-h(%d) > base-h(%d), load anyway-l, abort-ret:",
                                                 thish3d,h3d);
	          outtext(textb[0]);
                  input_string(1,0);
                  if (is[0]=='l') abort_load=0;
               }
	   }

           /*to allow start of large rulemix to be loaded on small rulemix*/
	   if (wrstype==2 && thislineL>lineL) thislineL=lineL;

           if (buf0nhood>nhood){
	      abort_load=1;
	      draw_prompt_box(1);          
	      sprintf(textb[0],
	       "file-kmax(%d) > base-kmax(%d), can't load, cont-ret:",
					      buf0nhood,nhood);	      
              outtext(textb[0]);                    
           }
           /*loading rules-only: allowed for <k-hom and rule-mix>:
             if kmix-file, or if file-k < base-k
             both are risky -- kmix-file or k-hom-file must match k-hom base*/
           if (wrstype==2 && (file_kmix==1 || buf0nhood<nhood)){
              abort_load=1;              
              draw_prompt_box(1);
             if (file_kmix==1) sprintf(textb[0],
		"rulemix-only: loading kmix-file is risky, load anyway-l, abort-ret:");
             else if (buf0nhood<nhood) sprintf(textb[0],
		"rulemix-only: loading file-k(%d) < base-k(%d) is crazy, load anyway-l, abort-ret:",
					      buf0nhood,nhood);	      
              outtext(textb[0]);
              input_string(1,0);
              if (is[0]=='l') abort_load=0;                    
           }

           /*if rulemix==0 memory is assigned only for network cell[0]
             so if rules were set, can't accept a file_kmix (need rulemix
                                       or a file where file_k !=  base_k*/
           if (rules_set && rulemix==0 && (file_kmix==1 || buf0nhood!=nhood)){
              abort_load=1;
	      draw_prompt_box(1);          
	      sprintf(textb[0],
	      "base net has no rulemix, file has mixed-k, can't load, cont-ret:");
              outtext(textb[0]);                    
           } 

           if (abort_load==1){
	         free(buf);
		 close(fid);
		 input_string(1,0);
		 moveto(tempx,tempy);
		 erase_prompt_box(1);
		 return(-1);
	   }

             if (file_kmix==1 && nhood_mixed==0) nhood_mixed=1;
	     if (tot_only==0){
                 tablemax_file= (signed int)pow(value_range,(double)buf0nhood)-1;
                 rulebytes_file=(signed int)ceil(value_bits * 
                 (double)(tablemax_file+1)/8);
             }
             else{
                 if (totalistic==1){
                    tablemax_file=buf0nhood*(value_range-1); /*max index of codetable*/
                    rulebytes_file=(signed int) ceil(value_bits * 
                             (double)(tablemax_file+1)/8);/*bytes for code, min=1*/
                 }
                 else if (totalistic==2){        
                    tablemax_file=v_tablecodemax[buf0nhood];
                    rulebytes_file=(signed int) /*bytes for v_code, min=1*/
                    ceil(value_bits * (double)(tablemax_file+1)/8);
                 }
             }
	     
	     buffindex=lead_bytes;

             /*for 3d, put same or smaller 3d file somewhere on larger 3d network*/
	     if (lineL>=thislineL && threed && threed_file==1 && 
                           i3d>=thisi2d && j3d>=thisj2d && h3d>=thish3d){
                 unsigned int *poss3d;
 
		 /*put smaller 3d file rule/wiring scheme somewhere
		   on larger grid, default centre*/
                 if ((poss3d=(unsigned int *)
                        calloc(3,sizeof(unsigned int)))
				   ==NULL) outof_memory("(poss3d");
                 abort_loc=locate_small_net(3,poss3d,thislineL,thisi2d,thisj2d,thish3d);
                 ii=poss3d[0];
		 jj=poss3d[1];
                 hh=poss3d[2];
                 free(poss3d);
                 if (abort_loc==-1){ 
                   free(buf);
	           close(fid);
                   erase_prompt_box(2);
	           moveto(tempx,tempy);
	           return(-1);
	        }
		 for (z=0;z<=thislineL-1;z++){
                    thisii=z%thisi2d;
	            thisjj=z%(thisi2d*thisj2d)/thisi2d;
                    thishh=z/(thisi2d*thisj2d);
                    poss=(i3d*j3d*(hh+thishh))+(i3d*(jj+thisjj))+(ii+thisii);  

		    if (wrstype==2 || wrstype==3){
                       if (tot_only==0) memmove(carule[poss],
                                          buf+buffindex,rulebytes_file);
                       else{
                           if (totalistic==1)
                                memmove(cacode[poss],buf+buffindex,rulebytes_file);
                           if (totalistic==2)
                                memmove(v_code[poss],buf+buffindex,rulebytes_file);
                       }
		       buffindex+=rulebytes_file;
		    }
		    if (wrstype==1 || wrstype==3){
                       k_changed=notwired=0;
		       for (wire=0;wire<=buf0nhood-1;wire++){
			 if (notwired==0 /*&& wire<=buf0nhood-1*/){ 
			     if (bytes_thislineL==1){ 
			        wiringposs=buf[buffindex];
                                if (wiringposs==255) notwired=1;
                             }
			     else if (bytes_thislineL==2){
			         wiringposs=buf[buffindex]+
				   (((unsigned int)buf[buffindex+1])<<8);
                                 if (wiringposs==Max_ushort) notwired=1;/*was Maxu*/
			     }
                             else if (bytes_thislineL==4){
                                 wiringposs=0;
	                         wiringposs=buf[buffindex];
	                         wiringposs=(wiringposs << 8)+buf[buffindex+1];
                                 wiringposs=(wiringposs << 8)+buf[buffindex+2];
                                 wiringposs=(wiringposs << 8)+buf[buffindex+3];
                                 if (wiringposs==Maxu) notwired=1;
			     }
		         }
                         if (notwired==1 &&  k_changed==0){ 
                              this_k=wire; /*if k-mix note actual k*/
                              k_changed=1;
                         } 
                         if (notwired==1) wiring[poss][wire]=Maxu;
                         else{
                             thisii=wiringposs%thisi2d;
			     thisjj=wiringposs%(thisi2d*thisj2d)/thisi2d;
			     thishh=wiringposs/(thisi2d*thisj2d);
                             wiringposs=(i3d*j3d*(hh+thishh)) + 
                                  (i3d*(jj+thisjj)) + (ii+thisii); 

			     wiring[poss][wire]=wiringposs;
                             //?? fprintf(stderr,"%d ",wiring[poss][wire]);
                         }
			 buffindex+=bytes_thislineL;
                         if (nhood>=buf0nhood && wire==buf0nhood-1){
                             if  (k_changed==0)
                                     nhoodm[poss]=buf0nhood; 
                             for (wire1=buf0nhood;wire1<=nhood-1;wire1++){
                               wiring[poss][wire1]=Maxu;
                             }
                         }
		       }
                       if (k_changed==1) nhoodm[poss]=this_k;
		    }
		 }
                 if ((wrstype==1 || wrstype==3) && nhood_mixed) cell_out_freq();
	      }
	      /*for 2d, put small 2d file somewhere on larger 2d network*/
	      else if (lineL>=thislineL && twod && twod_file==1 && 
                               i2d>=thisi2d && j2d>=thisj2d){
                unsigned int *poss3d;
                 
		 /*put smaller 2d file rule/wiring scheme somewhere
		   on larger grid, default centre*/
                 if ((poss3d=(unsigned int *)
                        calloc(3,sizeof(unsigned int)))
				   ==NULL) outof_memory("(poss3d");
                 abort_loc=locate_small_net(2,poss3d,thislineL,thisi2d,thisj2d,0);
                 ii=poss3d[0];
		 jj=poss3d[1];          
                 free(poss3d);
                 if (abort_loc==-1){ 
                   free(buf);
	           close(fid);
                   erase_prompt_box(2);
	           moveto(tempx,tempy);
	           return(-1);
	         }
		 for (z=0;z<=thislineL-1;z++){
                    thisii=z%thisi2d;
                    thisjj=z/thisi2d;
                    poss=i2d*(jj+thisjj) + (ii+thisii);

		    if (wrstype==2 || wrstype==3){ /*RULE SCHEME ONLY or WIRING+RULE SCHEME*/
		       if (tot_only==0) memmove(carule[poss],buf+buffindex,rulebytes_file);
                       else{
                           if (totalistic==1)
                                memmove(cacode[poss],buf+buffindex,rulebytes_file);
                           if (totalistic==2)
                                memmove(v_code[poss],buf+buffindex,rulebytes_file);
                       }
		       buffindex+=rulebytes_file;
		    }
		    if (wrstype==1 || wrstype==3){ /*WIRING ONLY or WIRING+RULE SCHEME*/
                       k_changed=notwired=0;
		       for (wire=0;wire<=buf0nhood-1;wire++){
                          if (notwired==0 && wire<=buf0nhood-1){ 
			     if (bytes_thislineL==1){ 
			        wiringposs=buf[buffindex];
                                if (wiringposs==255) notwired=1;
                             }
			     else if (bytes_thislineL==2){
			         wiringposs=buf[buffindex]+
				   (((unsigned int)buf[buffindex+1])<<8);
                                 if (wiringposs==Max_ushort) notwired=1;/*was Maxu*/
			     }
                             else if (bytes_thislineL==4){
                                 wiringposs=0;
	                         wiringposs=buf[buffindex];
	                         wiringposs=(wiringposs << 8)+buf[buffindex+1];
                                 wiringposs=(wiringposs << 8)+buf[buffindex+2];
                                 wiringposs=(wiringposs << 8)+buf[buffindex+3];
                                 if (wiringposs==Maxu) notwired=1;
			     }

		          }
                          if (notwired==1 &&  k_changed==0){ 
			      this_k=wire; /*if k-mix note actual k*/
                              //?? fprintf(stderr,"-%d ",this_k);
                              k_changed=1;
                          }
                          if (notwired==1) wiring[poss][wire]=Maxu;
                          else{
			     thisii=wiringposs%thisi2d;
			     thisjj=wiringposs/thisi2d;
			     wiringposs=(i2d*(jj+thisjj)) + (ii+thisii);
			     wiring[poss][wire]=wiringposs;
                          }
			  buffindex+=bytes_thislineL;
                          /*set remainder of wiring to Maxu*/
                          if (nhood>=buf0nhood && wire==buf0nhood-1){
                             if  (k_changed==0)
                                     nhoodm[poss]=buf0nhood; 
                             for (wire1=buf0nhood;wire1<=nhood-1;wire1++){
                               wiring[poss][wire1]=Maxu;
                             }
                          }
		       }
                       if (k_changed==1) nhoodm[poss]=this_k;
		    }
		    
		 }
                 if ((wrstype==1 || wrstype==3) && nhood_mixed) cell_out_freq();
	      }
	      else{  /*1d file or 3d/2d that don't fit or high dim into lower*/	 
                 unsigned int *poss3d; 
                  
		 /*put smaller 1d file rule/wiring scheme somewhere
		   on larger line, default centre*/
                 starti=0;
		 if (lineL>=thislineL){
                    if ((poss3d=(unsigned int *)
                        calloc(3,sizeof(unsigned int)))
				   ==NULL) outof_memory("(poss3d");
                    abort_loc=locate_small_net(1,poss3d,thislineL,thislineL,0,0);
                    starti=poss3d[0];
                    free(poss3d);
                    if (abort_loc==-1){ 
                       free(buf);
	               close(fid);
                       erase_prompt_box(2);
	               moveto(tempx,tempy);
	               return(-1);
	            }
		 } 
		 for (poss=0;poss<=thislineL-1;poss++){
		    if (wrstype==2 || wrstype==3){
		       if (tot_only==0) 
                           memmove(carule[poss+starti],buf+buffindex,rulebytes_file);
                       else{
                          if (totalistic==1)
                             memmove(cacode[poss+starti],buf+buffindex,rulebytes_file);
                          else if (totalistic==2)
                             memmove(v_code[poss+starti],buf+buffindex,rulebytes_file);
                       }
		       buffindex+=rulebytes_file;
		    }
		    if (wrstype==1 || wrstype==3){
                       k_changed=notwired=0;
		       for (wire=0;wire<=buf0nhood-1;wire++){
                          if (notwired==0){ 
			     if (bytes_thislineL==1){ 
			        wiringposs=buf[buffindex];
                                if (wiringposs==255) notwired=1;
                             }
			     else if (bytes_thislineL==2){
			         wiringposs=buf[buffindex]+
				   (((unsigned int)buf[buffindex+1])<<8);
                                 if (wiringposs==Max_ushort) notwired=1;/*was Maxu*/
                                
			     }
                             else if (bytes_thislineL==4){
                                 wiringposs=0;
	                         wiringposs=buf[buffindex];
	                         wiringposs=(wiringposs << 8)+buf[buffindex+1];
                                 wiringposs=(wiringposs << 8)+buf[buffindex+2];
                                 wiringposs=(wiringposs << 8)+buf[buffindex+3];
                                 if (wiringposs==Maxu) notwired=1;
			     }
		          }
			  if (notwired==1 && k_changed==0){ 
                              this_k=wire; /*if k-mix note actual k*/
                              k_changed=1;
                          } 
                          if (notwired==1) wiring[poss+starti][wire]=Maxu;  
			  else wiring[poss+starti][wire]=wiringposs+starti;
			  buffindex+=bytes_thislineL;

                          if (nhood>=buf0nhood && wire==buf0nhood-1){
                             if  (k_changed==0)
                                     nhoodm[poss+starti]=buf0nhood; 
                             for (wire1=buf0nhood;wire1<=nhood-1;wire1++){
                               wiring[poss+starti][wire1]=Maxu;
                             }
                         }
		       }                       
                       if (k_changed==1) nhoodm[poss+starti]=this_k;
                    }                    
		 }
                 if ((wrstype==1 || wrstype==3) && nhood_mixed) cell_out_freq();
	     }
	}
     }
     
  }
  close(fid);
  free(buf);
  moveto(tempx,tempy); 
  /*
  foldposs=64;
  if (wrstype=='s') print_layered_bitstring(
              wrsbuf,tablemax,cellscale,cellsep,0,1);*/
  return(buf0nhood);
}

/***** for multi-state, get the value of a cell or rule table entry *****/
/*for compatibility with DOS, 
otherwise conflict between char and  unsigned char*/

signed int get_unsigned_value(unsigned char *array, 
                unsigned int ct_count, char this_value_bits){
  signed int this_value=0;
  unsigned long ct_bitcount;
  char bit0,bit1,bit2;
            ct_bitcount=this_value_bits*ct_count;
            bit0=get_bit(array,ct_bitcount);
            if (this_value_bits==1) this_value=bit0; 
            else if (this_value_bits>1){ 
                   bit1=get_bit(array,ct_bitcount+1);
                   if (this_value_bits==2) this_value=bit0 + bit1*2; 
                   else if (this_value_bits==3){
		      bit2=get_bit(array,ct_bitcount+2);
                      this_value=bit0 + bit1*2 + bit2*4; 
                   } 
            }           
            return(this_value);
}

/*** locate same or smaller 1d, 2d, 3d network in larger network, Aug98, rev Sept05**/
char locate_small_net(char dim,unsigned int *poss3d,unsigned int thislineL,
   signed int thisi2d,signed int thisj2d,signed int thish3d){ 
          
   signed int starti=0,startj=0,starth=0,
                  ti=0,tj=0,th=0;
   signed int xbox;
              if (dim==1){
                     ti=lineL;
                     starti=(ti-thisi2d)/2;
              }
              else if (dim==2){
                     ti=i2d;
                     tj=j2d;
                     starti=(ti-thisi2d)/2;
		     startj=(tj-thisj2d)/2;
              }
              else if (dim==3){
                     ti=i3d;
                     tj=j3d;
                     th=h3d;
                     starti=(ti-thisi2d)/2;
		     startj=(tj-thisj2d)/2;
                     starth=(th-thish3d)/2;
              }
              if (lineL>thislineL){   
                 get_prompt_box(6,2);
                 if (dim==3){                   
		    sprintf(textb[0],
		     "3d:i,j,h=%d,%d,%d file:i,j,h=%d,%d,%d abort-q or enter start coords",
				   ti,tj,th,thisi2d,thisj2d,thish3d);
		    sprintf(textb[1],
		     "(def %d,%d,%d max %d,%d,%d rnd-r) i:",
			    starti,startj,starth,
                                    ti-thisi2d,tj-thisj2d,th-thish3d);
                 }
                 else if (dim==2){
                    sprintf(textb[0],
		     "2d:i,j=%d,%d file:i,j=%d,%d abort-q or enter start coords",
				   ti,tj,thisi2d,thisj2d);
		    sprintf(textb[1],
		     "(default %d,%d max %d,%d rnd-r) i:",
			    starti,startj,ti-thisi2d,tj-thisj2d);
                 }
                 else if (dim==1){
                    sprintf(textb[0],
		     "1d: i=%d, file size=%d, abort-q or enter start pos",
						    ti,thisi2d);
		    sprintf(textb[1],
		     "(def %d, max %d, rnd-r):",starti,ti-thisi2d);
                 }
		 xbox=draw_prompt_box(2);
		 outtext(textb[0]);
		 moveto(xbox,gety+CHeight);
		 outtext(textb[1]);
                 if (dim==1){
                    sprintf(textb[2],"%d",lineL-thisi2d);
                    input_string(strlen(textb[2]),0);
                 }
		 else input_string(3,0);
 
                 if (is[0]=='q') goto skip;
		 else if (is[0]==13);
                 else if (is[0]=='r') starti=myrand()%(ti-thisi2d);
		 else if (atoi(is)<=ti-thisi2d && atoi(is)>-1)
						   starti=atoi(is);
                 if (dim==2 || dim==3){
		    sprintf(textb[1]," j:");
		    outtext(textb[1]);
		    sprintf(textb[2],"%d",startj);
                    input_string(3,0);

                    if (is[0]=='q') goto skip;
		    else if (is[0]==13);
                    else if (is[0]=='r') startj=myrand()%(tj-thisj2d);
		    else if (atoi(is)<=tj-thisj2d && atoi(is)>-1)
						   startj=atoi(is);
                 }
                 if (dim==3){
                    sprintf(textb[1]," h:");
		    outtext(textb[1]);
		    sprintf(textb[2],"%d",starth);
		    input_string(3,0);

                    if (is[0]=='q') goto skip;
		    else if (is[0]==13); 
                    else if (is[0]=='r') startj=myrand()%(th-thish3d);
		    else if (atoi(is)<=h3d-thish3d && atoi(is)>-1)
						   starth=atoi(is);
                 }                                  
	       skip:
                 uncover_free_prompt_box(6);
                 if (is[0]=='q') return(-1);
              }
              if (dim==1) poss3d[0]=starti;
	      else{
		    poss3d[0]=starti;
		    poss3d[1]=startj;
                    if (dim==3) poss3d[2]=starth;
              }
              /*copy file dimention, size ijh, and startpos ijh
		to global variables to show as block in net graphics*/
              file_dim=dim; /*dimension of (converted?) file array*/
              /*size of file array*/
              file_i=thisi2d;   
              file_j=thisj2d;
              file_h=thish3d;
	      /*start position in base array*/
              file_starti=starti;
              file_startj=startj;
              file_starth=starth;
              return(1);
}

/*** file-axis  >base-axis or file-dim > base-dim, Jan2016, or dim **/
char locate_big_net(char dim,char file_dim,unsigned int thislineL,
   signed int thisi2d,signed int thisj2d,signed int thish3d){ 
          
   signed int starti=0,startj=0,starth=0,
                  ti=0,tj=0,th=0;
   signed int xbox;
                  
              if (dim==1){
                     ti=lineL;
              }
              else if (dim==2){
                     ti=i2d;
                     tj=j2d;
              }
              else if (dim==3){
                     ti=i3d;
                     tj=j3d;
                     th=h3d;
	       }
               if (dim<file_dim) 
		 sprintf(textb[2],"basedim<filedim %d<%d, filedim reduced",dim,file_dim);
	       else if (dim>file_dim) 
		 sprintf(textb[2],"basedim>filedim %d>%d, filedim increased",dim,file_dim);
               else sprintf(textb[2],"basedim=filedim %d=%d",dim,file_dim);

	       if (dim==3){
		   if (ti<thisi2d || tj<thisj2d || th<thish3d)
		 	     sprintf(textb[1],"%s, coords bigger",textb[2]);
                   else sprintf(textb[1],"%s",textb[2]);
               }
	       else if (dim==2){
                   if (ti<thisi2d || tj<thisj2d)
		 	     sprintf(textb[1],"%s, coords bigger",textb[2]);
                   else sprintf(textb[1],"%s",textb[2]);
               }
               else if (dim==1){
                   if (ti<thisi2d)
		 	     sprintf(textb[1],"%s, coords bigger",textb[2]);
                   else sprintf(textb[1],"%s",textb[2]);
	       }
               

               if (dim==3){ 
	          sprintf(textb[0],
		     "3d:i,j,h=%d,%d,%d file:i,j,h=%d,%d,%d abort-q, load anyway-ret:",
				   ti,tj,th,thisi2d,thisj2d,thish3d);
               }
               else if (dim==2){
                  sprintf(textb[0],
		     "2d:i,j=%d,%d file:i,j=%d,%d abort-q, load anyway-ret:",
				   ti,tj,thisi2d,thisj2d);
               }

               else if (dim==1){
                   sprintf(textb[0],
		         "1d:i=%d, file:%d abort-q, load anyway-ret:",
						    ti,thislineL);
               }
	       xbox=draw_prompt_box(2);
               outtext(textb[1]);
               moveto(xbox,gety+CHeight);
	       outtext(textb[0]);
	       input_string(1,0);
               
               if  (is[0]=='q') return(-1);
               else return(1);	       
}

/********************* save last rule, dec 93 ********************/
void save_last_rule(char* rule,char thisnhood){
  signed int tempx,tempy,
               fid,
               rulebytes,tablemax;
  unsigned char *buf;

  tempx=getx;
  tempy=gety;
  if (totalistic==1){
     tablemax=thisnhood*(value_range-1); /*max index of codetable*/
     rulebytes=(signed int) ceil(value_bits * 
          (double)(tablemax+1)/8);/*bytes for code, min=1*/
     sprintf(filename,"%s%d%s%d%s","l_v",value_range,"k",thisnhood,".tco\0"); 
   }
  else if (totalistic==2){        
     tablemax=v_tablecodemax[thisnhood];
     rulebytes=(signed int) /*bytes for v_code, min=1*/
             ceil(value_bits * (double)(tablemax+1)/8);
     sprintf(filename,"%s%d%s%d%s","l_v",value_range,"k",thisnhood,".vco\0");
   }
   else{
     tablemax= (signed int)pow(value_range,(double)thisnhood)-1;
     rulebytes=(signed int)ceil(value_bits * (double)(tablemax+1)/8);
     sprintf(filename,"%s%d%s%d%s","l_v",value_range,"k",thisnhood,".rul\0");
   }

  /*max buffer to store bytes*/
  if ((buf=(unsigned char *)calloc(2+rulebytes,sizeof(unsigned char)))
		 ==NULL) outof_memory("buf for saving last rule");
  fid=myopen(filename,1,0);

  if (fid==-1){
        file_error(filename);
	is[0]='q';
	close(fid);
	free(buf);
	return;
  }
  buf[0]=value_range;
  buf[1]=thisnhood;
  memmove(buf+2,rule,rulebytes);
  vret=write(fid, buf, 2+rulebytes);
  close(fid);
  free(buf);
  moveto(tempx,tempy);
}

/********************* load last rule, dec 93 ********************/
char load_last_rule(char* rule,char thisnhood){
  signed int tempx,tempy,fid,rulebytesM,tablemaxM;
  unsigned char *buf,
		buf_nhood, /*nhood found in buf[1]*/
                this_value_range; /*value_range found in buf[0]*/
  tempx=getx;
  tempy=gety;

  if (totalistic==1){
        tablemaxM=thisnhood*(value_range-1); /*max index of codetable*/
        rulebytesM=(signed int) ceil(value_bits * 
          (double)(tablemaxM+1)/8);/*bytes for code, min=1*/
        sprintf(filename,"%s%d%s%d%s","l_v",value_range,"k",thisnhood,".tco");
  }
  else if (totalistic==2){ 
        tablemaxM=v_tablecodemax[thisnhood];
        rulebytesM=(signed int) /*bytes for v_code, min=1*/
             ceil(value_bits * (double)(tablemaxM+1)/8);
        sprintf(filename,"%s%d%s%d%s","l_v",value_range,"k",thisnhood,".vco");
  }
  else if (totalistic==0){
     sprintf(filename,"%s%d%s%d%s","l_v",value_range,"k",thisnhood,".rul");
     tablemaxM=(signed int)pow(value_range,(double)thisnhood)-1;
     rulebytesM=(signed int)ceil(value_bits * (double)(tablemaxM+1)/8);
  }
  //?? fprintf(stderr,"\nload-%s",filename);

  /*max buffer to store bytes, for max nhoood*/
  if ((buf=(unsigned char *)calloc(2+rulebytesM,sizeof(unsigned char)))
		 ==NULL) outof_memory("buf for loading last rule");
  fid=myopen(filename,0,0); 

  if (fid==-1){
        file_error(filename);
	is[0]='q';
	free(buf);
	close(fid);
	return(0);
  }
  
  vret=read(fid,buf,2+rulebytesM); /*first byte=v, second=k, read into buf*/
  this_value_range=buf[0]; /*v found in buf[0]*/
  buf_nhood=buf[1]; /*nhood k  found in buf[1]*/
 //??  fprintf(stderr,"buf[0]=%d buf[1]=%d",buf[0],buf[1]);
  if (this_value_range!=value_range || buf_nhood!=thisnhood){
        if (this_value_range!=value_range && buf_nhood!=thisnhood){
           sprintf(textb[0],
           "v(found)%d != v(%d) and k(found)%d != k(%d), can't load, cont-ret:",
	     this_value_range,value_range,buf_nhood,thisnhood);
        }
	else if (this_value_range!=value_range){
           sprintf(textb[0],
           "v(found)%d != v(%d), can't load, cont-ret:",
	                   this_value_range,value_range);
        }
        if ( buf_nhood!=thisnhood){
           sprintf(textb[0],
           "k(found)%d != k(%d), can't load, cont-ret:",
	                           buf_nhood,thisnhood);
        }
        outtext(textb[0]);
        input_string(1,0);
        file_error(filename);
	is[0]='q';
	free(buf);
	close(fid);
	return(0);
  }

  /*read correct no of bytes into buf*/
  /*vret=read(fid,buf+2,rulebytes);*/
  memmove(rule,buf+2,rulebytesM);
  free(buf);
  close(fid);
  if (tot_only==0){
     if (totalistic==1) 
          code2rule(carule[0],rule,thisnhood);
     else if (totalistic==2)
          v_code2rule(carule[0],rule,thisnhood,1);
  } 
  moveto(tempx,tempy);
  return(buf_nhood);
}

/*************** load/save rule or seed as an ascii file, combined Feb 2016 *************/
unsigned int load_save_ascii_rule_seed(char load_save, char rule_seed,
              char* base_buf,unsigned int base_size){
  char file_ret;
  signed int fid;
  unsigned int z,tempx,tempy,filebytes=0;
  char *ascii_buf,this_value_range; /*value_range found in buf[0]*/

  tempx=getx;
  tempy=gety;
  if (load_save=='l') sprintf(textb[4],"LOAD ");
  if (load_save=='s') sprintf(textb[4],"SAVE ");
  
  if (rule_seed=='r'){;
     sprintf(textb[3],"mytbl_v%d",value_range);
     file_ret=select_filename(textb[4],"TABLE (ascii)","*.tbl",textb[3]);
  }
  else if (rule_seed=='s'){
     sprintf(textb[3],"Aseed_v%d",value_range);
     file_ret=select_filename(textb[4],"SEED (ascii)","*.see",textb[3]);
  }

  if (file_ret=='q'){
        erase_prompt_box(1);
        moveto(tempx,tempy);
	is[0]='q';
	return(0);
  } 
  /*first byte=v, then ascii table, from base_size  to 0*/
  if ((ascii_buf=(char *)calloc(base_size+1,sizeof(char)))
		 ==NULL) outof_memory("ascii_buf to save/load ascii rule or seed");
  
  if (load_save=='l'){
    unsigned int bytes_required;

     fid=myopen(filename,0,0); 

     if (fid==-1){
        file_error(filename);
	is[0]='q';
	free(ascii_buf);
	close(fid);
        erase_prompt_box(1);
        moveto(tempx,tempy);
	return(0);
     }
  
     filebytes= filelength(fid);
     vret=read(fid,ascii_buf,1); /*first byte=v, (second=k not done), read into buf*/
     this_value_range=ascii_buf[0]-'0'; /*v found in buf[0]*/
  
     if (this_value_range!=value_range 
	    || (base_size)!=(filebytes-1)){
        if (this_value_range!=value_range){
           draw_prompt_box(1);
           sprintf(textb[0],
           "file-v(%d) != base-v(%d), abort-q, load anyway-ret:",
	        this_value_range,value_range);
           outtext(textb[0]);
           input_string(1,0);
        }
        if (is[0]!='q' && base_size != filebytes-1){
           draw_prompt_box(1);
           sprintf(textb[0],
           "file-size(%d) != base-size(%d), abort-q, load anyway-ret:",
		   filebytes-1, base_size);
           outtext(textb[0]);
           input_string(1,0);
        }
        if (is[0]=='q'){
	   free(ascii_buf);
	   close(fid);
           erase_prompt_box(1);
           moveto(tempx,tempy);
	   return(0);
        }
     }

     /*read correct no of bytes into buf*/     
     bytes_required=base_size;
     if ((filebytes)<base_size) bytes_required=filebytes-1;     
     vret=read(fid,ascii_buf+1,bytes_required);
     //fprintf(stderr,"\n");
     for (z=1;z<=bytes_required;z++){
         //fprintf(stderr,"%d ",z-1);
         set_value(base_buf,z-1,ascii_buf[z]-'0'); /*don't exceed value_range'*/ 
         if (get_value( base_buf,z-1) > value_range-1) set_value(base_buf,z-1,value_range-1);
     }
  }
  if (load_save=='s') {
      fid=myopen(filename,1,0);
      if (fid==-1){
         file_error(filename);     
         is[0]='q';
         close(fid);
         free(ascii_buf);         
         erase_prompt_box(1);
         moveto(tempx,tempy);
         return(0);
      }
      ascii_buf[0]=value_range;
      sprintf(ascii_buf,"%d",value_range);
      //fprintf(stderr,"\n%d: ",value_range);
      for (z=1;z<=base_size;z++){
         sprintf(ascii_buf+z,"%d",get_value(base_buf,z-1));
         //fprintf(stderr," %d=%d",z-1,get_value(base_buf,z-1));
      }
      //fprintf(stderr,"\n ->write %d: ",base_size);
      vret=write(fid, ascii_buf, base_size+1);
  }
  free(ascii_buf);
  close(fid);  
  erase_prompt_box(1);
  moveto(tempx,tempy);  
  return(filebytes);
}


/*************** load/save seed from a GOLLY asc1i script ********************/
unsigned int load_Golly_seed(char load_save,char *seed,unsigned int lineL){
  char file_ret,endline;
  signed int fid;
  unsigned int xdim,ydim,max_xdim,this_num,netcount,zn,jj,
               z,zi,tempx,tempy,filebytes=0;
  char *ascii_buf,*num_buf,max_digits,num_count,
       this_value_range; /*value_range found in buf[0]*/

  tempx=getx;
  tempy=gety;
  if (load_save=='l') sprintf(textb[4],"LOAD ");
  if (load_save=='s') sprintf(textb[4],"SAVE ");
  sprintf(textb[3],"Golly_v%d",value_range);
  file_ret=select_filename(textb[4],"SEED (ascii)","*.gly",textb[3]);
  if (file_ret=='q' ){
	moveto(tempx,tempy);
	is[0]='q';
	return(0);
  } 

  /*lineL must be >= filebytes*/
  if ((ascii_buf=(char *)calloc(lineL+1,sizeof(char)))
		 ==NULL) outof_memory("ascii_buf to save/load ascii Golly seed");
  max_digits=6; /*number of digits for each value count*/
  if ((num_buf=(char *)calloc(max_digits,sizeof(char)))
		 ==NULL) outof_memory("num_buf to save/load ascii Golly seed");  
  
  if (load_save=='l'){
     fid=myopen(filename,0,0); 

     if (fid==-1){
        file_error(filename);
	is[0]='q';
	free(ascii_buf);
        free(num_buf);
	close(fid);
        moveto(tempx,tempy);
	return(0);
     }
  
     filebytes= filelength(fid);

     /*Golly's pattern format is just run-length encoding;
     numbers before 'o', 'b', '$' stand for number of each (including newlines).
     'o' -- ON cell, 'b' -- OFF cell, and '$' -- newline.
     So this: 5x6
     2bo2$o3bo2$bobo$2bo!
     ..*..
     .....
     *...*
     .....
     .*.*.
     ..*..
     
     /*read correct no of bytes into buf*/
     vret=read(fid,ascii_buf,filebytes);
     //fprintf(stderr,"\n%s\n",ascii_buf);

     /*check x/y dims -- if same as i2d,j2d */
     num_count=0;
     endline=0;
     xdim=0;
     max_xdim=0;
     ydim=0;
     
     //fprintf(stderr,"\n");
     for (z=0;z<=filebytes-1;z++){          
       this_num=0;      
       if (isdigit(ascii_buf[z])){
           num_count++;
           num_buf[num_count-1]=ascii_buf[z];
           continue;  
       }
       else if (num_count>=1 && (ascii_buf[z]=='o' || ascii_buf[z]=='b' || ascii_buf[z]=='$')){
	  this_num=atoi(num_buf);
          //fprintf(stderr,"%d",this_num);

          if (ascii_buf[z]=='o' || ascii_buf[z]=='b') xdim+=this_num;
          else if (ascii_buf[z]=='$'){
             ydim+=this_num;
             endline=1;
          }
          //fprintf(stderr,"%c",ascii_buf[z]);
          
          this_num=0;             
          for (zi=0;zi<=num_count-1;zi++) num_buf[zi]=0; /*set buf to zero*/
          num_count=0;
       }
       else if (ascii_buf[z]=='o' || ascii_buf[z]=='b' || ascii_buf[z]=='$' || ascii_buf[z]=='!'){
          if (ascii_buf[z]=='o' || ascii_buf[z]=='b') xdim++;          
          else if (ascii_buf[z]=='$' || ascii_buf[z]=='!'){
               ydim++;
               endline=1;
          }
          //fprintf(stderr,"%c",ascii_buf[z]);	             
	}
        if (endline==1){
	   if (max_xdim < xdim) max_xdim=xdim;
           //fprintf(stderr,"\nmaxx=%d x,y=%d,%d\n",max_xdim,xdim,ydim);
           xdim=0;
           endline=0;
        }
        if (ascii_buf[z]=='!') break;
     }
     
     if (max_xdim>i2d || ydim>j2d){
           draw_prompt_box(1);
           sprintf(textb[0],
           "Golly: base ij=%d,%d < file ij=%d,%d, can't load, cont-ret:",
                             i2d,j2d,max_xdim,ydim);
           outtext(textb[0]);
           input_string(1,0);
           //file_error(filename);
	   is[0]='q';
	   free(ascii_buf);
           free(num_buf);
	   close(fid);
           moveto(tempx,tempy);
	   return(0);
     }

     fprintf(stderr,"\nload Golly: base ij=%d,%d >= file ij=%d,%d -OK",i2d,j2d,max_xdim,ydim);

     num_count=0;
     netcount=lineL-1;
     jj=0;
     //fprintf(stderr,"\n%dx%d=%d\n",i2d,j2d,lineL);
     memmove(seed,all_0s,bytesL); //first empty the seed
     for (z=0;z<=filebytes-1;z++){
       this_num=0;      
       if (isdigit(ascii_buf[z])){
           num_count++;
           num_buf[num_count-1]=ascii_buf[z];
           continue;  
       }
       if (ascii_buf[z]=='!') break;
       else if (num_count>=1 && (ascii_buf[z]=='o' || ascii_buf[z]=='b' || ascii_buf[z]=='$')){
	  this_num=atoi(num_buf);
          //fprintf(stderr,"%d",this_num);

          /*fprintf(stderr,"(");*/
          for (zn=0; zn<=this_num-1; zn++){
		  if (ascii_buf[z]=='o') set_value(seed,netcount-zn,1);
                  else set_value(seed,netcount-zn,0);
		  /*fprintf(stderr,"%d ",netcount-zn);*/
	  }
          /*fprintf(stderr,")");*/
	  if (ascii_buf[z]=='o' || ascii_buf[z]=='b') netcount-=this_num;
          else if (ascii_buf[z]=='$'){
             jj+=this_num;
             netcount=lineL-1-(i2d*jj);
	  }
          //fprintf(stderr,"%c",ascii_buf[z]);
          
          this_num=0;             
          for (zi=0;zi<=num_count-1;zi++) num_buf[zi]=0; /*set buf to zero*/
          num_count=0;
       }
       else if (ascii_buf[z]=='o' || ascii_buf[z]=='b' || ascii_buf[z]=='$'){
          if (ascii_buf[z]=='o' || ascii_buf[z]=='b'){
             if (ascii_buf[z]=='o') set_value(seed,netcount,1);
             else set_value(seed,netcount,0);
             netcount-=1;
             //fprintf(stderr,"%c",ascii_buf[z]);
             
          }
          else if (ascii_buf[z]=='$'){
	       jj+=1;
               netcount=lineL-1-(i2d*jj);
               //fprintf(stderr,"%c",ascii_buf[z]);
               //fprintf(stderr,"(%d)\n",netcount);
          }          
	}
     }
  }
  
  if (load_save=='s') {
    char *sparebuf;
    signed int zz, az,vz,i,this_repeat,bufsize,newsize,countZ;
         /*coutZ was count$, but this gave an error in watcom*/
      
      fid=myopen(filename,1,0);
      if (fid==-1){
         file_error(filename);     
         is[0]='q';
         close(fid);
         free(ascii_buf);
         return(0);
      }
      fprintf(stderr,"\nsave Golly: ij=%dx%d",i2d,j2d);      
      zz=0;
      az=0;
      vz=0;
      this_repeat=0;
      for (z=L;z!=Maxu;z--){
         zz+=1;
         if (zz%i2d>0 && get_value(seed,z)==get_value(seed,z-1)){
             this_repeat++;
             //fprintf(stderr,"%d,",this_repeat);
             continue;
	 }
	 if (this_repeat==0){
	   if (get_value(seed,z)==0){
                sprintf(ascii_buf+az,"b");
                az++;
                //fprintf(stderr,"b");
	    }
	    else if (get_value(seed,z)==1){ 
                sprintf(ascii_buf+az,"o");
                az++;
                //fprintf(stderr,"o");                
            }
            this_repeat=0;
         }
	 else if (this_repeat>0){	      
            if (get_value(seed,z+1)==0 && zz%i2d==0){
	       //fprintf(stderr,"<<%d>>",vz);
	       if (vz==j2d-1) break;
               vz++;
	       sprintf(ascii_buf+az,"$");
               az++;
               //fprintf(stderr,"(%d)",this_repeat);
               //fprintf(stderr,"$");
               this_repeat=0;
               continue;
            }
            else{ 
	       sprintf(ascii_buf+az,"%d",this_repeat+1);
               sprintf(textb[1],"%d",this_repeat+1);
               //fprintf(stderr,"%d",this_repeat+1);
               az+=strlen(textb[1]);
               if (get_value(seed,z+1)==0){ 
                  sprintf(ascii_buf+az,"b");
                  az++;
                  //fprintf(stderr,"b");
               }
               else if (get_value(seed,z+1)==1){ 
                  sprintf(ascii_buf+az,"o");
                  az++;
                  //fprintf(stderr,"o");
               }
               this_repeat=0;
            }
         }
         if (zz%i2d==0){
	    //fprintf(stderr,"<%d>",vz);
            if (vz==j2d-1) break;
	    vz++;
	    sprintf(ascii_buf+az,"$");
            az++;
            //fprintf(stderr,"$");
            this_repeat=0;
         }
      }
      sprintf(ascii_buf+az,"!");
      az++;
      //fprintf(stderr,"!");
      sprintf(ascii_buf+az,"%c",'\0');
      //fprintf(stderr,"\n%s",ascii_buf);

      
      //replace multiple $s with x$, $$$-> 3$
      //memmove void *memmove(void *dest, const void *src, size_t n);
      countZ=0;
      newsize=0;
      bufsize=strlen(ascii_buf);
      if ((sparebuf=(char *)calloc(bufsize*2,sizeof(char)))
		 ==NULL) outof_memory("sparebuf to save/load ascii Golly seed");
      //fprintf(stderr,"\n%s",ascii_buf);

      for (z=0;z<=bufsize-1;z++){
	if (ascii_buf[z]=='$'){
          countZ=1;
	  for (i=z+1;i<=bufsize-1;i++){
	     if (ascii_buf[i]!='$'){
                break;
             }
	     countZ++;             
          }
          if (countZ>=2){
	     //copy rest to a new buf
	     //fprintf(stderr,"\n%d",strlen(ascii_buf+i));
	     memmove(sparebuf,ascii_buf+i,strlen(ascii_buf+i));
             //fprintf(stderr,"\nsb=%s",sparebuf);
             sprintf(ascii_buf+z,"%d$\0",countZ);
             //fprintf(stderr,"\nas=%s",ascii_buf);             
             newsize=strlen(ascii_buf);
             z=newsize-1;
             memmove(ascii_buf+newsize,sparebuf,strlen(sparebuf));
             for (zz=0;zz<=bufsize-1;zz++){
                 if (ascii_buf[zz]=='!'){
		     ascii_buf[zz+1]='\0';
                     break;
                 }
	     }
             //fprintf(stderr,"\nns=%s",ascii_buf);
             countZ=0;
          }          
        }      
      }
      free(sparebuf);
      //vret=write(fid, ascii_buf, az);  
      vret=write(fid, ascii_buf, strlen(ascii_buf));
      fprintf(stderr," -OK");     
  }
  free(ascii_buf);
  free(num_buf);
  close(fid);
  moveto(tempx,tempy);
  return(filebytes);
}

/********************* save rule or seed, dec 93 ********************/
void load_glider_buf(signed int no_of_glider_rules){
  signed int fid,rulebytes,tablemax;
  unsigned long buffreq,filebytes;

  
  /*name the glider rules file*/
  if (tot_only==0){
     tablemax= (signed int)pow(value_range,(double)nhoodm[0])-1;
     rulebytes=(signed int)ceil(value_bits * (double)(tablemax+1)/8);
     sprintf(filename,"g_v%dk%d.r_s",value_range,nhoodm[0]);
  }
  else if (totalistic==2){
     tablemax= v_tablecodemax[nhood];
     rulebytes=(signed int) /*bytes for k-code, min=1*/
            ceil(value_bits * (double)(tablemax+1)/8);
     sprintf(filename,"g_v%dk%d.r_v",value_range,nhoodm[0]); /*55 rules 22+32+1*/
     /*old collections: v3k6a.r_v=22+1 rules, v3k6b.r_v=32+1 rules*/
     /*fprintf(stderr,"\n%s %d rules",filename,no_of_glider_rules);*/
  } 

  fid=myopen(filename,0,0);
  if (fid==-1) return;
  
  /*OLD: 5 lead bytes (0-4) 
    byte 0 =nhood
    bytes 1,2 =lineL, max=1+256(9+128)=35074, ie. no of different rules
    bytes 3,5 = i2d,j2d for twod otherwise 0,0*/
  /*-----------------------------------------------------------*/
  /*NEW for value range: 6 lead bytes (0-5)
    byte 0=value_range, if byte 0=0 then load old style
    byte 1 =nhood
    bytes 2,3 =lineL
    bytes 4,5 = i2d,j2d, 0,0 for oned*/

  /*glider_buf is global variable, freed in main*/

  filebytes=filelength(fid);
  if ((glider_buf=(unsigned char *)
	   realloc(glider_buf,filebytes*sizeof(unsigned char)+rulebytes))
				==NULL) outof_memory("glider_buf");
  buffreq=filebytes;

  vret=read(fid,glider_buf,buffreq);
  /*update number of rules in buf*/
  no_glider_rules[value_range][(signed int)nhoodm[0]]=
            (signed int)((buffreq-6)/rulebytes); /*rule at 0 empty*/


  /*fprintf(stderr,"\ncomplex rules g_v%dk%d = %d",
              value_range,(signed int)nhoodm[0],
                 (signed int)((buffreq-6)/rulebytes));
    fprintf(stderr," = %d", 
            no_glider_rules[value_range][(signed int)nhoodm[0]]);*/

  close(fid);
}

/********************* select file and list files, dec 93 **************/
char select_list_files(char* filespec,
	     signed int leftbox,signed int topbox){

#if __WATCOM__
 /*returns filename length or 0*/
 signed int tempx,tempy,done;
 char len=0;
 struct find_t fileinfo;

  /*watcom
 struct find_t{
  char reserved[21];
  char attrib;
  unsigned int wr_time;
  unsigned int wr_date;
  unsigned long size;
  char name[13];
 };*/

  tempx=getx;
  tempy=gety;
  setviewport(0, 0, Maxx, Maxy, 0);  
  draw_box(2,leftbox,topbox,Maxx-2,Maxy-2,1,0);
  moveto(leftbox+3,topbox);

 start:
     done = _dos_findfirst(filespec,_A_NORMAL,&fileinfo);

  if (done==-1){
     sprintf(textb[0],"no %s files",filespec);
     outtext(textb[0]);
     input_string(1,0);
  }
  else{
     while (!done){
	sprintf(textb[2],"%s", fileinfo.name);
	if (gety>Maxy-vgay(40)){
	    outtext("see more-m");
	    moveto(leftbox+3,gety+CHeight);
	    outtext("or filename");
	    moveto(leftbox+3,
	    gety+CHeight);
	    outtext(":");
	    len=input_string(8,0);
	    if (is[0]=='m') {
		erase_box(leftbox,topbox,Maxx-2,Maxy-2);
		draw_box(-1,leftbox,topbox,Maxx-2,Maxy-2,1,0);
		moveto(leftbox+3,topbox);
		len=0;
	    }
	    else if (isalpha(is[0])) break;
	    else {
		len=0;
		break;
	    }
	}
	outtext(textb[2]);
	moveto(leftbox+3,gety+CHeight);
	done = _dos_findnext(&fileinfo);
     }
     if (len==0 && done){
	outtext("list again-?");
	moveto(leftbox+3,gety+CHeight);
	outtext("or filename");
	moveto(leftbox+3,gety+CHeight);
	outtext(":");
	len=input_string(8,0);
	    if (is[0]=='?') {
		erase_box(leftbox,topbox,Maxx-2,Maxy-2);
		draw_box(-1,leftbox,topbox,Maxx-2,Maxy-2,1,0);
		moveto(leftbox+3,topbox);
		len=0;
		goto start;
	    }
	    else if (!isalpha(is[0])) len=0;
     }
  }
  sprintf(textb[9],"%s","boximage[2]");
  putimage(leftbox,topbox,boximage[2],COPY_PUT,textb[9]);
  freeimage(boximage[2]);
  moveto(tempx,tempy);
  return(len);
  /************************ different for unix *******************/
# elif __UNIX__
/*returns filename length or 0*/
 signed int tempx,tempy;
 
 char len=0,filefound;

 DIR *dirp;
 struct dirent *dp; 

  tempx=getx;
  tempy=gety;
  draw_box(2,leftbox,topbox,Maxx-2,Maxy-2,1,0);
  moveto(leftbox+3,topbox);
  
  start:
  dirp = opendir(".");
  filefound=0;
  while (1){
        dp=readdir(dirp);
        
        if (dp==NULL) break;        
        if (memcmp(dp->d_name+(strlen(dp->d_name)-4), 
                                   filespec+1, 4)!=0) continue;
        filefound=1;       
	sprintf(textb[2],"%s",dp->d_name );
        if (gety>Maxy-vgay(40)){
	    outtext("see more-m");
	    moveto(leftbox+3,gety+CHeight);
	    outtext("or filename");
	    moveto(leftbox+3,gety+CHeight);
	    outtext(":");
	    len=input_string(8,0);
	    if (is[0]=='m') {
		erase_box(leftbox,topbox,Maxx-2,Maxy-2);
		draw_box(-1,leftbox,topbox,Maxx-2,Maxy-2,1,0);
		moveto(leftbox+3,topbox);
		len=0;
	    }
	    else if (isalpha(is[0])) break;
	    else {
		len=0;
		break;
	    }
	}
	outtext(textb[2]);
	moveto(leftbox+3,gety+CHeight);
	
     
  }
  if (len==0 && (dp==NULL || 
                 memcmp(dp->d_name+strlen(dp->d_name)-4, filespec, 4)!=0)){
        outtext("list again-?");
	moveto(leftbox+3,gety+CHeight);
	outtext("or filename");
	moveto(leftbox+3,gety+CHeight);
	outtext(":");
	len=input_string(8,0);
	if (is[0]=='?') {
		erase_box(leftbox,topbox,Maxx-2,Maxy-2);
		draw_box(-1,leftbox,topbox,Maxx-2,Maxy-2,1,0);
		moveto(leftbox+3,topbox);
		len=0;
		closedir(dirp);
                goto start;
	}
	else if (!isalpha(is[0])) len=0;
  }
  if (filefound==0){            
            sprintf(textb[0],"no %s files",filespec);
            outtext(textb[0]);
            input_string(1,0);           
  }
  sprintf(textb[9],"%s","boximage[2]");             
  putimage(leftbox,topbox,boximage[2],COPY_PUT,textb[9]);
  freeimage(boximage[2]);
  moveto(tempx,tempy);
  return(len);
# endif
}

/*********** change drive or directory, Oct 94 *********************/
void change_drive_dir(char which){
  /*same for Watcom and Unix*/

  unsigned int xbox,len;
  char *new_path;

   getcwd(path,81);

   sprintf(textb[0],"new_path");
   if ((new_path=(char *)calloc(81,sizeof(char)))
			  ==NULL) outof_memory(textb[0]);

   sprintf(textb[0],
	"current path %s, CHANGE dir",path);

   xbox=draw_prompt_box(2);
   outtext(textb[0]);
   moveto(xbox,gety+CHeight);
#if __WATCOM__
   outtext("new path, (ie c:\\dir\\subdir):");
#elif __UNIX__
   outtext("new path or subdir:");
#endif
   len=input_string(80,0);
   
   if (is[0]!=13 && is[0]!='q'){
      is[len]='\0';
      sprintf(new_path,"%s",is);
      if (chdir(new_path)==-1){
	 moveto(xbox,gety);
	 setfillstyle(SOLID_FILL,black);
	 bar(getx,gety+vgay(2),
			   Maxx-vgax(3),gety+CHeight+vgay(2));
	 sprintf(textb[1],"can't change to %s",new_path);
	 outtext(textb[1]);
	 input_string(1,0);
      }
   }
   free(new_path);
   getcwd(path,81);
}
/*----------------------------------------------------------------*/




