/*->c.wz */

#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.font"
#include "h.kernel"



#ifndef PROD

#define DBUG 

#endif


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



#define OS_SpriteOp 0x2E

os_error * sprite__op(os_regset *r)
{
  return os_swix(OS_SpriteOp, r);
}



void setfromarea(int op, sprite_area *area, os_regset *r)
{
  if (area == sprite_mainarea)
  {
    r->r[0] = op;
/*  r->r[1] unused */
  }
  else
  {
    r->r[0] = op + 256;
    r->r[1] = (int) area;
  }
}



void setfromtag(int op, sprite_area *area, sprite_id *spr, os_regset *r)
{
  if (area == sprite_mainarea)
  {
    r->r[0] = op;
 /* r->r[1] unused */
  }
  else
  {
    r->r[1] = (int) area;
    if ((spr->tag) == sprite_id_addr)
    {
      r->r[0] = 512 + op;
      r->r[2] = (int) (spr->s.addr);
    }
    else
    {
      r->r[0] = 256 + op;
      r->r[2] = (int) (spr->s.name);
    }
  }
}




/*

os_error * sprite_put_char_scaled(char ch,
                                  int x, int y,
                                  sprite_factors *factors)
{
  os_regset r;
  os_error *result;
  r.r[0] = 51;
  r.r[1] = ch;
  r.r[3] = x;
  r.r[4] = y;
  r.r[6] = (int) factors;
  result = sprite__op(&r);
  return result;
}

*/




void sprite_area_initialise(sprite_area *area, int length)
{
  area->size    = length; /* No SpriteOp to do this ! */
  area->number  = 0;
  area->sproff  = 16;
  area->freeoff = 16;
}




os_error * sprite_area_load(sprite_area *area, const char *filename)
{
  os_regset r;
  os_error *result;
  setfromarea(10, area, &r);
  r.r[2] = (int) filename;
  result = sprite__op(&r);
  return result;
}






os_error * sprite_readsize(sprite_area *area, sprite_id *spr,
                           sprite_info *resultinfo)
{
  os_regset r;
  os_error *result;
  setfromtag(40, area, spr, &r);
  result = sprite__op(&r);

  resultinfo->width = r.r[3] ;
  resultinfo->height = r.r[4] ;
  resultinfo->mask = r.r[5] ;
  resultinfo->mode = r.r[6] ;
  return result;
}




os_error * sprite_put_given(sprite_area *area, sprite_id *spr, int gcol_action,
                            int x, int y)
{
  os_regset r;
  os_error *result;
  setfromtag(34, area, spr, &r);
  r.r[3] = x;
  r.r[4] = y;
  r.r[5] = gcol_action;
  result = sprite__op(&r);
  return result;
}








os_error * sprite_put_scaled(sprite_area *area, sprite_id *spr,
                             int gcol_action,
                             int x, int y,
                             sprite_factors *factors,
                             sprite_pixtrans *pixtrans)
{
  os_regset r;
  os_error *result;
  int i;

  setfromtag(52, area, spr, &r);
  r.r[3] = x;
  r.r[4] = y;
  r.r[5] = gcol_action;
  r.r[6] = (int) factors;
  r.r[7] = (int) pixtrans;
  result = sprite__op(&r);
  return result;
}




os_error * sprite_create(sprite_area *area, char *name, sprite_palflag palflag,
                         int width, int height, int mode)
{
  os_regset r;
  os_error *result;
  setfromarea(15, area, &r); /* NB. Not all done in numeric order !! */
  r.r[2] = (int) name;
  r.r[3] = palflag;
  r.r[4] = width;
  r.r[5] = height;
  r.r[6] = mode;
  result = sprite__op(&r);
  return result;
}







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



#define  XOS_Write0           0x00000002 | os_X
#define  XOS_Plot             0x00000045 | os_X



os_error *bbc_tint(int type, int value)
{
   os_error *e = bbc_vdu(bbc_MultiPurpose);
   if (!e) e = bbc_vdu(17);
   if (!e) e = bbc_vdu(type & 3);
   if (!e) e = bbc_vdu((value << 6) & 0x0C0);
   if (!e) e = bbc_vduw(0);
   if (!e) e = bbc_vduw(0);
   if (!e) e = bbc_vduw(0);
   return(e);
}




/* Array of length of sequence for vdu codes. */ 
static char Qlen[32] =
{ 1,   /* VDU 0 */
  2,   /* next character to printer only */
  1,   /* printer on */
  1,   /* printer off */
  1,   /* print at text cursor */
  1,   /* print at graphics cursor */
  1,   /* enable VDU driver */
  1,   /* beep */
  1,   /* backspace */
  1,   /* forward space (horizontal tab) */
  1,   /* line feed */
  1,   /* up a line */
  1,   /* clear (text) screen */
  1,   /* carriage return */
  1,   /* page mode on */
  1,   /* page mode off */
  1,   /* clear graphics window */
  2,   /* define text colour */
  3,   /* define graphics colour */
  6,   /* define logical colour */
  1,   /* restore default palette */
  1,   /* disable VDU drivers */
  2,   /* Select screen mode */
  10,  /* VDU 23,.. */
  9,   /* set graphics window */
  6,   /* PLOT ... */
  1,   /* restore default windows */
  1,   /* ESCAPE char - no effect */
  5,   /* define text window */
  5,   /* define graphics origin */
  1,   /* home cursor */
  3    /* tab cursor */
/* and all the rest are 1 */
};



/* Multiple character VDU call. */
os_error *bbc_vduq(int c,...)
{
   os_error *e;
   va_list ap;
   int n;
   e = bbc_vdu(c);

   if ((c >= ' ') || e) return(e);

   va_start(ap, c);
   n = Qlen[c];

   while ((--n) && (!e)) e = bbc_vdu(va_arg(ap,int));

   va_end(ap);
   return(e);
}


 
os_error *bbc_stringprint(char *s)
{
  return(os_swi1(XOS_Write0, (int) s));
}




os_error *bbc_rectangle(int x, int y, int w, int h)
{
   os_error *e = bbc_move(x, y);
   if (!e) e = bbc_plot(bbc_SolidExFinal + bbc_DrawRelFore,  0,  h);
   if (!e) e = bbc_plot(bbc_SolidExFinal + bbc_DrawRelFore,  w,  0);
   if (!e) e = bbc_plot(bbc_SolidExFinal + bbc_DrawRelFore,  0, -h);
   if (!e) e = bbc_plot(bbc_SolidExFinal + bbc_DrawRelFore, -w,  0);
   return(e);
}


/* Plot a solid rectangle. Left X, bottom Y, Width, Height. */
os_error *bbc_rectanglefill(int x, int y, int w, int h)
{
   os_error *e = bbc_move(x, y);
   if (!e) e = bbc_plot(bbc_RectangleFill + bbc_DrawRelFore, w, h);
   return(e);
}




/* Set up graphics window. */
os_error *bbc_gwindow(int a, int b, int c, int d)
{
   os_error *e = bbc_vdu(bbc_DefGraphWindow);
   if (!e) e = bbc_vduw(a);
   if (!e) e = bbc_vduw(b);
   if (!e) e = bbc_vduw(c);
   if (!e) e = bbc_vduw(d);
   return(e);
}





int bbc_modevar(int mode, int varno)
{
   int result;
   (void) os_swi3r(os_X | 0x35, mode, varno, 0, 0, 0, &result);
   return result;
}


int bbc_vduvar(int varno)
{
   int vars[2];
   int result;
   vars[0] = varno;
   vars[1] = -1; /* terminator. */
   (void) os_swi2(os_X | 0x31, (int) &vars[0], (int) &result);
   return result;
}



/* Set graphics foreground/background colour and action. */
os_error *bbc_gcol(int a, int b)
{
   os_error *e = bbc_vdu(bbc_DefGraphColour);
   if (!e) e = bbc_vdu(a);
   if (!e) e = bbc_vdu(b);
   return(e);
}


/* Perform an operating system plot operation. Plot number, x, y. */
os_error *bbc_plot(int n, int x, int y)
{
   return(os_swi3(XOS_Plot, n, x, y));
}


/* Move graphics cursor to an absolute position. */
os_error *bbc_move(int x, int y)
{ 
   return(bbc_plot(bbc_SolidBoth + bbc_BMoveAbs, x, y));
}



/* Draw a line to absolute coordinates from the current graphics position. */
os_error *bbc_draw(int x, int y)
{
   return(bbc_plot(bbc_SolidBoth + bbc_DrawAbsFore, x, y));
}

/* Read buffer status */

int bbc_adval(int x)
{
 int dmy;
 os_byte(0x80,&x,&dmy);
 return x;
}


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


#define CacheAddr           0x00040080
#define FindFont            0x00040081
#define LoseFont            0x00040082
#define ReadDefn            0x00040083
#define ReadInfo            0x00040084
#define StringWidth         0x00040085
#define Paint               0x00040086
#define Caret               0x00040087
#define ConverttoOS         0x00040088
#define Converttopoints     0x00040089
#define SetFont             0x0004008A
#define CurrentFont         0x0004008B
#define FutureFont          0x0004008C
#define FindCaret           0x0004008D
#define CharBBox            0x0004008E
#define ReadScaleFactor     0x0004008F
#define SetScaleFactor      0x00040090
#define ListFonts           0x00040091
#define SetFontColours      0x00040092
#define SetPalette          0x00040093
#define ReadThresholds      0x00040094
#define SetThresholds       0x00040095
#define FindCaretJ          0x00040096
#define StringBBox          0x00040097
#define ReadColourTable     0x00040098





os_error *font_strwidth(fs)

font_string *fs;

{

os_regset r;
os_error *e;

r.r[1] = (int)fs->s;
r.r[2] = fs->x;
r.r[3] = fs->y;
r.r[4] = fs->split;
r.r[5] = fs->term;

e = os_swix(StringWidth, &r);

fs->x = r.r[2];
fs->y = r.r[3];
fs->split = r.r[4];
fs->term = r.r[5];

return e;

}





os_error *font_paint(s, options, x, y)

char *s;
int options, x, y;

{

os_regset r;
os_error *e;

r.r[1] = (int)s;
r.r[2] = options;
r.r[3] = x;
r.r[4] = y;

e = os_swix(Paint, &r);

return e;

}




os_error *font_stringbbox(s, fi)

char *s;
font_info *fi;

{

os_regset r;
os_error *e;

r.r[1] = (int)s;

e = os_swix(StringBBox, &r);

fi->minx = r.r[1];
fi->miny = r.r[2];
fi->maxx = r.r[3];
fi->maxy = r.r[4];

return e;

}





os_error *font_readscalefactor(x, y)

int *x, *y;

{

os_regset r;
os_error *e;

e = os_swix(ReadScaleFactor, &r);

*x = r.r[1];
*y = r.r[2];

return e;

}


os_error *font_setscalefactor(x, y)

int x, y;

{

os_regset r;
os_error *e;

r.r[1] = x;
r.r[2] = y;

e = os_swix(SetScaleFactor, &r);

return e;

}



os_error *font_findcaret(fs)

font_string *fs;

{

os_regset r;
os_error *e;

r.r[1] = (int)fs->s;
r.r[2] = fs->x;
r.r[3] = fs->y;

e = os_swix(FindCaret, &r);

fs->x = r.r[2];
fs->y = r.r[3];
fs->split = r.r[4];
fs->term = r.r[5];

return e;

}



os_error *font_findcaretj(fs, offset_x, offset_y)

font_string *fs;
int offset_x, offset_y;

{

os_regset r;
os_error *e;

r.r[1] = (int)fs->s;
r.r[2] = fs->x;
r.r[3] = fs->y;
r.r[4] = offset_x;
r.r[5] = offset_y;

e = os_swix(FindCaretJ, &r);

fs->x = r.r[2];
fs->y = r.r[3];
fs->split = r.r[4];
fs->term = r.r[5];

return e;

}




os_error *font_find(name, xsize, ysize, xres, yres, fontadd)

char *name;
int xsize, ysize; /* in 16ths of a point */
int xres, yres;   /* dots per inch of res: 0->use default */
font *fontadd;

{

os_regset r;
os_error *e;

r.r[1] = (int)name;
r.r[2] = xsize;
r.r[3] = ysize;
r.r[4] = xres;
r.r[5] = yres;

e = os_swix(FindFont, &r);

*fontadd = (font) r.r[0];

return e;
}

os_error *font_lose(f)

font f;

{
os_regset r;
os_error *e;

r.r[0] = f;
e = os_swix(LoseFont, &r);
return e;
}





os_error *font_setfont(f)

font f;

{

os_regset r;
os_error *e;

r.r[0] = f;

e = os_swix(SetFont, &r);

return(e);

}



os_error *font_setcolour(f, background, foreground, offset)

font f;
int background, foreground, offset;

{

os_regset r;
os_error *e;

r.r[0] = f;
r.r[1] = background;
r.r[2] = foreground;
r.r[3] = offset;

e = os_swix(SetFontColours, &r);

return e;

}




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


int akbd_pollsh(void)
{
  int x = -1;
  int y = 255;
  (void) os_byte(129, &x, &y);
  return(x==255 && y==255);
}

int akbd_pollctl(void)
{
  int x = -2;
  int y = 255;
  (void) os_byte(129, &x, &y);
  return(x==255 && y==255);
}


int bbc_inkey(int delay)
{
 int x = delay;
 int y = delay>>8;
 (void) os_byte(129, &x, &y);
 if(!y) return(x);
 else   return(-1);
}


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



#define OS_CLI  0x05
#define OS_Byte 0x06
#define OS_Word 0x07
#define OS_File 0x08
#define OS_Args 0x09
#define OS_GBPB 0x0C
#define OS_Find 0x0D





os_error *os_swix(int swicode, os_regset *r)
{
   return ((os_error *)_kernel_swi(swicode, (_kernel_swi_regs *)r, (_kernel_swi_regs *)r));
}



os_error *os_swi4r(int swicode,
  int r0, int r1, int r2, int r3,
  int *r0out, int *r1out, int *r2out, int *r3out)
{
 os_regset r;
 os_error *e;

 r.r[0] = r0;
 r.r[1] = r1;
 r.r[2] = r2;
 r.r[3] = r3;

 e=os_swix(swicode, &r);

 if(r0out) *r0out = r.r[0];
 if(r1out) *r1out = r.r[1];
 if(r2out) *r2out = r.r[2];
 if(r3out) *r3out = r.r[3];

 return e;
}




os_error *os_swi4(int swicode, int r0, int r1, int r2, int r3)
{
 os_regset r;

 r.r[0] = r0;
 r.r[1] = r1;
 r.r[2] = r2;
 r.r[3] = r3;

 return os_swix(swicode, &r);
}










os_error *os_swi1(int swicode, int r0) {
  return os_swi4(swicode, r0, 0, 0, 0);
}

os_error *os_swi2(int swicode, int r0, int r1) {
  return os_swi4(swicode, r0, r1, 0, 0);
}

os_error *os_swi3(int swicode, int r0, int r1, int r2) {
  return os_swi4(swicode, r0, r1, r2, 0);
}



os_error *os_swi3r(int swicode,
  int r0, int r1, int r2, int *r0out, int *r1out, int *r2out)
{
  return os_swi4r(swicode, r0, r1, r2, 0, r0out, r1out, r2out, 0);
}




os_error * os_byte(int a, int *x, int *y)
{
  return os_swi3r(os_X | OS_Byte, a, *x, *y, 0, x, y);
}


os_error * os_word(int wordcode, void *p)
{
  os_regset r;

  r.r[0] = wordcode;
  r.r[1] = (int) p;

  return os_swix(OS_Word, &r);
}


os_error * os_gbpb(os_gbpbstr *p)
{
  return os_swix(OS_GBPB, (os_regset *) p);
}

os_error * os_file(os_filestr *p)
{
  return os_swix(OS_File, (os_regset *) p);
}


os_error * os_find(os_regset *p)
{
  return os_swix(OS_Find, (os_regset *) p);
}


os_error * os_cli(char * command)
{
  os_regset r;

  r.r[0] = (int) command;

  return os_swix(OS_CLI, &r);
}


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

static int wimpt__mode = 12;
static int wimpt__dx;
static int wimpt__dy;
static int wimpt__bpp;

int wimpt__read_screen_mode(void)
{
  int x, y;
  (void) os_byte(135, &x, &y);
  return y;
}

BOOL wimpt_checkmode(void) {
  int old = wimpt__mode;
  wimpt__mode = wimpt__read_screen_mode();
  wimpt__dx = 1 << bbc_vduvar(bbc_XEigFactor);
  wimpt__dy = 1 << bbc_vduvar(bbc_YEigFactor);
  wimpt__bpp = 1 << bbc_vduvar(bbc_Log2BPP);
  return old != wimpt__mode;
}


wimp_t wimpt__task = 0;

wimp_t wimpt_task(void) {return wimpt__task;}


static char *programname = "";


char *wimpt_programname(void)
  {return programname;}


void wimpt__exit(void)
{
  (void) wimp_taskclose(wimpt__task);
}




void wimpt_noerr(os_error *e) {
  if (e != 0) {
    os_error er;
    er.errnum = e->errnum;
    sprintf(
      er.errmess,
      "%s has suffered a fatal internal error (%s) and must exit immediately",
      programname,
      e->errmess);
    myreporterror(&er, 0);
    exit(0);
  };
}



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


#ifdef DBUG

/* in dbug mode, we use this signal handler, which gives a trace back */

typedef void SignalHandler(int);
static       SignalHandler *oldhandler;

static void debug_handler(int sig)
{
 if(sig!=SIGINT || 1)
 {
  os_cli("*spool zz");
  raise(SIGTERM);            /* get a precious stack backtrace! */
  os_cli("*spool");
  exit(0);
 }
 else
 {
  signal(SIGINT,&debug_handler);
 }

 exit(0);
}


#else

/* in production versions, we use these signal handlers      */
/* the escape one is used during printing, and does nothing  */
/* the other one prints up an error message and then resumes */

static void escape_handler(int sig)
{
 (void) signal(SIGINT, &escape_handler);
 /* reinstall ourselves, as SIG_DFL has been restored by the system: */
 /* as defined by the (dumb) ANSI spec! */
 sig=0;
}


static void general_handler(int sig)
{
 char string[128];
 sprintf(string,"Trace has suffered an internal error type=%d.",sig);
 errorbox(string);
 (void) signal(sig, &general_handler);
}


#endif



void wimpt_init(char *progname)
{
 #ifdef DBUG

  signal(SIGSEGV,&debug_handler);
  signal(SIGINT,&debug_handler);
  signal(SIGFPE,&debug_handler);
  signal(SIGILL,&debug_handler);
  signal(SIGSTAK,&debug_handler);

  signal(SIGTERM,SIG_DFL);


 #else

 signal(SIGINT,  &escape_handler);
 signal(SIGABRT, &general_handler);
 signal(SIGFPE,  &general_handler);
 signal(SIGILL,  &general_handler);
 signal(SIGSEGV, &general_handler);
 signal(SIGTERM, &general_handler);

 #endif

 programname = progname;
 (void) wimp_taskinit(programname, &wimpt__task);
 wimpt_checkmode();
 atexit(wimpt__exit);
}






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


#undef SetPalette
#undef SetFontColours


/*                          W I M P    S W I 's                            */
#define Initialise          0x000400C0
#define CreateWindow        0x000400C1
#define CreateIcon          0x000400C2
#define DeleteWindow        0x000400C3
#define DeleteIcon          0x000400C4
#define OpenWindow          0x000400C5
#define CloseWindow         0x000400C6
#define Poll                0x000400C7
#define RedrawWindow        0x000400C8
#define UpdateWindow        0x000400C9
#define GetRectangle        0x000400CA
#define GetWindowState      0x000400CB
#define GetWindowInfo       0x000400CC
#define SetIconState        0x000400CD
#define GetIconState        0x000400CE
#define GetPointerInfo      0x000400CF
#define DragBox             0x000400D0
#define ForceRedraw         0x000400D1
#define SetCaretPosition    0x000400D2
#define GetCaretPosition    0x000400D3
#define CreateMenu          0x000400D4
#define DecodeMenu          0x000400D5
#define WhichIcon           0x000400D6
#define SetExtent           0x000400D7
#define SetPointerShape     0x000400D8
#define OpenTemplate        0x000400D9
#define CloseTemplate       0x000400DA
#define LoadTemplate        0x000400DB
#define ProcessKey          0x000400DC
#define CloseDown           0x000400DD
#define StartTask           0x000400DE
#define ReportError         0x000400DF
#define GetWindowOutline    (0x000400c0+32)
#define PollIdle            (0x000400c0+33)
#define PlotIcon            (0x000400c0+34)
#define SetMode             (0x000400c0+35)
#define SetPalette          (0x000400c0+36)
#define ReadPalette         (0x000400c0+37)
#define SetColour           (0x000400c0+38)
#define SendMessage         (0x000400c0+39)
#define CreateSubMenu       (0x000400c0+40)
#define SpriteOp            (0x000400c0+41)
#define BaseOfSprites       (0x000400c0+42)
#define BlockCopy           (0x000400c0+43)
#define SlotSize            (0x000400c0+44)
#define ReadPixTrans        (0x000400c0+45)
#define ClaimFreeMemory     (0x000400c0+46)
#define CommandWindow       (0x000400c0+47)
#define TextColour          (0x000400c0+48)
#define TransferBlock       (0x000400c0+49)
#define ReadSysInfo         (0x000400c0+50)
#define SetFontColours      (0x000400c0+51)


os_error * wimp_taskinit(char *name, wimp_t *t)
{
os_regset r;
os_error *e;

r.r[0] = 200;
r.r[1] = 'T' +
        ('A' << 8) +
        ('S' << 16) +
        ('K' << 24);
r.r[2] = (int) name;
e = os_swix(Initialise, &r);
*t =  r.r[1];
return(e);
}




os_error *wimp_spriteop(int reason_code, char *name)
{
 os_regset r ;
 r.r[0] = reason_code ;
 r.r[2] = (int) name ;
 return os_swix(SpriteOp, &r) ;
}




os_error * wimp_create_wind(wimp_wind * w, wimp_w * result)
{

os_regset r;
os_error *e;

r.r[1] = (int)w;

e = os_swix(CreateWindow, &r);

*result = r.r[0]; 

return(e);

}



os_error * wimp_create_icon(wimp_icreate * i, wimp_i * result)
{

os_regset r;
os_error *e;

r.r[1] = (int)i;

e = os_swix(CreateIcon, &r);

*result = r.r[0]; 

return(e);

}



os_error * wimp_delete_wind(wimp_w w)
{

os_regset r;
os_error *e;

r.r[1] = (int)&w;

e = os_swix(DeleteWindow, &r);

return(e);

}



os_error * wimp_delete_icon(wimp_w w, wimp_i i)
{

os_regset r;
os_error *e;
int j[2];

j[0] = (int)w;
j[1] = (int)i;

r.r[1] = (int) j;

e = os_swix(DeleteIcon, &r);

return(e);

}



os_error * wimp_open_wind(wimp_openstr * o)
{

os_regset r;
os_error *e;

r.r[1] = (int)o;

e = os_swix(OpenWindow, &r);

return(e);

}


os_error * wimp_close_wind(wimp_w w)
{

os_regset r;
os_error *e;

r.r[1] = (int)&w;

e = os_swix(CloseWindow, &r);

return(e);

}


os_error * wimp_redraw_wind(wimp_redrawstr * wr, int * result)
{

os_regset r;
os_error *e;

r.r[1] = (int)wr;

e = os_swix(RedrawWindow, &r);

*result = r.r[0];

return(e);

}



os_error * wimp_update_wind(wimp_redrawstr * wr, int * result)
{

os_regset r;
os_error *e;

r.r[1] = (int)wr;

e = os_swix(UpdateWindow, &r);

*result = r.r[0];

return(e);

}



os_error * wimp_get_rectangle(wimp_redrawstr * wr, int * result)
{

os_regset r;
os_error *e;

r.r[1] = (int)wr;

e = os_swix(GetRectangle, &r);

*result = r.r[0];

return(e);

}


os_error * wimp_get_wind_state(wimp_w w, wimp_wstate * result)
{

os_regset r;
os_error *e;

result->o.w = w;

r.r[1] = (int)result;

e = os_swix(GetWindowState, &r);

return(e);

}




os_error * wimp_get_wind_info(wimp_winfo * result)

{

os_regset r;
os_error *e;

r.r[1] = (int)result;
e = os_swix(GetWindowInfo, &r);

return(e);

}




typedef struct {
  wimp_w    wind_h;
  wimp_i    icon_h;
  wimp_iconflags flags_v;
  wimp_iconflags flags_m;
} wimp_handles_and_flags;


os_error * wimp_set_icon_state(wimp_w w, wimp_i i, 
     wimp_iconflags value, wimp_iconflags mask)
{

os_regset r;
os_error *e;
wimp_handles_and_flags b;

b.wind_h = w;
b.icon_h = i;
b.flags_v = value;
b.flags_m = mask;

r.r[1] = (int)&b;

e = os_swix(SetIconState, &r);

return(e);

}




typedef struct {
  wimp_w    wind_h;
  wimp_i    icon_h;
  wimp_icon icon_s;
} wimp_icon_and_handles;

os_error * wimp_get_icon_info(wimp_w w, wimp_i i, wimp_icon * result)

{

os_regset r;
os_error *e;
wimp_icon_and_handles b;


b.wind_h = w;
b.icon_h = i;

r.r[1] = (int)&b;

e = os_swix(GetIconState, &r);

*result = b.icon_s;

return(e);

}



typedef struct {
  wimp_mousestr m;
  int dud;
} mstr;


os_error * wimp_get_point_info(wimp_mousestr * result)

{

os_regset r;
os_error *e;
mstr m;

r.r[1] = (int)&m;

e = os_swix(GetPointerInfo, &r);

*result = m.m;
return(e);

}



os_error * wimp_drag_box(wimp_dragstr * d)
{

os_regset r;
os_error *e;

r.r[1] = (int)d;

e = os_swix(DragBox, &r);

return(e);

}




os_error * wimp_force_redraw(wimp_redrawstr * r)

{

os_error *e;

e = os_swix(ForceRedraw, (os_regset *)r);

return(e);

}



os_error * wimp_set_caret_pos(wimp_caretstr * c)
{

os_error *e;

e = os_swix(SetCaretPosition, (os_regset *)c);

return(e);

}



os_error * wimp_get_caret_pos(wimp_caretstr * c)

{

os_regset r;
os_error *e;

r.r[1] = (int)c;

e = os_swix(GetCaretPosition, &r);

return(e);

}



os_error * wimp_create_menu(wimp_menustr * m, int x, int y)

{

os_regset r;
os_error *e;

r.r[1] = (int)m;
r.r[2] = x;
r.r[3] = y;

e = os_swix(CreateMenu, &r);

return(e);

}



os_error * wimp_decode_menu(wimp_menustr * m, void * p1, void * p2)

{

os_regset r;
os_error *e;

r.r[1] = (int)m;
r.r[2] = (int)p1;
r.r[3] = (int)p2;

e = os_swix(DecodeMenu, &r);

return(e);

}




os_error * wimp_set_extent(wimp_redrawstr * wr)
{

os_regset r;
os_error *e;

r.r[0] = wr->w;
r.r[1] = (int)wr + 4;

e = os_swix(SetExtent, &r);

return(e);

}




os_error * wimp_open_template(char * name)

{

os_regset r;
os_error *e;

r.r[1] = (int)name;

e = os_swix(OpenTemplate, &r);

return(e);

}



os_error * wimp_close_template(void)
{

os_regset r;
os_error *e;

e = os_swix(CloseTemplate, &r);

return(e);

}



os_error * wimp_load_template(wimp_template * t)

{

os_error *e;

e = os_swix(LoadTemplate, (os_regset *)t);

return(e);

}




os_error *wimp_processkey(int chcode) {
  return os_swi1(ProcessKey, chcode);
}




os_error * wimp_taskclose(wimp_t t)

{
os_regset r;
os_error *e;

r.r[0] = t;
r.r[1] = 'T' +
        ('A' << 8) +
        ('S' << 16) +
        ('K' << 24);
  e = os_swix(CloseDown, &r);
  return e;
}




os_error *wimp_getwindowoutline(wimp_redrawstr *re)
{
  os_regset r;
  os_error *e;

  r.r[1] = (int) re;
  e = os_swix(GetWindowOutline, &r);
  return e;
}


os_error *wimp_readpalette(wimp_palettestr* p)
{
  os_regset r;
  os_error *e;
  int i ;

  r.r[1] = (int) p;
  e = os_swix(ReadPalette, &r);

  for (i=0 ; i<20; i++)
  {
   int t = ((int *)p)[i] & 0xF0F0F0FF ;
   ((int *)p)[i] = t | ((t>>4) & 0xF0F0F00) ;
                   /* copy all the colour nibbles down, to scale by 17/16 */
  }
  return e;
}




os_error *wimp_setcolour(int colour)
{
  os_regset r;
  os_error *e;

  r.r[0] = colour;
  e = os_swix(SetColour, &r);
  return e;
}


os_error *wimp_sendmessage(wimp_etype code, wimp_msgstr* m, wimp_t dest)
{
  return os_swi3(os_X | SendMessage, code, (int) m, dest);
}

os_error *wimp_sendwmessage(
  wimp_etype code, wimp_msgstr* m, wimp_w w, wimp_i i)
{
  return os_swi4(os_X | SendMessage, code, (int) m, w, i);
}

os_error *wimp_create_submenu(wimp_menustr *sub, int x, int y)
{
  os_regset r;
  os_error *e;

  r.r[1] = (int) sub;
  r.r[2] = x;
  r.r[3] = y;
  e = os_swix(CreateSubMenu, &r);
  return e;
}

os_error *wimp_slotsize(int *currentslot /*inout*/,
                        int *nextslot /*inout*/,
                        int *freepool /*out*/) {
  return os_swi3r(SlotSize, *currentslot, *nextslot, 0,
                            currentslot, nextslot, freepool);
}



os_error *wimp_blockcopy(wimp_w w, wimp_box *source, int x, int y)
{
  os_regset r;

  r.r[0] = w;
  r.r[1] = source->x0;
  r.r[2] = source->y0;
  r.r[3] = source->x1;
  r.r[4] = source->y1;
  r.r[5] = x;
  r.r[6] = y;
  return os_swix(BlockCopy, &r);
}
