/* ->c.wos */

/* Ovation!   (c) D. J. Pilling,  December 1988                     */
/*                       Wimp/OS routines                             */

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

#include "h.os"
#include "h.wimp"
#include "h.sprite"
#include "h.werr"
#include "h.wimpt"
#include "h.bbc"
#include "h.akbd"
#include "h.kernel"
#include "h.swis"
#include "h.font"

#include "h.Drawlevel0"

#include "h.swinos"

#include "h.wos"
#include "h.main"
#include "h.timex"
#include "h.strdef"
#include "h.view"
#include "h.mym"
#include "h.ram"
#include "h.key"
#include "h.fsx"
#include "h.trans"


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

wimp_eventstr wimpevent,wimpfirst;
int           icon;
int           ewindow;
int           buttons;
int           mousex,mousey,mhandle,micon;
int           x0,x1,y0,y1,bx,by,bhandle,scx,scy,wflags;
int           ix0,ix1,iy0,iy1;
int           chandle,cicon;
int           ox0,ox1,oy0,oy1;


int draghandle;
int dragtype;

int timeout;


int wimp_version;


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

int deltax;
int deltay;
int maskx;
int masky;
int screenx;
int screeny;
int lndeltax;
int lndeltay;
int ncolours;
int gcharsizex;
int gcharsizey;
int gcharspacex;
int gcharspacey;
int ln2bpp;

static wimp_palettestr vdupal;

int hscrlbar=40;
int vscrlbar=40;



void getdeltas(int mode,int * dx,int * dy)
{
 int xospx,yospx;
 xospx=(1 << bbc_modevar(mode,bbc_XEigFactor));
 yospx=(1 << bbc_modevar(mode,bbc_YEigFactor));
 *dx=xospx;
 *dy=yospx;
}



void getbpp(int mode,int * rln2bpp,int * bitmask)
{
 int ln2bpp=bbc_modevar(mode,bbc_Log2BPP); 
 int max=1<<ln2bpp;
 int mask=0;
 int i;

 for(i=0;i<max;i++) mask|=(1<<i);

 *rln2bpp=ln2bpp;
 *bitmask=mask;
}



void vdupalvars(void)
{
 wimp_readpalette(&vdupal);
}



void vdumodevars(void)
{
 int xpic,ypic;

 xpic=bbc_vduvar(bbc_XWindLimit);
 ypic=bbc_vduvar(bbc_YWindLimit);

 lndeltax=bbc_vduvar(bbc_XEigFactor);
 lndeltay=bbc_vduvar(bbc_YEigFactor);
 deltax=(1 << lndeltax);
 deltay=(1 << lndeltay);

 maskx=0xFFFFFFFF-(deltax-1);
 masky=0xFFFFFFFF-(deltay-1);

 screenx=(xpic+1)*deltax;
 screeny=(ypic+1)*deltay;

 ncolours=bbc_vduvar(bbc_NColour);

 gcharsizex=bbc_vduvar(bbc_GCharSizeX);
 gcharsizey=bbc_vduvar(bbc_GCharSizeY);
 gcharspacex=bbc_vduvar(bbc_GCharSpaceX);
 gcharspacey=bbc_vduvar(bbc_GCharSpaceY);
 ln2bpp=bbc_vduvar(bbc_Log2BPP); 

 vdupalvars();
}





void seti(handle,icon,eor,bic) int handle,icon,eor,bic;
{
 wimp_set_icon_state(handle,icon,eor,bic);
}


void select(handle,icon) int handle,icon;
{
 seti(handle,icon,0x200000,0x200000);
}


void deselect(handle,icon) int handle,icon;
{
 seti(handle,icon,0,0x200000);
}


void selectst(int handle,int icon,int state)
{
 if(state) select(handle,icon);
 else      deselect(handle,icon);
}


void writeableicon(int window,int icon)
{
 seti(window,icon,0xF000,0xF000);
}


void unwriteableicon(int window,int icon)
{
 seti(window,icon,0x6000,0xF000);
}



void shadeicon(int window,int icon)
{
 seti(window,icon,0x400000,0x400000);
}


void unshadeicon(int window,int icon)
{
 seti(window,icon,0x000000,0x400000);
}



void shadeicon2(int window,int icon)
{
 seti(window,icon,0x3000000,0xF000000);
}


void unshadeicon2(int window,int icon)
{
 seti(window,icon,0x7000000,0xF000000);
}


/*

void makemenuicon(int window,int icon)
{
 seti(window,icon,0x9000,0xF000);
}


void unmakemenuicon(int window,int icon)
{
 seti(window,icon,0x0,0xF000);
}


void makemenust(int window,int icon,int state)
{
 if(state) makemenuicon(window,icon);
 else      unmakemenuicon(window,icon); 
}

 */


void shadeiconst(int window,int icon,int state)
{
 if(state) shadeicon(window,icon);
 else      unshadeicon(window,icon);
}

static void shadeiconst2(int window,int icon,int state)
{
 if(state) shadeicon2(window,icon); 
 else      unshadeicon2(window,icon);
}



void getpointer(void)
{
 wimp_mousestr mstr;
 wimp_get_point_info(&mstr);
 mousex=mstr.x;
 mousey=mstr.y;
 buttons=mstr.bbits;
 mhandle=mstr.w;
 micon  =mstr.i;
}


void getw(handle) int handle;
{
 wimp_wstate winds;
 wimp_get_wind_state(handle,&winds);
 x0=winds.o.box.x0;
 y0=winds.o.box.y0;
 x1=winds.o.box.x1;
 y1=winds.o.box.y1;
 scx=winds.o.x;
 scy=winds.o.y;
 bhandle=winds.o.behind;
 wflags=winds.flags;
 bx=x0-scx;
 by=y1-scy;
}

void geti(handle,icon) int handle,icon;
{
 wimp_icon istate;
 wimp_get_icon_info(handle,icon,&istate);
 ix0=istate.box.x0;
 iy0=istate.box.y0;
 ix1=istate.box.x1;
 iy1=istate.box.y1; 
}




void dragicon(int mx,int my,int w,int i)
{
 wimp_dragstr drg;

 draghandle=w;
 getw(w);
 geti(w,i);

 drg.window=w;
 drg.type=5;
 drg.box.x0=bx+ix0;
 drg.box.y0=by+iy0;
 drg.box.x1=bx+ix1;
 drg.box.y1=by+iy1;
 drg.parent.x0=drg.box.x0-mx;
 drg.parent.y0=drg.box.y0-my;
 drg.parent.x1=drg.box.x1-mx+screenx;
 drg.parent.y1=drg.box.y1-my+screeny;

 wimp_drag_box(&drg);
}


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

static int dragaspritestarted;

void dragasprite(int w,int i)
{
 os_regset rx;
 int       coords[4];

 {
  rx.r[0]=161;
  rx.r[1]=28;
  os_swix(OS_Byte,&rx);
  if(rx.r[2] & 0x2)
  {
   getw(w);
   geti(w,i);

   coords[0]=bx+ix0;
   coords[1]=by+iy0;
   coords[2]=bx+ix1;
   coords[3]=by+iy1;

   rx.r[0]=(01)+((01)<<2)+((00)<<4)+((1)<<6)+((1)<<7);
   rx.r[1]=1;
   rx.r[2]=(int)iconaddr(w,i);
   rx.r[3]=(int)coords;

   dragaspritestarted=(os_swix(DragASprite_Start,&rx)==NULL);
  }
 }
}

void dragaspritestop(void)
{
 os_regset rx;
 if(dragaspritestarted) os_swix(DragASprite_Stop,&rx);
}

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


void open(int handle,int x0,int y0,int x1,int y1,int scx,int scy,int behind)
{
 wimp_openstr oblock;
 oblock.w=handle;
 oblock.box.x0=x0;
 oblock.box.x1=x1;
 oblock.box.y0=y0;
 oblock.box.y1=y1;
 oblock.x=scx;
 oblock.y=scy;
 oblock.behind=behind;
 wimp_open_wind(&oblock);
}

void extent(int handle,int x0,int y0,int x1,int y1)
{
  wimp_redrawstr eblock;
  eblock.w=handle;
  eblock.box.x0=x0;
  eblock.box.y0=y0;
  eblock.box.x1=x1;
  eblock.box.y1=y1;
  wimp_set_extent(&eblock);
}


char * iconaddr(handle,icon) int handle,icon;
{ 
 static wimp_icon istate;
 wimp_get_icon_info(handle,icon,&istate);

 if(istate.flags & 0x100) return(istate.data.indirecttext.buffer);
 else return(istate.data.text);
}



void caret(int handle,int icon,int x,int y,int height,int index)
{
  wimp_caretstr cblock;
  cblock.w=handle;
  cblock.i=icon;
  cblock.x=x;
  cblock.y=y;
  cblock.height=height;
  cblock.index=index;
  wimp_set_caret_pos(&cblock);
}


void iecarrot(int wh,int ih)
{ 
 caret(wh,ih,0,0,-1,strlen(iconaddr(wh,ih)));
}



/*

void incarrot(int wh,int ih)
{
 char * c=iconaddr(wh,ih);
 while(1)
 {
  if((*c<'0' || *c>'9') && *c!='.' && *c!='/') break;
  c++;
 }
 caret(wh,ih,0,0,-1,c-iconaddr(wh,ih));
}
 */



void setfocus(int handle)
{
 caret(handle,-1,200,200,20,0);
}




void findcaret(void)
{ 
 wimp_caretstr cblock;
 wimp_get_caret_pos(&cblock);
 chandle=cblock.w;
 cicon=cblock.i;
}



void writeicon(int window,int icon,char * string)
{
 int             more;
 wimp_icon       isblock;
 wimp_icreate    iblock;
 wimp_redrawstr  rblock;
 wimp_caretstr   cblock;
 int             len;


 wimp_get_caret_pos(&cblock);

 wimp_get_icon_info(window,icon,&isblock);

 if(isblock.flags & 0x100)
 {
  xstrncpy(isblock.data.indirecttext.buffer,string,
           isblock.data.indirecttext.bufflen);
 }
 else
 {
  xstrncpy(isblock.data.text,string,12);
  wimp_delete_icon(window,icon);
  iblock.w=window;
  iblock.i=isblock;
  wimp_create_icon(&iblock,&icon);
 }
    rblock.w=window;
    rblock.box=isblock.box;
  
   wimp_update_wind(&rblock,&more);
   while(more)
   {
   wimp_get_rectangle(&rblock,&more);
   }
    
 if(cblock.i==icon && cblock.w==window)
 {
  len=strlen(string);
  cblock.index=len;
  wimp_set_caret_pos(&cblock);
 }
}


void writeiconf(int window,int icon,char * format, ...)
{
 va_list args;
 char v[292];
 va_start(args, format);
 vsprintf(v, format, args);
 writeicon(window,icon,v);
 va_end(args);
}



os_error * writevalid(int window,int icon,char * string)
{ 
 os_error      * err;
 wimp_icon       isblock;

 err=wimp_get_icon_info(window,icon,&isblock);

 if(!err)
 {
  strcpy(isblock.data.indirecttext.validstring,string);
  err=wimp_set_icon_state(window,icon,0,0);
 }
 return(err);
}



int geticonint(int handle,int icon,int * val)
{
 int code;
 int temp;

 code=sscanf(iconaddr(handle,icon),"%d",&temp);
 if(code==1) *val=temp;
 return(code==1);
}



void setspa(int window,int icon,int len,char * name)
{ 
 wimp_icon       isblock;
 wimp_icreate    iblock;

 wimp_get_icon_info(window,icon,&isblock);

 isblock.data.indirectsprite.spritearea=sprites;
 isblock.data.indirectsprite.name=name;
 isblock.data.indirectsprite.nameisname=len;

 isblock.flags|=wimp_INDIRECT;

 wimp_delete_icon(window,icon);
 iblock.w=window;
 iblock.i=isblock;
 wimp_create_icon(&iblock,&icon);
}


void setindirect(int window,int icon,int len,char * string)
{ 
 wimp_icon       isblock;
 wimp_icreate    iblock;

 wimp_get_icon_info(window,icon,&isblock);

 isblock.data.indirecttext.buffer=string;
/* isblock.data.indirecttext.validstring=NULL; */
 isblock.data.indirecttext.bufflen=len;

 isblock.flags|=wimp_INDIRECT;

 wimp_delete_icon(window,icon);
 iblock.w=window;
 iblock.i=isblock;
 wimp_create_icon(&iblock,&icon);
}





void radioon(int window,int icon)
{
 writeicon(window,icon,"radioon");
}


void radiooff(int window,int icon)
{
 writeicon(window,icon,"radiooff");
}


void radiost(int window,int icon,int state)
{
 if(state) radioon(window,icon);
 else      radiooff(window,icon);
}


void opton(int window,int icon)
{
 writeicon(window,icon,"opton");
}


void optoff(int window,int icon)
{
 writeicon(window,icon,"optoff");
}


void optst(int window,int icon,int state)
{
 if(state) opton(window,icon);
 else      optoff(window,icon);
}


/* complete repaint of window contents */

void refreshwindow(int handle)
{
 wimp_redrawstr r;
 getw(handle);
 r.box.x0=x0-bx;
 r.box.x1=x1-bx;
 r.box.y0=y0-by;
 r.box.y1=y1-by;
 r.w=handle;
 wimp_force_redraw(&r);
}


os_error * oscli(char * string)
{
 return(os_cli(string));
}


void fx(int a,int x,int y)
{
 os_regset rx;

 rx.r[0]=a;
 rx.r[1]=x;
 rx.r[2]=y;

 os_swix(OS_Byte,&rx);
}


int os3(void)
{
 os_regset rx;

 rx.r[0]=129;
 rx.r[1]=0;
 rx.r[2]=0xFF;

 os_swix(OS_Byte,&rx);

 return(rx.r[1]>=0xA4);
}


void addmessages(int * mess)
{
 os_regset rx;

 rx.r[0]=(int)mess;

 os_swix(Wimp_AddMessages,&rx);
}



/*****************************************************************************/
                               /* Hourglass code */


/*

void hourglasspc(int percent)
{
  os_regset rx;
  rx.r[0]=percent;
  os_swix(Hourglass_Percentage,&rx);
}


void hourglasssmash(void)
{
  os_regset rx;
  os_swix(Hourglass_Smash,&rx);
}

 */

void hourglassoff(void)
{
  os_regset rx;
  os_swix(Hourglass_Off,&rx);
}


void hourglasson(void)
{
  os_regset rx;
  os_swix(Hourglass_On,&rx);
}

/*

void hourglassonafter(int delay)
{
  os_regset rx;
  rx.r[0]=delay;
  os_swix(Hourglass_Start,&rx);
}

 */



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


os_error * throwbackstart(void)
{
 os_error * ep;
 os_regset  rx;

 ep=os_swix(DDEUtils_ThrowbackStart,&rx);

 return(ep);
}


os_error * throwbackend(void)
{
 os_error * ep;
 os_regset  rx;

 ep=os_swix(DDEUtils_ThrowbackEnd,&rx);

 return(ep);
}



os_error * throwbacksend(int reason,...)
{
 os_error * ep;
 os_regset  rx;

 va_list args;

 va_start(args, reason);

 rx.r[0]=reason;

 switch(reason)
 {
  case   Throwback_ReasonProcessing:
                                    rx.r[2]=(int)(va_arg(args,int));
                                    break;

  case Throwback_ReasonErrorDetails:
                                    rx.r[2]=(int)(va_arg(args,int));
                                    rx.r[3]=va_arg(args,int);
                                    rx.r[4]=va_arg(args,int);
                                    rx.r[5]=(int)(va_arg(args,int));
                                    break;

  case  Throwback_ReasonInfoDetails:
                                    rx.r[2]=(int)(va_arg(args,int));
                                    rx.r[3]=va_arg(args,int);
                                    rx.r[4]=0;
                                    rx.r[5]=(int)(va_arg(args,int));
                                    break;
 }


 va_end(args);

 ep=os_swix(DDEUtils_ThrowbackSend,&rx);

 return(ep);
}


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


void centerwindow(wimp_wstate * wst,int handle,int i)
{
  int width;
  int height;
  int left;
  int top;

  wimp_get_wind_state(handle,wst);

  width=wst->o.box.x1-wst->o.box.x0;
  height=wst->o.box.y1-wst->o.box.y0;

  left=(screenx-width)>>1;
  top=(screeny-height)>>1;

  left+=hscrlbar*(i % 4);
  top-=vscrlbar*(i % 5);

  wst->o.box.x0=left;
  wst->o.box.y0=top;
  wst->o.box.x1=wst->o.box.x0+width;
  wst->o.box.y1=wst->o.box.y0+height;

  wst->o.behind=-1;
}



void popup(int handle,int i)
{
 wimp_wstate wst;
 centerwindow(&wst,handle,i);
 wimp_open_wind(&wst.o);
}




void reopenw(int handle)
{
 wimp_wstate wst;
 wimp_get_wind_state(handle,&wst);
 wimp_open_wind(&wst.o);
}


/* moves a window forward to the front of stack */

void forward(int handle)
{
 wimp_wstate wblock;
 wimp_get_wind_state(handle,&wblock);
 wblock.o.behind=-1;
 wimp_open_wind(&wblock.o);
}


void openatscroll(int handle,int scx,int scy)
{
 wimp_wstate wblock;
 wimp_get_wind_state(handle,&wblock);
 wblock.o.x=scx;
 wblock.o.y=scy;
 wimp_open_wind(&wblock.o);
}


/* force window to lie inside screen border etc. */

void clipwindow(wimp_openstr * wopen,int andscroll)
{
 int maxwidth;
 int maxheight;

 if(wopen->box.x0<deltax) 
 {
  wopen->box.x1-=(wopen->box.x0-deltax);
  wopen->box.x0=deltax;
 }

 maxwidth=andscroll?screenx-vscrlbar:screenx;

 if((wopen->box.x1-wopen->box.x0)>=maxwidth)
 {
  wopen->box.x1=wopen->box.x0+maxwidth;
 }


 if(wopen->box.y1>(screeny-hscrlbar-deltay))
 {
  wopen->box.y0-=wopen->box.y1-(screeny-hscrlbar-deltay);
  wopen->box.y1=screeny-hscrlbar-deltay;
 }

 maxheight=screeny-(3*hscrlbar)/2;

 if((wopen->box.y1-wopen->box.y0)>maxheight)
 {
  wopen->box.y0=wopen->box.y1-maxheight;
 }

}



void popupc(int tag)
{
 if(!createwindow(tag)) return;
 popup(whandle[tag],0);
}



/*  wimp_mousestr mstr;
  wimp_get_point_info(&mstr);
  wimp_create_menu((wimp_menustr *)window,mstr.x-80,mstr.y+80); */

 /* zapmenu(); */


/* pops up menu style window */

void menuwindow(int handle)
{
 wimp_wstate wst;

 centerwindow(&wst,handle,0);
 wimp_create_menu((wimp_menustr *)handle,wst.o.box.x0,wst.o.box.y1);
 repopf=0;
}


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

static int conf_ok;
int doconfirm=1;
static int conmode;
 /* CONYN Yes/No CONDN Discard/Cancel CONSDC Save/Discard/Cancel */


void conficon(void)
{
 switch(icon)
 {
  case 0:
  case 1:
         conf_ok=icon;
         break;

  case 4:
         conf_ok=-1;  /* Cancel */
         break;

  case 5:
         conf_ok=0;   /* Discard==No */
         break;

  case 3:
         if(conmode==CONDC) conf_ok=1;  /* Discard same as  YES */
                                        /* Are you sure you want to Quit? */
         else
         if(conmode==CONSDC) conf_ok=1; /* Save  */
         break;
 }
}


void confkey(int * key)
{
 if(*key==27) conf_ok=-1;
 else
 return;
 *key=-1;
}


/* returns 1==OK 0==NO -1==FORGET IT */


int confirm(int mode,char * format, ...)
{
 va_list args;
 char string[256];
 int handle;

 va_start(args, format);
 vsprintf(string, format, args);
 va_end(args);
 trans(string,sizeof(string));

 if(!doconfirm)
 {
  if(mode==CONSDC) return(0);
  else             return(1);
 }


 if((handle=createwindow(CONF))==NULL) return(-1);

 conmode=mode;

 if(mode==CONYN)
 {
  wimp_delete_icon(handle,3);
  wimp_delete_icon(handle,4);
  wimp_delete_icon(handle,5);
 }
 else
 if(mode==CONDC)
 {
  wimp_delete_icon(handle,0);
  wimp_delete_icon(handle,1);
  wimp_delete_icon(handle,5);
 }
 else
 if(mode==CONSDC)
 {
  writeicon(handle,3,transtoken("Save"));
  wimp_delete_icon(handle,0);
  wimp_delete_icon(handle,1);
 }

 writeicon(handle,2,string);
 conf_ok=-2;

 menuwindow(handle);

 while(conf_ok==-2)
 {
  getw(handle);
  if(!(wflags & 0x10000))
  {
   while(1)
   {
    getpointer();
    if(!buttons) break;
    poll(0);
   }
   conf_ok=-1;
   break;
  }
  poll(0);
 }


 zapmenu();
 closedownt(CONF);

 return(conf_ok);
}


/***************************************************************************/
#define ReportError         0x000400DF

os_error * myreporterror(os_error* er, wimp_errflags flags)
{
 /* resetpointer();  */
 trans(er->errmess,sizeof(er->errmess));
 return os_swi3(os_X | ReportError, (int) er, flags, (int)"ArcFax");
}


static os_error * myreporterrors(char * message, wimp_errflags flags)
{
 os_error e;
 e.errnum = 0;
 strcpy(&e.errmess[0], message);
 return(myreporterror(&e, flags));
}



void werr(int fatal, char* format, ...)
{
 va_list va;
 os_error e;
 e.errnum = 0;
 va_start(va, format);
 vsprintf(&e.errmess[0], format, va);
 va_end(va);
 myreporterror(&e, 0);
 if (fatal) exit(1);
}



void errorbox(char * message)
{
 myreporterrors(message,0);
}

/*
void messagebox(char * message)
{
 myreporterrors(message,1+16);
}
*/

void fatalerror(char * message)
{
 errorbox(message);
 exit(1);
}

void abend(os_error * e)
{
 /* if e is true, abend */
 if(e)
 {
  myreporterror(e,0);
  exit(1);
 }
}


void report(os_error * e)
{
 if(e)
 {
  myreporterror(e,0);
 }
}


/****************************************************************************/
                /* filing system bits and pieces */



int cstrcmp(char * first,char * second)
{
 int f;
 int s;

 while(1)
 {
  f=toupper(*first++);
  s=toupper(*second++);
  if(f!=s || !f) return(f-s);
 }
}




char * xstrncpy(char *s1,char *s2,int n)
{

 while(n-->0)
   if((*s1++=*s2++)<32) break;
 *(s1-1)=0;

 return(s1);
}






void setftype(char * filename,int type)
{
 char string[132]; 
 sprintf(string,"settype %s %X",filename,type);
 oscli(string);
}



char * leaf(char * filename)
{ char * p;

  p=strrchr(filename,'.');
  if(!p) p=filename; else p+=1;
  return(p);
}




int filetype(load) int load;
{
 if((load & 0xFFF00000)==0xFFF00000)
           return((load >> 8) & 0xFFF);
 else return(CODE);
}




os_error * stat(char * name,fstat * f)
{
 os_error  *  errpoi;
 os_filestr  fiblock;

 fiblock.action=5;
 fiblock.name=name;
 errpoi=os_file(&fiblock);
 if(errpoi) return(errpoi);

 f->object=fiblock.action;
 f->length=fiblock.start;
 f->load=fiblock.loadaddr;
 f->exec=fiblock.execaddr;
 f->acc =fiblock.end;

 f->type=filetype(f->load);

 return(NULL);
}




os_error * statx(char * name,fstat * f)
{
 os_error  *  errpoi;
 os_filestr  fiblock;

 fiblock.action=17;
 fiblock.name=name;
 errpoi=os_file(&fiblock);
 if(errpoi) return(errpoi);

 f->object=fiblock.action;
 f->length=fiblock.start;
 f->load=fiblock.loadaddr;
 f->exec=fiblock.execaddr;
 f->acc =fiblock.end;

 f->type=filetype(f->load);

 return(NULL);
}


os_error * stamp(char * name,fstat * f)
{
 os_filestr  fiblock;

 fiblock.action=1;
 fiblock.name=name;
 fiblock.loadaddr=f->load;
 fiblock.execaddr=f->exec;
 fiblock.start=0;
 fiblock.end=f->acc;
 return(os_file(&fiblock));
}


/*

int filelength(char * filename)
{
 fstat           f;
 os_error * errpoi;

 errpoi=stat(filename,&f);
 if(errpoi) return(0);

 return(f.length);
}
 
 */

/* returns 0 ==does not exist  1==file 2==dir */


int fexists(char * name)
{
 os_filestr  fiblock;

 fiblock.action=17;  /* don't use path */
 fiblock.name=name;
 os_file(&fiblock);

 return(fiblock.action);
}






char * kerror(void)
{
 _kernel_oserror * kerr;
 kerr=_kernel_last_oserror();
 if(kerr->errnum) return(kerr->errmess);
 else             return("");
}



static int  dirposn;

void startscan(void)
{
 dirposn=0;
}

int getdirposn(void)
{
 return(dirposn);
}

void setdirposn(int posn)
{
 dirposn=posn;
}


/* PRM page 877 */
/* note that you can read nothing, but you have to continue */
/* search is only over when dirposn==-1                     */


int  nextitem(char * dirname,fxstat * f,char * wild)
{
  char         buff[256];
  os_error   * errpoi;
  os_gbpbstr   gpblock;

  while(1)
  {
   if(dirposn==-1) return(0);

   gpblock.seq_point=dirposn;
   gpblock.action=10;
   gpblock.file_handle=(int)dirname;
   gpblock.data_addr=buff;
   gpblock.number=1;
   gpblock.buf_len=0x100;
   gpblock.wild_fld=wild;

   errpoi=os_gbpb(&gpblock);

   if(errpoi) return(0);

   dirposn=gpblock.seq_point;

   if(gpblock.number) break;
  }

  f->f.load  =(* (int *)(buff+0x0));
  f->f.exec  =(* (int *)(buff+0x4));
  f->f.length=(* (int *)(buff+0x8));
  f->f.acc   =(* (int *)(buff+0xC));
  f->f.object=(* (int *)(buff+0x10));
  strcpy(f->name,buff+0x14);
  f->f.type=filetype(f->f.load);

  return(1);
}



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

int taskhandle;
int iconbaricon;

#define WORKSIZE 0x3800

static char workspace[WORKSIZE];   /* workspace for holding indirected icons */
static char * worklo=workspace;
static char * workhi=workspace+WORKSIZE;


#define WINDSIZE 0x6000


int     whandle[MAXI];           /* wimp handle for internal handle */
wimp_wind * windpoi[MAXI];       /* pointer to window definition    */

static char windspc[WINDSIZE];  /* workspace for holding window definitions */
static char *  windlo=windspc;
static char *  windhi=windspc+WINDSIZE;

#define SPSIZE 0x20000          /* 0x5A00 */          /* 0x4800 */
char    sprites[SPSIZE];        /* pointer to sprite space */


#define ReadSysInfo         (0x000400c0+50)

void starttask(void)
{
 os_regset r;

 taskhandle=wimpt_task();

 r.r[0]=0;
 os_swix(ReadSysInfo,&r);
 if(r.r[0]==1)
 {
  errorbox("Not within desktop environment");
  wimp_taskclose(taskhandle);
  exit(1);
 }
}



static char iconsp[12];
static char * hsprites[4]={"n_!arcfax","!arcfaxrx","!arcfaxtx","g_!arcfax"};


void seticonbar(void)
{
 wimp_icreate wic;
 wic.w=-1;
 wic.i.box.x0=0;
 wic.i.box.y0=0;
 wic.i.box.x1=68;
 wic.i.box.y1=68;
 wic.i.flags=wimp_ISPRITE | wimp_IHCENTRE | wimp_IVCENTRE | 
             0x3000       | wimp_INDIRECT;

 wic.i.data.indirectsprite.name=iconsp;
 wic.i.data.indirectsprite.spritearea=(void *)1;
 wic.i.data.indirectsprite.nameisname=12;

 strcpy(iconsp,hsprites[0]);

 wimp_create_icon(&wic,&iconbaricon);
}


void sethearsayicon(int which)
{
 static int lasttime=0;

 if(which!=lasttime)
 {
  strcpy(iconsp,hsprites[which]);
  seti(-1,iconbaricon,0,0);
  lasttime=which;
 }
}




void loadsprites(void)
{ 
 char string[256];

 sprite_area_initialise((sprite_area *)sprites,SPSIZE);

 sprintf(string,"%s.Sprites",path(AFXRD));

 abend(sprite_area_load((sprite_area *)sprites,string)); 

 if(!os3())
 {
  sprintf(string,"%s.Sprites2",path(AFXRD));
  report(sprite_area_merge((sprite_area *)sprites,string));
 }
}




windowname windownames[MAXI]=
{
 "info",        INFO,
 "savefile",    SAVEFILE0,
 "conf",        CONF,
 "directory",   FILER,
 "Printing",    PSTAT,
 "zoom",        ZOOM,
 "password",    PASSWORD,
 "settings",    STATUS,
 "Schedule",    SX,
 "Entry",       ENTRY,
 "Teledir",     TDIR,
 "view",        VX,
 "btools",      VXTOOLS,
 "after",       AFTER,
 "group",       GROUP,
 "NewSet",      SETNEWFAX,
 "finfo",       FINFO,
 "Process",     PROCESS,
 "VXPrint",     VXPRINT,
 "Control",     CONTROL,
 "Newfax",      NEWFAX,
 "Modem",       MODEM,
 "Fax",         FAX,
 "Batch",       BATCH,
 "Printer",     PRINTER,
 "Log",         LOG,
 "Voice",       VOICE,
 "Replay",      REPLAY,
 "Grabber",     GRABBER,
 "DBug",        DBUG,
 "server",      SERVER,
 "vinfo",       VINFO,
 "dinfo",       DINFO,
 "Warn",        DWARN,
 "Standalone",  STANDALONE,
};






static void loadtemp(int from,int n,char * sub)
{
 wimp_wind * ww;
 char nbuff[16];
 wimp_template wtmp;
 int to=from+n;
 int i;
 char filename[FSMAXPATH];
 char * name;
 int    tag;

 sprintf(filename,"%s.%s",path(RESP),sub);
 abend(wimp_open_template(filename));

 for(i=from;i<to;i++)
 {
   name=windownames[i].name;
   tag=windownames[i].tag;

   strcpy(nbuff,name);
   ww=(wimp_wind *)windlo;

   wtmp.buf=ww;
   wtmp.work_free=worklo;
   wtmp.work_end=workhi;
   wtmp.font=0;
   wtmp.name=nbuff;
   wtmp.index=0;

   abend(wimp_load_template(&wtmp)); 
   worklo=wtmp.work_free;

   windpoi[tag]=ww;
   windlo=(char *)ww+sizeof(wimp_wind)+(ww->nicons)*sizeof(wimp_icon);

   if(windlo>windhi) fatalerror("No window space");
 }

/* dprintf(0,"windlo=%d windspc=%d  %d ",windlo,windspc,windlo-windspc);
 dprintf(1,"worklo=%d workspc=%d  %d ",worklo,workspace,worklo-workspace); */

 wimp_close_template();
}


void loadtemps(void)
{ 
 int i;
 for(i=0;i<MAXI;i++) whandle[i]=0;
 loadtemp(0,35,path(AFXT));
}


int createwindowsub(int tag,char * title)   /* called with tag for argument */
{
 int          wh;
 wimp_wind  * wp;
 os_error   * ep;

 if(whandle[tag]) return(whandle[tag]);

 wp=windpoi[tag];

 if(tag==REPLAY || tag==STATUS || tag==CONTROL)
  wp->spritearea=sprites;
 else
  wp->spritearea=(char *)1; /* use common sprites for these */

 if(title)
 {
  if(wp->titleflags & wimp_INDIRECT)
    strcpy(wp->title.indirecttext.buffer,title);
  else
    strcpy(wp->title.text,title);
 }


 ep=wimp_create_wind(wp,&wh);
 if(ep)
 {
  report(ep);
  wh=0;
 }

 whandle[tag]=wh;

 return(wh);
}


int createwindow(int tag) 
{
 return(createwindowsub(tag,NULL));
}



void closedownhandle(int * handle)
{
 if(handle)
 {
  if(*handle)
  {
   wimp_close_wind(*handle);
   wimp_delete_wind(*handle);
   *handle=0;
  }
 }
}


void closedownt(int tag)
{
 closedownhandle(&whandle[tag]);
}


void closedown(int window)
{
 int i;

 for(i=0;i<MAXI;i++)
 {
  if(whandle[i]==window)
  {
   closedownt(i);
   return;
  }
 }

 wimp_close_wind(window);
}




os_error * findwindowtask(int handle,int icon,int * task)
{
 os_error *  err;
 os_regset   rx;
 wimp_msgstr msg;

 rx.r[0]=19;
 rx.r[1]=(int)&msg;
 rx.r[2]=handle;
 rx.r[3]=icon;

 err=os_swix(Wimp_SendMessage,&rx);

 *task=rx.r[2];

 return(err);
}



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

/* #define PROD */



#ifndef DEMO 

#ifndef PROD

void dprintf(int line,char * format, ...)
{
 va_list args;
 char v[128];
 char string[128];

 va_start(args, format);
 vsprintf(v, format, args);

 sprintf(string,"%s$Debug",wimpt_programname());
 if(getenv(string))
 {
  bbc_vdu(4);bbc_vdu(30);
  while(line--) bbc_vdu(10);
  printf("%-40s",v);
  bbc_vdu(5);
  if(isshift) bbc_get(); 
 }

 va_end(args);
}

#else

void dprintf(int line,char * format, ...)
{
 va_list args;
 char v[128];
 va_start(args, format);
 vsprintf(v, format, args);

 va_end(args);
}

#endif

#else

void dprintf(int line,char * format, ...)
{
 va_list args;
 char v[128];
 va_start(args, format);
 vsprintf(v, format, args);

 va_end(args);
}

#endif



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




#define FONTCODE 26



int wimpavfontwidth=16;


int wimpfonthandle;
int wimpfontlead;
int wimpfontheight;
int wimpfontwidth;




void wimpfontstart(void)
{
 os_regset rx;
 char    * p;
 char      fontname[256];
 int       xsize=192;
 int       ysize=192;
 int       temp;
 font_info fi;
 int       i;
 int       j;

 wimpfonthandle=0;

 wimpfontheight=32;
 wimpfontwidth=wimpavfontwidth=16;
 wimpfontlead=0;


 if(wimp_version>=350) 
 {
  j=2;
  for(i=32;i<127;i++)
  {
   fontname[j]=i;
   j++;
  }
  for(i=160;i<256;i++)
  {
   fontname[j]=i;
   j++;
  }
  fontname[j]=0;


  rx.r[0]=1+(1<<30);
  rx.r[1]=(int)(fontname+2);
  rx.r[2]=j;


  if(!os_swix(Wimp_TextOp,&rx))
  {
   wimpavfontwidth=rx.r[0]/j;
  }
 }
 else
 {
  if((p=getenv("Wimp$Font"))!=NULL)
  {
   strcpy(fontname,p);
 
   if((p=getenv("Wimp$FontSize"))!=NULL) 
   {
    if(sscanf(p,"%d",&temp)==1) ysize=temp;
   }

   if((p=getenv("Wimp$FontWidth"))!=NULL)
   {
    if(sscanf(p,"%d",&temp)==1) xsize=temp;
   }

   font_find(fontname,xsize,ysize,0,0,&wimpfonthandle);
  }

  if(wimpfonthandle)
  {
   j=2;
   for(i=32;i<127;i++)
   {
    fontname[j]=i;
    j++;
   }
   for(i=160;i<256;i++)
   {
    fontname[j]=i;
    j++;
   }
   fontname[j]=0;


   rx.r[0]=wimpfonthandle;
   os_swix(Font_ReadInfo,&rx);
   wimpfontlead=rx.r[4];
   wimpfontheight=rx.r[4]-rx.r[2];
   wimpfontwidth=rx.r[3]-rx.r[1];


   fontname[0]=FONTCODE;
   fontname[1]=wimpfonthandle;

   font_stringbbox(fontname,&fi);

   wimpavfontwidth=(fi.maxx-fi.minx)/((j-2)*400);
  }
 }
}






void wimpfontend(void)
{
 if(wimpfonthandle)
 {
  font_lose(wimpfonthandle);
  wimpfonthandle=0;
 }
}





void stringat(int x,int y,char * string,int col,int height)
{
 os_regset rx;
 int       shift;


 if(wimpfonthandle)
 {
  shift=(height-deltay-wimpfontheight)/2+wimpfontlead;

  rx.r[0]=wimpfonthandle; 
  rx.r[1]=vdupal.c[(col>>8) & 0xFF].word;
  rx.r[2]=vdupal.c[col & 0xFF].word;
  rx.r[3]=14;

  os_swix(ColourTrans_SetFontColours,&rx);

  font_paint(string,font_ABS|font_OSCOORDS,x,y-shift);
 }
 else
 {
  y-=(height+deltay-32)/2;
 
  wimp_setcolour(col & 0xFF);
  wimp_setcolour(((col>>8) & 0xFF)|128);

  rx.r[0]=2+(1<<30);
  rx.r[1]=(int)string;
  rx.r[2]=-1;
  rx.r[3]=-1;
  rx.r[4]=x;
  rx.r[5]=y-32+8; /*2*deltay; */

  if(wimp_version<350 || os_swix(Wimp_TextOp,&rx))
  {
   bbc_move(x,y);
   bbc_stringprint(string);
  }
 }
}







void plinthtext(int x,int y,int w,int h,char * string,int col)
{
 int i;

 wimp_setcolour((col>>8) & 0xFF);
 bbc_rectanglefill(x,y,w,-h);

 wimp_setcolour(4);

 for(i=0;i<4;i+=deltay)
 {
  bbc_move(x,y+i);
  bbc_draw(x+w,y+i);
 }

 for(i=0;i<4;i+=deltax)
 {
  bbc_move(x+i,y);
  bbc_draw(x+i,y-h);
 }

 wimp_setcolour(0);

 for(i=0;i<4;i+=deltay)
 {
  bbc_move(x,y-h+i);
  bbc_draw(x+w,y-h+i);
 }

 for(i=0;i<4;i+=deltax)
 {
  bbc_move(x+w-i,y);
  bbc_draw(x+w-i,y-h);
 }

 stringat(x+6,y,string,col,h);
}


void noplinthtext(int x,int y,int w,int h,char * string,int col)
{
 wimp_setcolour((col>>8) & 0xFF);
 bbc_rectanglefill(x,y,w,-h);
 wimp_setcolour(7);
 bbc_rectangle(x,y,w,-h);
 stringat(x+8,y,string,col,h);
}


