/*->c.main                     */
/* CrossStar 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.def"

#include "h.wos"
#include "h.ram"
#include "h.mym"
#include "h.file"
#include "h.cross"
#include "h.dc"
#include "h.sp"
#include "h.vm"
#include "h.ana"

#include "h.main"



#ifndef PROD

/* #define DBUG  */

#endif

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



void palchange(void)
{

}



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

 if(wimpt_checkmode()) 
 {


 }
}



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[CROSS])  crossicon();
 else
 if(ewindow==whandle[CROSS2]) cross2icon();
 else
 if(ewindow==whandle[CROSS3]) cross3icon();
 else
 if(ewindow==whandle[WORDS])  ewordsicon();
 else
 if(ewindow==whandle[EDITD])  editdicon();
 else
 if(ewindow==whandle[SAVEFILE0])  saveicon();
 else
 if(ewindow==whandle[CONF])   conficon();
 else
 if(ewindow==whandle[CHECK])  checkicon();

}



void redraw(void)
{ 
 wimp_redrawstr redrawstr;
 int            more;

 ewindow=wimpevent.data.o.w;

 if(ewindow==whandle[WORDS]) redewords();
 else
 {
  redrawstr.w=ewindow;
  wimp_redraw_wind(&redrawstr,&more);
                             
  if(ewindow==whandle[CROSS3]) solredraw(&redrawstr,more);
  else
  if(ewindow==whandle[CROSS2]) gridredraw(&redrawstr,more);
 }
}



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

 if(ewindow==whandle[CROSS]) opencross(&(wimpevent.data.o));
 else
 if(ewindow==whandle[EDITD]) wopeneditd(&(wimpevent.data.o));
 else
 if(ewindow==whandle[CHECK]) wopencheck(&(wimpevent.data.o));
 else
 wimp_open_wind(&(wimpevent.data.o));
}


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

 if(ewindow==whandle[CROSS]) closecross();
 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[CROSS2])    cross2key(&key);
 else
 if(ewindow==whandle[EDITD])     editdkey(&key);
 else
 if(ewindow==whandle[SAVEFILE0]) savekey(&key);
 else
 if(ewindow==whandle[CONF])      confkey(&key);
 else
 if(ewindow==whandle[CHECK])     checkkey(&key);

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





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


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

 addzeroevent(DRAGZERO);
}



void zerodrag(void)
{
 if(dragtype==ZONEDRAG) cross2zero();




}



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 & DCDEMON)  editdemon(0);
 if(dopoll & MEMDEMON) memorydemon();
 if(dopoll & SAVEZERO) savezero();
}


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



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;





}



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

/* deals with *Hearsay filename case */

int loadanyfile(char * name)
{
 fstat f;
/* int code; */

 stat(name,&f);

 switch(f.type)
 {
  case CROSSF:
              return(loadgridopen(name));
              break;
 }
 return(0);
}





int loadfile(int type,char * name,int xvolatile)
{
 if(type==CROSSF)
 {
  if(mhandle==whandle[CROSS]  || mhandle==whandle[CROSS2] || 
     mhandle==whandle[CROSS3]) return(loadgrid(name));
  else
  if(mhandle==-2) return(loadgridopen(name));
 }
 else if((mhandle==whandle[EDITD] || mhandle==whandle[WORDS]) && 
                  type==TEXT) return(readdc(name));

 else if(mhandle==-2) return(checkfile(name));

 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==CROSSF)
 {
  if(mhandle==whandle[CROSS]  || mhandle==whandle[CROSS2] || 
     mhandle==whandle[CROSS3] || mhandle==-2) return(1);
 }
 else if((mhandle==whandle[EDITD] || mhandle==whandle[WORDS]) && 
           type==TEXT) return(1);
 else if(mhandle==-2) return(1);


 return(0);
}



int goodruntype(int type)
{
 if(type==CROSSF) return(1);
 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)
{
 int type=wimpevent.data.msg.data.dataopen.type;

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

  switch(type)
  {
   case CROSSF:
               if(loadgridopen(wimpevent.data.msg.data.dataload.name)==NOLOAD)
                                                                       return;
               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);
 }
}




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("CrossStar");   /* boots task */

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

/* loadsprites(); */

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

 crossboot();

 initsp();

 timeout=monotonic()+6000;

 loaddefaultgrid();

 if(argc==2) loadanyfile(argv[1]);
 while(1) poll(0);

 return(0);
}

