/* ->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.swinos"


#include "h.wos"
#include "h.main"
#include "h.key"
#include "h.mym"
#include "h.ram"






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

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


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 getcurdeltas(int * dx,int * dy)
{
 int lndeltax=bbc_vduvar(bbc_XEigFactor);
 int lndeltay=bbc_vduvar(bbc_YEigFactor);
 *dx=(1 << lndeltax);
 *dy=(1 << lndeltay);
}



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 getbpc(int mode,int * rln2bpp,int * bitmask)
{
 int ln2bpp=bbc_modevar(mode,bbc_Log2BPC); 
 int max=1<<ln2bpp;
 int mask=0;
 int i;

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

 *rln2bpp=ln2bpp;
 *bitmask=mask;
}




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



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

 */

/*

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

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

*/


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



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;

    wimp_get_caret_pos(&cblock);

    wimp_get_icon_info(window,icon,&isblock);

    if(isblock.flags & 0x100)
       strcpy(isblock.data.indirecttext.buffer,string);
    else
   {
    strcpy(isblock.data.text,string);
    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)
                                wimp_set_caret_pos(&cblock);
}


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


/*

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


void geto(int window)
{
wimp_redrawstr r;
r.w=window;
wimp_getwindowoutline(&r);
ox0=r.box.x0;
ox1=r.box.x1;
oy0=r.box.y0;
oy1=r.box.y1;
}



void setmouse(int x,int y)
{
  char blk[5];
  os_error * errpoi;

  blk[0]=3;
  blk[1]=x;blk[2]=x >> 8;
  blk[3]=y;blk[4]=y >> 8;

  errpoi=os_word(21,blk);
}



void refreshwindowtitle(int handle)
{
 wimp_redrawstr r;

 getw(handle);
 geto(handle);

 r.w=-1;
 r.box.x0=x0;
 r.box.x1=x1;
 r.box.y1=oy1;
 r.box.y0=y1;

 wimp_force_redraw(&r);
}


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



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


#define Hourglass_On    0x406C0
#define Hourglass_Off   0x406C1
#define Hourglass_Start 0x406C3
#define Hourglass_Percentage 0x406C4
#define Hourglass_Smash 0x406C2

/*

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

 */



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


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



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




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


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

int conf_ok;
int doconfirm=1;


void conficon(void)
{
 if(icon==0 || icon==1)
 {
  conf_ok=icon;
 }
}


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


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


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

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

 if(!doconfirm) return(1);

 if(!createwindow(CONF)) return(-1);
 writeicon(whandle[CONF],2,string);
 conf_ok=-2;

 menuwindow(whandle[CONF]);

 while(conf_ok==-2)
 {
  getw(whandle[CONF]);
  if(!(wflags & 0x10000))
  {
   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();  */
 return os_swi3(os_X | ReportError, (int) er, flags, (int)"Trace");
}


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


void memerr(void)
{
 errorbox("Not enough memory!");
}



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




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









/*

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


/* 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,fstat * 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->load  =(* (int *)(buff+0x0));
  f->exec  =(* (int *)(buff+0x4));
  f->length=(* (int *)(buff+0x8));
  f->acc   =(* (int *)(buff+0xC));
  f->object=(* (int *)(buff+0x10));
  strcpy(f->name,buff+0x14);
  f->type=filetype(f->load);

  return(1);
}



int monotonic(void)
{
 os_regset rx;
 os_swix(OS_ReadMonotonicTime,&rx);
 return(rx.r[0]);
}


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

int taskhandle;
int iconbaricon;

#define WORKSIZE 0x600

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


#define WINDSIZE 0x1000


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

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



#define SPSIZE  0x4000
/* 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);
 }
}



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;
  strcpy(wic.i.data.text,"!Trace");
  wimp_create_icon(&wic,&iconbaricon);
}


/*
void loadsprites(void)
{ 
 sprite_area_initialise((sprite_area *)sprites,SPSIZE);
 abend(sprite_area_load((sprite_area *)sprites,
                       "<Trace$Path>.resources.sprites"));
}
 */


typedef struct {char * name;int tag;} windowname;


windowname windownames[]=
{
 "Info",        INFO,
 "Savefile",    SAVEFILE0,
 "Confirm",     CONF,
 "Draw",        DRAWW,
 "Sprite",      SPRITEW,
 "Zoom",        ZOOM,
 "Finfo",       FINFO
};




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[64];
 char * name;
 int    tag;

 sprintf(filename,"<Trace$Path>.resources.%s",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;
 char * p;
 char   temp[64];

 if((p=getenv("Trace$Templates"))==NULL) p="Templates";

 strcpy(temp,p);

 for(i=0;i<MAXI;i++) whandle[i]=0;

 loadtemp(0,7,temp);
}



void writetitle(int tag,char * title)
{
 wimp_wind  * wp;
 wp=windpoi[tag];
 if(wp->titleflags && wimp_INDIRECT)
    strcpy(wp->title.indirecttext.buffer,title);
}



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==KEYPAD)
  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 closedownt(int tag)
{
 if(whandle[tag])
 {
  wimp_close_wind(whandle[tag]);
  wimp_delete_wind(whandle[tag]);
  whandle[tag]=0;
 }
}

void closedown(int window)
{
 int i;

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

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


#ifndef DEMO 

#ifndef PROD

void dprintf(int line,char * format, ...)
{
 va_list args;
 char v[128];
 va_start(args, format);
 vsprintf(v, format, args);
 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

