/*->c.main                     */
/* Trace 2.00 August 1991      */
/* (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.ram"
#include "h.mym"
#include "h.mytrace"
#include "h.file"
#include "h.pic"

#include "h.fit"


#include "h.main"



#ifndef PROD

#define DBUG

#endif

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


void palchange(void)
{
 if(windowsopen)
 {
  refreshwindow(whandle[DRAWW]);
  refreshwindow(whandle[SPRITEW]);
 }
}


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

 if(wimpt_checkmode()) 
 {
  vdumodevars();
 }
}



void terminate(void) 
{
 wimp_taskclose(taskhandle);
 exit(0);
}



int termnok(void)
{
 return(0);
}


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


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


void decodeclick(void)
{
 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[SAVEFILE0])  saveicon();
 else
 if(ewindow==whandle[CONF])       conficon();
 else
 if(ewindow==whandle[SPRITEW])    mainicon();
 else
 if(ewindow==whandle[DRAWW])      mainicon();
 else
 if(ewindow==whandle[ZOOM])       zoomicon();
}



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

 if(ewindow==whandle[SPRITEW]) redrawsprite();
 else
 if(ewindow==whandle[DRAWW])   redrawdraw();                             
}



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

 if(ewindow==whandle[SPRITEW] || ewindow==whandle[DRAWW]) openwindows();

 wimp_open_wind(&(wimpevent.data.o));
}




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

 if(ewindow==whandle[SPRITEW] || ewindow==whandle[DRAWW]) closetrace();
 else
 closedown(ewindow);
}





void keypress(void)
{
 int key;

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

 if(ewindow==whandle[ZOOM]) zoomkey(&key);

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





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


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

 addzeroevent(DRAGZERO);
}



void zerodrag(void)
{




}



void decodedrag(void)
{
 if(draghandle==whandle[SAVEFILE0]) savedragend();

 remzeroevent(DRAGZERO);
}




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

int dopollidle=0;
int zerotime;

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


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


void zero(int zmask)
{
 int dopoll;
 zerotime=clock();

 dopoll=(dopollidle & (~zmask));

 if(dopoll & DRAGZERO)    zerodrag();
 if(dopoll & MEMORYDEMON) flex_demon();
 if(dopoll & BATCH)       dobatch();
}


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



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




}


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




}



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





}


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





}



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


int loadfile(int type,char * name,int xvolatile)
{
 if(type==SPRITE) return(loadspritefile(name));
 else
 if(type==DRAW)   return(loaddrawfile(name));
 else
 if(type==DIR)    return(loadbatch(name));
 else         
                  return(0);      /* could not load it */
 xvolatile=0;
}



void loadfilepost(int type)
{
 type=0;
}




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

int goodloadtype(int type)
{
 if(type==DRAW || type==SPRITE)
 {
  if(mhandle==whandle[SPRITEW]  || mhandle==whandle[DRAWW] 
                                || mhandle==-2) return(1);
 }
 else
 {
  if(type==DIR && mhandle==-2) return(3);
 }

 return(0);
}




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


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

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

void scrapfile(void)
{
 if(!getenv("Wimp$Scrap"))
 {
  errorbox("<Wimp$Scrap> not defined");
  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;
}






void dataloadack(void)
{


}



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

void savedata(void)
{
 int    saverefx;

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

 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);
}



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;
 }


 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);
 }

}




void opendata(void)
{

}




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("Unexpected RAM Fetch packet");
  return;
 }

 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 */

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  datasaveref;

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 */

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)
 {
 }
}



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

 return;

 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())
 {
  cblock[6]=0x1FC;
  wimp_sendmessage(8,(wimp_msgstr *)cblock,origtask);
 }
}



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);
}



void setslotsize(void)
{
 int size;

 size=wimpevent.data.msg.data.words[0];
/* if(size>=0) setmem(size); */

 if(wimpevent.e==18) 
   {
    wimpfirst.data.msg.hdr.your_ref=wimpfirst.data.msg.hdr.my_ref;
    wimp_sendmessage(19,&wimpfirst.data.msg,wimpfirst.data.msg.hdr.task);
   }
}


/* type 19 messages */

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();
}




/* type 17 & 18 messages */

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   0x400C0: /* dynamic menus */
                   menumessage();
                   break;
   case   0x400C1: setmodevars();
                   break;
   case   0x400C5: setslotsize();
                   break;
   case   0x80147: /* setprinterdriver();  */
                   break;
   case   0x80143: /* printinitdriver(); */
                   break;

   case   0x80140: printfilepd();
                   break;

   case   0x80145: printfileodd();
                   break;

   case   0x80144:
                   break;



  default        :
                   break;

  }
}





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



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



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

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

 /* leaves here */

 pollexit();

 if(dopollidle || zflags) wimp_poll(wimp_ENULL,&wimpevent);
 else
 {
  timeout=monotonic()+6000;
  wimp_pollidle(wimp_ENULL,&wimpevent,timeout);
 }

 pollenter();

 /* returns here */

 code=wimpevent.e;

 oldzmask=zmask;
 zmask|=zflags;

 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 17:
       case 18:
                message();
                break;

       case 19: 
                acknowledged();
                break;
 }

 zmask=oldzmask;

 return(code);
}












int main(int argc,char * argv[])
{ 
 setlocale(LC_ALL,"ISO8859-1");

 wimpt_init("Trace");   /* boots task */

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

 flex_init();

/* loadsprites(); */

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

 loadchoices();

 picinit();

 fitinit();


 timeout=monotonic()+6000;

 while(1) poll(0);

 return(0);
}

