/* Edit by Frank on Jun 20 17:20 */
/* Don't set sio chip parity */
/* Edit by Bill on May 29 01:01 */
/* Add key configurator */
/* Edit by Bill on May 10 9:24 */
/* Saving settings file to a different disk doesn't work and may bomb */
/* Edit by Bill on May 8 7:17 */
/* Save default file settings, now incompatable with existing save files! */
/* Edit by Bill & Jeff on May 1 14:16 */
/* findfinderfiles was bombing because of fName[1] definition of myAppFile */
/* Edit by Bill on Apr 30 05:50 */
/* Call FlushVol after saving the settings */

/* 
 * file ckmsav.c
 *
 * Module of MacKermit containing code for saving and restoring
 * various variables.
 *
 * Copyright (C) 1985, Trustees of Columbia University in the City of
 * New York.  Permission is granted to any individual or institution to
 * use, copy, or redistribute this software so long as it is not sold
 * for profit, provided this copyright notice is retained.
 *
 */

#include "ckcker.h"			/* Kermit definitions */
#include "ckmdef.h"			/* Common Mac module definitions */
#include "ckmres.h"			/* resource defs */
#include "mac/quickdraw.h"
#include "mac/osintf.h"
#include "mac/toolintf.h"
#include "mac/packintf.h"
#include "ckmkkc.h"			/* common key config defs */

char SAVC_TYPE[] = {"SAVC"},		/* rsrc character types */
     SAVI_TYPE[] = {"SAVI"},		/* rsrc integer types */
     MSET_TYPE[] = {"MSET"},		/* meta prefix string */
     FSET_TYPE[] = {"FSET"},		/* function defs */
     KSET_TYPE[] = {"KSET"};		/* key set */

#define SVVER 3				/* version & rsrc ID number */

char ttype[] = "TEXT";			/* want's to be long aligned */

OsType kermtype = {"KERM"};
OsType texttype = {"TEXT"};

KSHDL kshdl;				/* handle to kset */

int *inames[] = {
  &speed,&parity,&duplex,&delay,
  &mypadn,&npad,&timint,&rtimo,&rpsiz,&spsiz,
  &turnch,&turn,&bctr,&filargs.fildflg
};

#define NINAMES (sizeof(inames) / sizeof(int *))

char *cnames[] = {
  &mypadc,&padch,&eol,&seol,&stchr,&mystch
};

#define NCNAMES (sizeof(cnames) / sizeof(char *))


/* privrsrc - return a private copy of a resource.  The handle
 *    	      returned is relocatable but non purgeable.
 *
 */

Handle privrsrc(type,id)
char *type;
{
  Handle rhdl,phdl,cpyhdl();
  char errbuf[256];

  rhdl = GetResource(type,id);		/* load the resource */
  if (rhdl == (Handle) NIL)		/* nothing? */
  {
    strcpy(errbuf,"There is no resource ");
    strcat(errbuf,type);
    fatal(errbuf,0);			/* real problem guy */
  }

  phdl = cpyhdl(rhdl);			/* make private copy */
  ReleaseResource(rhdl);		/* rsrc completely gone now */
  return(phdl);				/* all done */
  SYM(PRIVRESOURCE);
}

KSHDL loadkset()
{
 Handle fhdl,mhdl;
 KSHDL khdl;

 khdl = (KSHDL) privrsrc(KSET_TYPE,KSVER);
 fhdl = privrsrc(FSET_TYPE,KSVER);
 (*khdl)->fcnshdl = fhdl;		/* save handle to relocatable block */
 mhdl = privrsrc(MSET_TYPE,KSVER);
 (*khdl)->metahdl = mhdl;		/* save handle */
 return(khdl);				/* return the KSET handle */
 SYM(LOADKSET);
}


Handle cpyhdl(hdl)
Handle hdl;
{
  Handle nhdl;
  int hsize;

  hsize = GetHandleSize(hdl);		/* find size */
  nhdl = NewHandle(hsize);		/* get a new handle */
  if (nhdl == (Handle) NIL)
   fatal("NewHandle failed in cpyhdl: ",0);
   
  HLock(hdl);				/* unlikely */
  HLock(nhdl);				/*  but lock anyway */
  BlockMove(*hdl,*nhdl,hsize);		/* copy contents */
  HUnlock(hdl);
  HUnlock(nhdl);
  HNoPurge(nhdl);			/* is probably default */
  return(nhdl);
  SYM(CPYHDL);
}


/* savevals - save variables for MacKermit */

typedef int  **IHandle;			/* handle to int[] */
typedef char **CHandle;			/* handle to char[] */

savevals()
{
  IHandle ihdl;
  CHandle chdl;

  SFReply savr;
  Point where;
  int err,rfnum,i;
  FInfo finf;

  SetPt(&where,75,115);
  SFPutFile(&where,"Save variables in file:","",NILPROC,&savr);
  if (!savr.good)			/* did they hit cancel? */
   return;				/* yes, so return now */
  
  SetVol(NILPTR,savr.vRefNum);		/* select volume for rsrc file */

  CreateResFile(isapstr(savr.fName)); 	/* try to create */   
  if (ResError() != noErr &&		/* an error occured */
      ResError() != dupFNErr)		/*  but not already exists? */
  {
    printerr("Unknown error from create: ",ResError());
    return;
  }
  
  rfnum = OpenResFile(isapstr(savr.fName));
  if (rfnum == -1)			/* failed to open? */
  {
    printerr("Couldn't Open resource file: ",ResError());
    return;
  }
  
  err = GetFInfo(isapstr(savr.fName),savr.vRefNum,&finf);
  if (err != noErr)
   printerr("Can't get finder info for file: ",err);
  else 
  {
    finf.fdType = texttype;		/* set type */
    finf.fdCreator = kermtype;		/* set creator */
    finf.fdFldr = filargs.filfldr;	/* use same as folder as application */
    err = SetFInfo(isapstr(savr.fName),savr.vRefNum,&finf);
    if (err != noErr)
      printerr("Can't set finder info: ",err);
  }
  
  ihdl = (IHandle) NewHandle(sizeof(inames));
  for (i=0; i < NINAMES; i++)		/* copy from indirect table */
    (*ihdl)[i] = *inames[i];		
  AddResource((Handle) ihdl,SAVI_TYPE,SVVER,"");
  
  chdl = (CHandle) NewHandle(sizeof(cnames));
  for (i=0; i < NCNAMES; i++)		/* copy from indirect table */
    (*chdl)[i] = *cnames[i];
  AddResource((Handle) chdl,SAVC_TYPE,SVVER,"");
  
  AddResource(cpyhdl((*kshdl)->metahdl),MSET_TYPE,KSVER,"");
  AddResource(cpyhdl((*kshdl)->fcnshdl),FSET_TYPE,KSVER,"");
  AddResource(cpyhdl((Handle) kshdl),KSET_TYPE,KSVER,"");

  CloseResFile(rfnum);
  FlushVol(NILPTR,savr.vRefNum);	/* flush the bits out */
}

/* kfilefilter - match creator "KERM" from sfgetfile call */

kfilefilter()
{
 FileParam *pb;				/* args from SFGetFile... */
 char *retval;
 
 retval = (char *) getpargs(&pb,sizeof(FileParam *));
 *retval = (strncmp(			/* compare creator's... and return */
      pb->ioFlFndrInfo.fdCreator.s, 	/* TRUE if not a match */
      kermtype.s,4) != 0);		/* FALSE otherwise for inclusion */
}

loadvals()
{
  SFReply savr;
  Point where;

  SetPt(&where,75,115);
  SFGetFile(&where,"Load variables from:",
      	    kfilefilter,1,ttype,NILPROC,&savr);
  if (!savr.good)			/* did they hit cancel? */
   return;				/* yes, so return now */
  
 doloadvals(savr.fName,savr.vRefNum);	/* do the load */
}

typedef struct {		/* AppFile */
	short	vRefNum;
	OsType	fType;
	short	versNum;
	char	fName[255];		/* used to be fName[1]! */
} myAppFile;

findfinderfiles()
{
 int msg,cnt,err;
 myAppFile apf;
 FInfo ainfo;

  CountAppFiles(&msg,&cnt);		/* anything clicked by user? */
  if (cnt == 0 || msg == appPrint)	/* or they want us to print (?) */
  {					/* forget about loading values */
   filargs.filfldr = fDesktop;		/* make new files appear on desk */
   kshdl = loadkset();			/* use our default KSET */
   return;
  }
  GetAppFiles(1,&apf);			/*  get the first one */
  ClrAppFiles(1);			/*  done with this */
  doloadvals(apf.fName,apf.vRefNum);	/*  load the file */
  err = GetFInfo(isapstr(apf.fName),	/* get settings file info */
      	      	  apf.vRefNum,&ainfo); 	
  if (err != noErr)
    printerr("Couldn't GetFInfo for default folder: ",err);		  
  filargs.filfldr = ainfo.fdFldr;	/* use appl or text file's folder */
}

doloadvals(fn,refnum)
char *fn;
int refnum;
{ 
  int rfnum,i;
  IHandle resinames;
  CHandle rescnames;

  SetVol(NILPTR,refnum);		/* select volume */
  rfnum = OpenResFile(isapstr(fn));	/* open the resource file */
  if (rfnum == -1)
  {
    printerr("Couldn't open file: ",ResError());
    return;
  };
  
/* load "SAVI" resource, the saved integer values, "SAVC" saved characters */

  if ((resinames = (IHandle) GetResource(SAVI_TYPE,SVVER)) == NIL ||
      (rescnames = (CHandle) GetResource(SAVC_TYPE,SVVER)) == NIL)
  {
   CloseResFile(rfnum);
   printerr("Can't load your settings, damaged file or wrong version.",0);    
   return;				/* and return */
  }
  
  LoadResource((Handle) resinames);	/* load it into memory */
  for (i=0; i < NINAMES; i++)
   *inames[i] = (*resinames)[i];

  LoadResource((Handle) rescnames);
  for (i=0; i < NCNAMES; i++)
   *cnames[i] = (*rescnames)[i];

  kshdl = loadkset();			/* load new KSET */   
  CloseResFile(rfnum);			/* no longer needed */
  
/* tell serial driver about new vals */

  setserial(innum,outnum,speed,KPARITY_NONE);
}
