/*->c.main                     */
/* ArcFax 1.00 July 1992       */
/* (c) David Pilling           */


#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <ctype.h>
#include <time.h>
#include <locale.h>

#include "h.os"
#include "h.wimp"
#include "h.sprite"
#include "h.wimpt"
#include "h.bbc"
#include "h.akbd"
#include "h.werr"
#include "h.flex"

#include "h.Drawlevel0"

#include "h.wos"
#include "h.timex"
#include "h.fsx"
#include "h.strdef"
#include "h.dir"
#include "h.ram"
#include "h.mym"
#include "h.pr"
#include "h.xext"
#include "h.serial"
#include "h.file"
#include "h.batch"
#include "h.view"
#include "h.script"
#include "h.config"
#include "h.buffer"
#include "h.code"
#include "h.link"
#include "h.pic"
#include "h.vx"
#include "h.sched"
#include "h.group"
#include "h.state"
#include "h.con"
#include "h.newfax"
#include "h.serialdev"
#include "h.trans"
#include "h.csv"
#include "h.tw"
#include "h.log"
#include "h.replay"
#include "h.dbug"
#include "h.ftpglue"
#include "h.band"
#include "h.help"
#include "h.mess"
#include "h.txi"
#include "h.scrap"
#include "h.copy"


#include "h.main"





/* #define TIFFRUN 1 */



/*****************************************************************************/






#define MAXPATHS 15

static char * arcfaxpaths[MAXPATHS]=
{
 "ArcFax$TXBatch",
 "ArcFax$RXBatch",
 "ArcFax$AutoRun",
 "ArcFax$Library",
 "ArcFax$TeleDir",
 "ArcFax$BatMan",
 "ArcFax$Dir",
 "ArcFaxRes$Dir",
 "ArcFax$PrintFile",
 "ArcFax$Driver",
 "ArcFax$Resources",
 "ArcFax$Templates",
 "ArcFax$TmpDir",
 "ArcFax$Schedule",
 "ArcFax$Server",
};


static char cachedpaths[MAXPATHS][256];


static void cachepaths(void)
{
 int    i;
 char * p;

 for(i=0;i<MAXPATHS;i++)
 {
  p=getenv(arcfaxpaths[i]);
  if(p) strcpy(cachedpaths[i],p);
  else  cachedpaths[i][0]=0;
 }
}


static void clearpaths(void)
{
 int  i;
 char string[256];

 for(i=0;i<MAXPATHS;i++)
 {
  sprintf(string,"Unset %s",arcfaxpaths[i]);
  oscli(string);
 }
}




char * path(int index)
{
 return(cachedpaths[index]);
}








static void palchange(void)
{

 vdupalvars();


}



static void setmodevars(void)
{
 /* set up mode specific things like width */

 if(wimpt_checkmode()) 
 {
  vdumodevars();

 }
}


void saveconfig(void)
{
 savebatch();
 savedir();
 saveschedule();
}


void terminate(void) 
{
 dirclose();   /* calls saveconfig() */

 scrapfinit();

 xexec("device_terminate",NULL,NULL,NULL);

 xexec("sys_terminate",NULL,NULL,NULL);

 wimp_taskclose(taskhandle);

 oscli("Seteval ArcFax$Case <ArcFax$Case>-1");

 if(!strcmp(getenv("ArcFax$Case"),"0"))
 {
  clearpaths();
  oscli("Unset ArcFax$Case");
 }

 exit(0);
}



int termnok(void)
{
 if((!onlinestate()) || confirm(CONYN,"{ONLINE}"))
 {
  stategoquiet();
  poll(FORCEZERO);                /* just to make sure */
  return(0);
 }
 else return(1);
}



void terminatec(void)
{
 if(activestate() && termnok()) return;
 terminate();
}


/*************************************************************************/


static void decodeclick(void)
{
 int vxn;

 buttons=wimpevent.data.but.m.bbits;
 micon=icon=wimpevent.data.but.m.i;
 mhandle=ewindow=wimpevent.data.but.m.w;
 mousex=wimpevent.data.but.m.x;
 mousey=wimpevent.data.but.m.y;

 if(ewindow==-2)                  decodeiconbar();
 else
 if(ewindow==whandle[STATUS])     configicon(icon);
 else
 if(ewindow==whandle[MODEM])      configmodemicon(icon);
 else
 if(ewindow==whandle[PRINTER])    configprintericon(icon);
 else
 if(ewindow==whandle[FAX])        configfaxicon(icon);
 else
 if(ewindow==whandle[BATCH])      configbatchicon(icon);
 else
 if(ewindow==whandle[VOICE])      configvoiceicon(icon);
 else
 if(ewindow==whandle[SERVER])     configservericon(icon);
 else
 if(getview(ewindow))             viewicon();
 else
 if(ewindow==whandle[SAVEFILE0])  saveicon();
 else
 if(ewindow==whandle[PSTAT])      staticon();
 else
 if(ewindow==whandle[ZOOM])       zoomicon();
 else
 if(ewindow==whandle[CONF])       conficon();
 else
 if(ewindow==whandle[TDIR])       diricon();
 else
 if(getentry(ewindow))            entryicon();
 else
 if(ewindow==whandle[PASSWORD])   passwordicon();
 else
 if(ewindow==whandle[AFTER])      aftericon();
 else
 if((vxn=getvx(ewindow))>=0)      iconvx(vxn);
 else
 if((vxn=gettoolsvx(ewindow))>=0) icontoolsvx(vxn);
 else
 if((vxn=getsn(ewindow))>=0)      iconsched(vxn);
 else
 if((vxn=getgn(ewindow))>=0)      icongroup(vxn);
 else
 if(ewindow==whandle[PROCESS])    processicon();
 else
 if(ewindow==whandle[VXPRINT])    vxprinticon();
 else
 if(ewindow==whandle[CONTROL])    conicon();
 else
 if(ewindow==whandle[NEWFAX])     newfaxicon(icon);
 else
 if(ewindow==whandle[LOG])        logicon(icon);
 else
 if(ewindow==whandle[REPLAY])     replayclick();
 else
 if(ewindow==whandle[DBUG])       dbicon(icon);
 else
 if(ewindow==whandle[SETNEWFAX])  confignewfaxicon(icon);

 txiconcheck(buttons,micon,mhandle);
}



static void redraw(void)
{ 
 int vxn;

 ewindow=wimpevent.data.o.w;
                             
 if(ewindow==whandle[TDIR])   dirredraw();
 else
 if((vxn=getvx(ewindow))>=0)  redrawvx(vxn);
 else
 if((vxn=getsn(ewindow))>=0)  redrawsched(vxn);
 else
 if((vxn=getgn(ewindow))>=0)  redrawgroup(vxn);
 else
 if(getview(ewindow))         viewredraw();
 else
 if(ewindow==whandle[LOG])    logredraw();
 else
 if(ewindow==whandle[DBUG])   dbredraw();
}










static void wopen(void)
{
 int vxn;

 ewindow=wimpevent.data.o.w;

 if(getview(ewindow))         openvwimp();
 else
 if((vxn=getvx(ewindow))>=0)  openvx(vxn);
 else
 wimp_open_wind(&(wimpevent.data.o));
}




static void wclose(void)
{
 int vxn;

 ewindow=wimpevent.data.o.w;

 if(getview(ewindow))            closevwimp();
 else
 if(ewindow==whandle[TDIR])      dirclose();
 else
 if(getentry(ewindow))           entryclose();
 else
 if((vxn=getvx(ewindow))>=0)     closevx(vxn);
 else
 if((vxn=getsn(ewindow))>=0)     closesched(vxn);
 else                          
 if((vxn=getgn(ewindow))>=0)     closegroup(vxn);
 else
 if(ewindow==whandle[CONTROL])   conclose();
 else
 if(ewindow==whandle[STATUS])    closeconfig(0);
 else
 if(ewindow==whandle[MODEM])     closeconfigmodem(0);
 else
 if(ewindow==whandle[PRINTER])   closeconfigprinter(0);
 else
 if(ewindow==whandle[FAX])       closeconfigfax(0);
 else
 if(ewindow==whandle[VOICE])     closeconfigvoice(0);
 else
 if(ewindow==whandle[SERVER])    closeconfigserver(0);
 else
 if(ewindow==whandle[BATCH])     closeconfigbatch(0);
 else
 if(ewindow==whandle[LOG])       closelog();
 else
 if(ewindow==whandle[REPLAY])    replayclose();
 else
 if(ewindow==whandle[DBUG])      dbclose();
 else
 if(ewindow==whandle[SETNEWFAX]) closeconfignewfax(0);
 else
 if(ewindow==whandle[NEWFAX])    newfaxclose(-1);
 else                            closedown(ewindow);
}




static void keypress(void)
{
 int key;
 int vxn;

 key=wimpevent.data.key.chcode;
 ewindow=wimpevent.data.key.c.w;
 icon=wimpevent.data.key.c.i;

 if(ewindow==whandle[SAVEFILE0]) savekey(&key);
 else
 if(ewindow==whandle[ZOOM])      zoomkey(&key);
 else
 if(getentry(ewindow))           entrykey(&key);
 else
 if(ewindow==whandle[PASSWORD])  passwordkey(&key);
 else
 if(ewindow==whandle[CONF])      confkey(&key);
 else
 if(ewindow==whandle[STATUS])    configkey(&key);
 else
 if(ewindow==whandle[MODEM])     configmodemkey(&key);
 else
 if(ewindow==whandle[PRINTER])   configprinterkey(&key);
 else
 if(ewindow==whandle[FAX])       configfaxkey(&key);
 else
 if(ewindow==whandle[BATCH])     configbatchkey(&key);
 else
 if(ewindow==whandle[VOICE])     configvoicekey(&key);
 else
 if(ewindow==whandle[SERVER])    configserverkey(&key);
 else
 if(ewindow==whandle[PROCESS])   processkey(&key);
 else
 if(ewindow==whandle[VXPRINT])   vxprintkey(&key);
 else
 if(ewindow==whandle[NEWFAX])    newfaxkey(&key);
 else 
 if((vxn=getvx(ewindow))>=0)     vxkey(vxn,&key);
 else
 if(ewindow==whandle[DBUG])      dbkey(&key);


 if(key!=-1)                     grabkey(&key);

 if(key!=-1) wimp_processkey(key);
}



/*****************************************************************************/


void startdrag(int type,int handle)
{
 draghandle=handle;
 dragtype=type;

 addzeroevent(DRAGZERO);
}



static void zerodrag(void)
{


}



static void decodedrag(void)
{
 int vxn;

 if(!txicondrag())
 {
  if(getview(draghandle))            extractdragend();  
  else
  if(draghandle==whandle[SAVEFILE0]) savedragend();
  else
  if((vxn=getvx(draghandle))>=0)     vxareadragend(vxn);
  else
  if(draghandle==whandle[TDIR])      dirdragend();
 }

 remzeroevent(DRAGZERO);
}




/*****************************************************************************/

static int dopollidle=0;
int zerotime;

void addzeroevent(int type)
{
 dopollidle|=type;
}


void remzeroevent(int type)
{
 dopollidle|=type;
 dopollidle^=type;
}



static char pollfnname[32];

void addpollfunction(int fp)
{
 strcpy(pollfnname,stringptr(stack[fp]));
 addzeroevent(POLLFNZERO);
}


void rempollfunction(int fp)
{
 remzeroevent(POLLFNZERO);
 fp=fp;
}


static void pollfnzero(void)
{
 xexec(pollfnname,NULL,NULL,NULL);
}




static void zero(int zmask)
{
 int dopoll;


 zerotime=clock();

 dopoll=(dopollidle & (~zmask));

 if(dopoll & DRAGZERO)    zerodrag();

/* dprintf(0,"zero (1) ");  */

 if(dopoll & RXDATAZERO)  rxdatazero();

/* dprintf(0,"zero (2) "); */

 if(dopoll & TXDATAZERO)  txdatazero();

/* dprintf(0,"zero (3) "); */

 if(dopoll & FAXPOLL)     faxpoll();

/* dprintf(0,"zero (4) ");  */

 if(dopoll & LINKDEMON)   linkzero();

/* dprintf(0,"zero (5) "); */

 if(dopoll & MEMORYDEMON) flex_demon();

/* dprintf(0,"zero (6) ");  */

 if(dopoll & PROCESSZERO) processzero();

/* dprintf(0,"zero (7) ");  */

 if(dopoll & MODEMCHANGEZERO) modemchangedemon();

/* dprintf(0,"zero (8) ");  */

 if(dopoll & SDEVZERO)    sdevzero();

/* dprintf(0,"zero (9) "); */

 if(dopoll & BLOCKZERO)   blockzero();

/* dprintf(0,"zero (A) ");  */

 if(dopoll & REPLAYZERO)  replayzero();

/* dprintf(0,"zero (B) ");  */

 if(dopoll & RXFAXZERO)   rxfaxzero();

/* dprintf(0,"zero (C) ");  */

 if(dopoll & ONZERO)      onlinezero();

/* dprintf(0,"zero (D) ");  */

 if(dopoll & CONZERO)     conzero();

/* dprintf(0,"zero (E) "); */

 if(dopoll & NEWFAXZERO)  newfaxzero();

/* dprintf(0,"zero (F) ");  */

 if(dopoll & POLLFNZERO)  pollfnzero();

/* dprintf(0,"zero (G) ");   */

}





/*****************************************************************************/



static void pointerenters(void)
{
 ewindow=wimpevent.data.o.w;




}


static void pointerleaves(void)
{
 ewindow=wimpevent.data.o.w;




}



static void losecaret(void)
{
 ewindow=wimpevent.data.c.w;
 icon=wimpevent.data.c.i;

}


static void gaincaret(void)
{
 ewindow=wimpevent.data.c.w;
 icon=wimpevent.data.c.i;

}



/*****************************************************************************/


static int loadfile(int type,char * name,int xvolatile)
{
 if(getview(mhandle))
 {
  return(batchxload(type,name,xvolatile));
 }
 else
 if(mhandle==-2)
 {
  if(type==SCRIPT) return(runscript(name,0));
  else
  if(type==TIFF)   return(loadtiff(name,0)?NOLOAD:1);
  else
  if(type==ASND)   return(loadsnd(name)?NOLOAD:1);
 }
 else
 if(mhandle==whandle[TDIR]) return(loadcsv(name));
 else                       return(loadtexticon(name,type,mhandle,micon));

 return(0);  /* could not load it */
}



static void loadfilepost(int type)
{
 if(mhandle==-2 && type==SCRIPT) runscriptpost();
}




/* return 1 if can load by ram transfer   */
/* return 2 if can load by scrap transfer */
/* return 3 if has to be real file        */

static int goodloadtype(int type)
{
 if(getview(mhandle))
 {
  return(2);
 }
 else
 if(mhandle==-2 && type==SCRIPT)
 {
  return(1);
 }
 else
 if(mhandle==-2 && (type==TIFF||type==ASND))
 {
  return(3);
 }
 else
 if(mhandle==whandle[TDIR] && type==CSV)
 {
  return(1);
 }
 else
 return(canloadtexticon(type,mhandle,micon));

 return(0);
}



static int goodruntype(int type)
{
 if(type==SCRIPT) return(1);

#ifdef TIFFRUN
 else
 if(type==TIFF) return(1);
#endif

 return(0);
}



static int goodprinttype(int type)
{
 type=0;
 return(0);
}


/***************************************************************************/
                          /* Message Handling */

static int         scrapref=-1;
static int         sscrapref=-1;
static char        scrapname[32];
static wimp_msgstr scmsg;

static void scrapfile(void)
{
 if(!getenv("Wimp$Scrap"))
 {
  errorbox("{WIMP00}");
  return;
 }

 wimpevent.data.msg=scmsg;

 strcpy(scrapname,wimpevent.data.msg.data.datasave.leaf);

 wimpevent.data.msg.data.datasaveok.estsize=-1;
 strcpy(wimpevent.data.msg.data.datasaveok.name,"<Wimp$Scrap>");
 wimpevent.data.msg.hdr.size=((48+12) & 0xFFFFFFFC);
 wimpevent.data.msg.hdr.your_ref=wimpevent.data.msg.hdr.my_ref;
 wimpevent.data.msg.hdr.action=2;
 wimp_sendmessage(17,&wimpevent.data.msg,wimpevent.data.msg.hdr.task);
 scrapref=wimpevent.data.msg.hdr.my_ref;
}



static void sparkscrapfile(void)
{
 char tempname[256];

 sprintf(tempname,"%s.%s",xvname(view),wimpevent.data.msg.data.datasave.leaf);

 wimpevent.data.msg.data.datasaveok.estsize=-1;
 strcpy(wimpevent.data.msg.data.datasaveok.name,tempname);
 wimpevent.data.msg.hdr.size=((48+(strlen(tempname)+3)) & 0xFFFFFFFC);
 wimpevent.data.msg.hdr.your_ref=wimpevent.data.msg.hdr.my_ref;
 wimpevent.data.msg.hdr.action=2;
 wimp_sendmessage(17,&wimpevent.data.msg,wimpevent.data.msg.hdr.task);
 sscrapref=wimpevent.data.msg.hdr.my_ref;
}




static void dataloadack(void)
{

}



/* something expects us to save data to it */

static void savedata(void)
{
 int    saverefx;

 saverefx=wimpevent.data.msg.hdr.your_ref;
 if(saverefx!=saveref)
 {
  errorbox("{UXDS}");
  return;
 }

 if(saveref==viewsaveref) viewsave();
 else
 {
  if(!(buttons & 0x1)) zapmenu();
  savefile(wimpevent.data.msg.data.datasaveok.name);
  wimpfirst.data.msg.hdr.your_ref=wimpfirst.data.msg.hdr.my_ref;
  wimpfirst.data.msg.hdr.action=3;
  wimp_sendmessage(17,&wimpfirst.data.msg,wimpfirst.data.msg.hdr.task);
 }
}



static void loaddata(void)
{
 int    type=wimpevent.data.msg.data.dataload.type;
 char * name=wimpevent.data.msg.data.dataload.name;
 int    xvolatile;
 int    code;

 mousex=wimpevent.data.msg.data.dataload.x;
 mousey=wimpevent.data.msg.data.dataload.y;
 micon=wimpevent.data.msg.data.dataload.i;
 mhandle=wimpevent.data.msg.data.dataload.w;

 xvolatile=((wimpfirst.data.msg.hdr.your_ref==scrapref) ||
              (wimpfirst.data.msg.hdr.your_ref==sscrapref)); 


 code=loadfile(type,name,xvolatile);

 /* saying ok, we loaded it ok */

 if(wimpfirst.data.msg.hdr.your_ref==scrapref)
 {
  oscli("delete <Wimp$Scrap>");
  scrapref=-1;
 }
 else
 if(wimpfirst.data.msg.hdr.your_ref==sscrapref && code==NOLOAD)
 {
  remove(name);
  sscrapref=-1;
 }

 if(code!=NOLOAD)
 {
  wimpfirst.data.msg.hdr.your_ref=wimpfirst.data.msg.hdr.my_ref;
  wimpfirst.data.msg.hdr.action=4;
  wimp_sendmessage(17,&wimpfirst.data.msg,wimpfirst.data.msg.hdr.task);
  loadfilepost(type);
 }

}




static void opendata(void)
{
 int code=0;
 int type=wimpevent.data.msg.data.dataopen.type;


/* dprintf(1,"w=%d i=%d x=%x y=%d size=%d type=%x name=%s",
          wimpevent.data.msg.data.dataopen.w,
          wimpevent.data.msg.data.dataopen.i,
          wimpevent.data.msg.data.dataopen.x,
          wimpevent.data.msg.data.dataopen.y,
          wimpevent.data.msg.data.dataopen.size,
          wimpevent.data.msg.data.dataopen.type,
          wimpevent.data.msg.data.dataopen.name); */


 if(goodruntype(type))
 {
  /* one of ours so load it */
  /*  double click on file  */

  switch(type)
  {

  case SCRIPT:             /* absorb these, or else it runs another Hearsay */
              code=runscript(wimpevent.data.msg.data.dataload.name,0);
              break;


  case   TIFF:
              {
               int sh;

               sc_create(&sh);
               code=0;

               copyfile(sc_name(sh),
                        wimpevent.data.msg.data.dataload.name,0,0);
               code=
                 loadtiff(sc_name(sh),sh)?NOLOAD:1;

               if(code==NOLOAD) sc_remove(sh,NULL);

              }
              break;

  }

  /* saying ok, we loaded it ok */

  wimpfirst.data.msg.hdr.your_ref=wimpfirst.data.msg.hdr.my_ref;
  wimpfirst.data.msg.hdr.action=4;
  wimp_sendmessage(17,&wimpfirst.data.msg,wimpfirst.data.msg.hdr.task);

  if(code && type==SCRIPT) runscriptpost();
 }
}




static void ramfetch(void)
{
 int saverefx;

 /* this is the first we know about it if something */
 /* else is trying to load a file                   */
 /* next comes a datasaveack -> scrap file          */

 /* means destination wants stuff saving to RAM */

 saverefx=wimpevent.data.msg.hdr.your_ref;
 if(saverefx!=saveref)
 {
  errorbox("{UXRM}");
  return;
 }
 if(saveref!=viewsaveref)  /* no ram tran on viewers */
 {
  ramnextwritefile();
  savefile(NULL); 
  ramoff();
  if(!(buttons & 0x1)) zapmenu();
 }
}







/* a drag from the filer, has ended on a printer driver          */
/* up to us to load and print the file if we can and then say so */

static void printfileodd(void)
{
 int type=wimpevent.data.msg.data.print.type;
 char * name=wimpevent.data.msg.data.print.name;

 if(goodprinttype(type))
 {
  wimpfirst.data.msg.hdr.your_ref=wimpfirst.data.msg.hdr.my_ref;
  wimpfirst.data.msg.hdr.action=0x80146;
  wimp_sendmessage(17,&wimpfirst.data.msg,wimpfirst.data.msg.hdr.task);
  /* printdoc(name); */  name=NULL;
 }

}




/**************************************************************************/

static int devicemajor;
static int deviceminor;
static int deviceref;
static int devicedone;

/* we have received a message trying to claim a device */

static void deviceclaim(void)
{
 int major;
 int minor;

 major=wimpevent.data.msg.data.device.major;
 minor=wimpevent.data.msg.data.device.minor;

/* dprintf(2,"claim device major=%d minor=%d",major,minor); */


 if(wimpevent.data.msg.hdr.task!=taskhandle)
 {
  if(activestate() && major==devicemajor && minor==deviceminor)
  {
   if(onlinestate())
   {
    wimpfirst.data.msg.hdr.your_ref=wimpfirst.data.msg.hdr.my_ref;
    wimpfirst.data.msg.hdr.action=12;
    strcpy(wimpfirst.data.msg.data.device.information,transtoken("DEVICE"));
    wimp_sendmessage(17,&wimpfirst.data.msg,wimpfirst.data.msg.hdr.task);
   }
   else
   {
    stategoquiet();
   }
  }
 }
}


static void deviceack(void)
{
 devicedone=1;
}


static void devicebusy(void)
{
 if(wimpevent.data.msg.hdr.your_ref==deviceref)
 {
  werr(0,"{ACTIVE}%s",wimpevent.data.msg.data.device.information);
  devicedone=-1;
 }
}


static void trytoclaimdevice(int major,int minor)
{
 wimp_msgstr msg;

 /* assumes mhandle etc. are valid here */

 msg.hdr.size=((48+12) & 0xFFFFFFFC);
 msg.hdr.task=taskhandle;
 msg.hdr.your_ref=0;
 msg.hdr.action=11;

 msg.data.device.major=major;
 msg.data.device.minor=minor;
 strcpy(msg.data.device.information,"ArcFax");

 wimp_sendmessage(18,&msg,0);

 deviceref=msg.hdr.my_ref;
}


int getdevice(int fp)
{
 int major;
 int minor;

 major=stack[fp];
 minor=stack[fp+1];

/* dprintf(2,"get device major=%d minor=%d",major,minor); */


 trytoclaimdevice(major,minor);
 devicedone=0;
 while(!devicedone) poll(0);

 if(devicedone>=0)
 {
  devicemajor=major;
  deviceminor=minor;
 }

 return(devicedone>=0);
}


/*****************************************************************************/



static int  datasaveref;

static void ramtransmit(void)
{
 int    type;
 char * name;

 type=scmsg.data.datasave.type;
 name=wimpevent.data.msg.data.datasave.leaf;

 ramloadbuffer();
 armfetch(&wimpevent.data.msg);

 /* means destination wants us to load stuff from RAM */

 loadfile(type,name,0);
 loadfilepost(type);
}



/* something is trying to send us a file */

static void datasave(void)
{
 int type;
 int code;

 mousex=wimpevent.data.msg.data.datasave.x;
 mousey=wimpevent.data.msg.data.datasave.y;
 micon=wimpevent.data.msg.data.datasave.i;
 mhandle=wimpevent.data.msg.data.datasave.w;

 scmsg=wimpevent.data.msg;
 type=scmsg.data.datasave.type;

 code=goodloadtype(type);

 if(code==1)
 {
  /* OK, we can load this filetype this way */
  /* send a ram fetch message               */
  ramnextreadfile();
  datasaveref=readmyref; /* so ack goes through routine above */
  readmyref=-1;
 }
 else
 if(code==2)
 {
  sparkscrapfile();
 }
}



static void prequit(void)
{
 int origtask;
 int cblock[7];
 int norestart;

 if(!activestate()) return;

 if(wimpfirst.data.msg.hdr.size>=24) 
                            norestart=wimpfirst.data.msg.data.words[0] & 0x1;
 else                       norestart=0;

 origtask=wimpfirst.data.msg.hdr.task;
 wimp_get_caret_pos((wimp_caretstr *)cblock);

 wimpfirst.data.msg.hdr.your_ref=wimpfirst.data.msg.hdr.my_ref;
 wimp_sendmessage(19,&wimpfirst.data.msg,wimpfirst.data.msg.hdr.task);

 if(!termnok())
 {
  if(!norestart)
  {
   cblock[6]=0x1FC;
   wimp_sendmessage(8,(wimp_msgstr *)cblock,origtask);
  }
  else
  {
   terminate();
  }
 }
}



static void menumessage(void)
{
 int m1,m2,m3,m4;
 int x,y;
 int submenu;

 submenu=wimpevent.data.msg.data.words[0];
       x=wimpevent.data.msg.data.words[1];
       y=wimpevent.data.msg.data.words[2];
      m1=wimpevent.data.msg.data.words[3];
      m2=wimpevent.data.msg.data.words[4];
      m3=wimpevent.data.msg.data.words[5];
      m4=wimpevent.data.msg.data.words[6];

 dynamicmenu(submenu,x,y,m1,m2,m3,m4);
}



static void writebootfile(void)
{
 char string[FSMAXPATH];
 int  handle;

 handle=wimpevent.data.msg.data.words[0];
 sprintf(string,"Run %s\n",path(AFXD));
 fs_write(handle,string,strlen(string));
}



/* type 19 messages */

static void acknowledged(void)
{
 /* note references work the other way around here */

 if(wimpevent.data.msg.hdr.my_ref==datasaveref)
 {
  ramoff();
  scrapfile();
 }
 else
 if(wimpevent.data.msg.hdr.my_ref==readmyref)   readack();
 else
 if(wimpevent.data.msg.hdr.my_ref==writemyref)  writeack();
 else
 if(wimpevent.data.msg.hdr.my_ref==viewopenref) viewack();
 else
 if(wimpevent.data.msg.hdr.my_ref==deviceref)   deviceack();
}


static int messagenumbers[22]=
{
 1,
 2,
 3,
 4,
 5,
 6,
 7,
 8,
 9,
 10,
 11,
 12,
 0x400C0,
 0x400C1,
 0x80147,
 0x80143,
 0x80140,
 0x80145,
 0x80144,
 0x502,
 SPARKMESS,
 0
};


static void messageinit(void)
{
 addmessages(messagenumbers);
}


/* type 17 & 18 messages */

static void message(void)
{
  wimpfirst=wimpevent;


  if(wimpevent.data.msg.hdr.your_ref==writemyref) writemess();
  else
  if(wimpevent.data.msg.hdr.your_ref==readmyref)  readmess();
  else
  switch(wimpevent.data.msg.hdr.action)
  {

   case         0: terminate();
                   break;

   case         1: datasave();    /* data save */
                   break;
   case         2: savedata();    /* data save ack */
                   break;
   case         3: loaddata();    /* data load */
                   break;
   case         4: dataloadack(); /* data load ack */
                   break;
   case         5: opendata();    /* data open */
                   break;
   case         6: ramfetch();    /* ram fetch */
                   break;
   case         7: ramtransmit(); /* ram transmit */
                   break;
   case         8: prequit();
                   break;
   case         9: palchange();
                   break;
   case        10:
                   writebootfile();
                   break;

   case        11:
                   deviceclaim();
                   break;
   case        12:
                   devicebusy();
                   break;


   case   0x400C0: /* dynamic menus */
                   menumessage();
                   break;

   case   0x400C1: setmodevars();
                   break;

   case   0x80147: setprinterdriver();
                   break;

   case   0x80143: printinitdriver();
                   break;

   case   0x80140: printfilepd();
                   break;

   case   0x80145: printfileodd();
                   break;

   case   0x80144:
                   break;

   case     0x502:
                   helpmessage();
                   break;

   case SPARKMESS:
                   messagein();
                   break;

  default        :
                   break;
  }
}



/* #define XDEBUG 1 */



static void pollexit(void)
{
#ifdef XDEBUG
 fx(229,1,0);
 fx(224,0,0);
#endif
}



static void pollenter(void)
{
#ifdef XDEBUG
 fx(229,0,0);
#endif
}



/***************************************************************************/


#define POLLWORDMASK (1<<22)


int poll(int zflags)
{
 int    code;
 static int zmask;
 int    oldzmask;
 int    pollmask;

 /* leaves here */

 pollexit();

 pollmask=wimp_ENULL;

 if(pollword) pollmask|=POLLWORDMASK;

 if(dopollidle==(FAXPOLL|BLOCKZERO) && zflags==0)
 {
  timeout=monotonic()+100;
  wimp_pollidlex(pollmask,&wimpevent,timeout,pollword);
 }
 else
 if(dopollidle || zflags) wimp_pollx(pollmask,&wimpevent,pollword);
 else
 {
  timeout=monotonic()+6000;
  wimp_pollidlex(pollmask,&wimpevent,timeout,pollword);
 }

 pollenter();

 /* returns here */

 code=wimpevent.e;

 oldzmask=zmask;
 zmask|=zflags;


 if(!twainpoll(&wimpevent))
 {
  switch(code)
  {
       case  0: 
                zero(zmask);
                break;

       case  1: redraw(); 
                break;            /* redraw window request */

       case  2: wopen(); 
                break;            /* open window request  */

       case  3: wclose(); 
                break;            /* close window request */

       case  4: pointerleaves();
                break;            /* poi. leaving window  */

       case  5: pointerenters();
                break;            /* poi. entering window */


       case  6: decodeclick();
                break;            /* mouse click          */


       case  7: decodedrag();
                break;            /* user drag box        */

       case  8: keypress();
                break;            /* key press            */

       case  9: decodemen();
                break;            /* menu select          */

       case 10: 
                break;            /* scroll request       */

       case 11: losecaret();
                break;

       case 12: gaincaret();
                break;

       case 13:
                linkmessage();
                break;


       case 17:
       case 18:
                message();
                break;

       case 19: 
                acknowledged();
                break;
  }
 }

 zmask=oldzmask;

 return(code);
}



/* a version for when you only want returns on zero polls */
/* and you don't want any terminal reading                */

void pollzt(void)
{
 while(poll(FORCEZERO)!=0);
}


/*
void pollz(void)
{
 while(poll(0)!=0);
}
*/


int main(int argc,char * argv[])
{ 
 int quietboot;
 int holdall;
 int i;

 setlocale(LC_ALL,"ISO8859-1");

 cachepaths();

 quietboot=0;
 holdall=0;

 for(i=1;i<argc;i++)
 {
  if(!cstrcmp(argv[1],"-quiet")) quietboot=1;
  else
  if(!cstrcmp(argv[1],"-hold"))  holdall=1;
 }

 wimp_version=wimpt_init("ArcFax");   /* boots task */

 starttask();             /* does checks and retrieves task handle */

 flex_init();

 messageinit();

 inittrans();



 inithelp();

 loadsprites();

 vdumodevars();
                                                                               
 loadtemps();            /* do this after load sprites */

 bootfile();             /* would like this to be first flex alloc */

 bootbatch();            /* must be after bootfile                 */

 picinit();

 vxinit(); 

 seticonbar();

 setupmenus();

 serialset();

 rosprintinit();

 dirboot();

 linkboot();

 loadschedule();

 stateinit();

 twaininit();

 keyboot();
 logboot();
 bandinit();

 scrapinit("ArcFax","ArcFax");


 scriptstart(quietboot,holdall);  /* better be last so that you don't */
                                  /* init something not set up        */

 timeout=monotonic()+6000;

 batchpop();

 messinit();

 while(1) poll(0);

 return(0);
}
