/*->c.tw */

#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <stdio.h>
#include <locale.h>

#include "h.os"
#include "h.wimp"
#include "h.wimpt"
#include "h.werr"
#include "h.flex"


#include "h.TWAIN"
#include "h.glue"
#include "h.acq"

#include "h.tw"



static TWAcquireblockstr  * origacqblock;
static TWAcquireblockstr    saveacqblock;
static TWAcquireblockstr    acqblock;



extern int  excalllo(int p0,int p1,int p2,int p3);
extern void excallset(int address);

static os_error * excall(int fn,int p0,int p1,int p2,int p3)
{
 if(fn)
 {
  excallset(fn);
  return((os_error *)excalllo(p0,p1,p2,p3));
 }
 return(NULL);
}


static void twerror(os_error * err)
{
 excall((int)saveacqblock.TWerror,(int)err,0,0,0);
}


static os_error * acqtransfer(int size,int last,int bpr,int rows)
{
 os_error * err;

 err=excall((int)saveacqblock.TWtrans,size,last,bpr,rows);

 acqblock.memory.memxfer.buffer=origacqblock->memory.memxfer.buffer;
 acqblock.memory.memxfer.size=origacqblock->memory.memxfer.size;

 return(err);
}


static os_error * acqend(void)
{
 return(excall((int)saveacqblock.TWend,0,0,0,0));
/* remzeroevent(tacqzero,0); don't need zero polls now */
}


static os_error * acqalloc(int size)
{
 os_error * err;

 origacqblock->transfertype=acqblock.transfertype;

 err=excall((int)saveacqblock.TWalloc,size,0,0,0);
 if(!err)
 {
  acqblock.memory.memxfer.buffer=origacqblock->memory.memxfer.buffer;
  acqblock.memory.memxfer.size=origacqblock->memory.memxfer.size;
 }

 return(err);
}


static os_error * acqpalette(int * paltab,int nc)
{
 /* This is the palette of the acquired image - if it has one */
 return(excall((int)saveacqblock.TWpal,(int)paltab,nc,0,0));
}


static os_error * acqinfo(int xpix,int ypix,int bpp,int xres,int yres,int planar)
{
 int array[6];

 origacqblock->transfertype=acqblock.transfertype;
 origacqblock->area=acqblock.area;

 array[0]=xpix;
 array[1]=ypix;
 array[2]=bpp;
 array[3]=xres;
 array[4]=yres;
 array[5]=planar;

 return(excall((int)saveacqblock.TWinfo,(int)array,0,0,0));
}



static void acqpoll(void)
{
 /* put your poll function here */
 excall((int)saveacqblock.TWpoll,0,0,0,0);
}





/* call this when someone clicks on Acquire... */

os_error * twainacquire(TWAcquireblockstr * xacqblock)
{
 /* addzeroevent(tacqzero,0); make sure you get zero polls from now on */

 saveacqblock=*xacqblock;
 origacqblock=xacqblock;

 TWAcquireDefault(&acqblock);

 acqblock.transfertype=TWSX_MEMORY;
 acqblock.settransfertype=1;

 acqblock.setarea=xacqblock->setarea;
 acqblock.nouserinterface=xacqblock->nouserinterface;
 acqblock.area.x0=xacqblock->area.x0;
 acqblock.area.y1=xacqblock->area.y1;
 acqblock.area.x1=xacqblock->area.x1;
 acqblock.area.y0=xacqblock->area.y0;

 acqblock.TWend=acqend;
 acqblock.TWalloc=acqalloc;
 acqblock.TWtrans=acqtransfer;
 acqblock.TWinfo=acqinfo;
 acqblock.TWpoll=acqpoll;
 acqblock.TWpal=acqpalette;
 acqblock.TWerror=twerror;

 TWAcquire(&acqblock);

 return(NULL);
}



static os_error * selectend(int ok)
{
 /* remzeroevent(tacqzero,0);  don't need zero polls now */
 TWCloseDSM();
 return(NULL);
 ok=ok;
}



/* call this when someone clicks on Select source... */

os_error * twainselect(void)
{
 os_error * err;

 if((err=TWOpenDSM())==NULL)
 {
  TWSelectDS(selectend);
  /* addzeroevent(tacqzero,0); make sure you get zero polls from now on */
 }

 return(err);
}


/* 
   Call this on return from wimp poll
   If it returns zero, then the application must process the wimp event in the
   usual way.
*/

int twainpoll(wimp_eventstr * wimpevent)
{
 if(TWProcessMessage(wimpevent)) return(1);
 else                            return(0);
}


/* Call on program termination */

void twainfinit(int taskhandle)
{
 TWSelectTerminate(0);

 /* TWTerminate();        this calls TWEnd which may not be set up */

 TWDisableDS();          /* this is required by 'the rules' */
 TWCloseDS();
 TWCloseDSM();

 taskhandle=taskhandle;
}


/* Call on program run */

os_error * twaininit(int taskhandle)
{
 TW_IDENTITY AppIdentity;

 AppIdentity.Id=0;/* init to 0, but Source Manager will assign real value */

 AppIdentity.Version.MajorNum=1;
 AppIdentity.Version.MinorNum=0;
 AppIdentity.Version.Language=TWLG_ENG;
 AppIdentity.Version.Country=TWCY_UNITEDKINGDOM;
 strcpy(AppIdentity.Version.Info,"TWAINLib");

 AppIdentity.ProtocolMajor=TWON_PROTOCOLMAJOR;
 AppIdentity.ProtocolMinor=TWON_PROTOCOLMINOR;
 AppIdentity.SupportedGroups=DG_IMAGE | DG_CONTROL;

 strcpy(AppIdentity.Manufacturer,"David Pilling");
 strcpy(AppIdentity.ProductFamily,"TWAINLib");
 strcpy(AppIdentity.ProductName,"TWAINLib");

 /* pass app particulars to glue code */
 
 TWInitialize(&AppIdentity,taskhandle);

 return(NULL);
}


