#include <devices/clipboard.h>
#include <exec/types.h>
#include <stdlib.h>
#include <stdio.h>
#include <exec/types.h>
#include <exec/devices.h>
#include <devices/timer.h>
#include <proto/exec.h>
#include <libraries/dos.h>
#include <proto/dos.h>

#include <string.h>
#include <ctype.h>

#define ID(a,b,c,d) (((a)<<24)|((b)<<16)|((c)<<8)|(d))

int writeclip(UBYTE *data,int width,int height)
{
   struct MsgPort *port;
   struct IOClipReq *io;
   int size;
   int ret=1;

   struct Head {
      ULONG Form,FSize;
      ULONG Cell,Cfld,CSize;
      USHORT Width,Height;
   } head={ ID('F','O','R','M'),
            0,
            ID('C','E','L','L'),
            ID('C','F','L','D')};

   /* FORMxxxxCELLCFLDxxxxXXYY...Field (pad)*/


   if(!(port=CreateMsgPort()))  goto exit_fail1;
   if(!(io=(struct IOClipReq *)CreateExtIO(port,sizeof(struct IOClipReq))))
                                 goto exit_fail2;

   if(OpenDevice("clipboard.device",0,(struct IORequest *)io,0))
                                 goto exit_fail3;

   size=(width*height+1)&0xfffffffe;

   head.CSize=size+4;
   head.FSize=size+16;
   head.Width=width;
   head.Height=height;

   io->io_Offset=0;
   io->io_ClipID=0;
   io->io_Command=CMD_WRITE;
   io->io_Length=sizeof(head);
   io->io_Data=(UBYTE *)&head;
   DoIO((struct IORequest *)io);
   if(io->io_Error) goto exit_fail4;

   io->io_Length=size;
   io->io_Data=data;
   DoIO((struct IORequest *)io);
   if(io->io_Error) goto exit_fail4;

   io->io_Command=CMD_UPDATE;
   DoIO((struct IORequest *)io);
   if(io->io_Error) goto exit_fail4;

   ret=0;
exit_fail4:
   CloseDevice((struct IORequest *)io);
exit_fail3:
   DeleteExtIO((struct IORequest *)io);
exit_fail2:
   DeleteMsgPort(port);
exit_fail1:;
   return(ret);
}


UBYTE *readclip(int *width,int *height,int *error)
{
   struct MsgPort *port;
   struct IOClipReq *io;
   int size;
   UBYTE * ret=NULL;

   struct Head {
      ULONG Form,FSize;
      ULONG Cell,Cfld,CSize;
      USHORT Width,Height;
   } head={ ID('F','O','R','M'),
            0,
            ID('C','E','L','L'),
            ID('C','F','L','D')};

   /* FORMxxxxCELLCFLDxxxxXXYY...Field (pad)*/

   *error=1;

   if(!(port=CreateMsgPort())) goto exit_fail1;
   if(!(io=(struct IOClipReq *)CreateExtIO(port,sizeof(struct IOClipReq))))
                                 goto exit_fail2;

   if(OpenDevice("clipboard.device",0,(struct IORequest *)io,0))
                                 goto exit_fail3;

   io->io_Offset=0;
   io->io_ClipID=0;
   io->io_Command=CMD_READ;
   io->io_Length=sizeof(head);
   io->io_Data=(UBYTE *)&head;
   DoIO((struct IORequest *)io);
   if(io->io_Error || io->io_Actual!=io->io_Length) {
      *error=3;
      goto exit_fail4;
   }

   if(head.Form!=ID('F','O','R','M') || head.Cell!=ID('C','E','L','L') ||
                                        head.Cfld!=ID('C','F','L','D')) {
      *error=2;
      goto exit_fail4;
   }

   size=head.Width*head.Height;
   *width=head.Width;
   *height=head.Height;

   if(!(ret=AllocVec(size,0))) {
      *error=1;
      goto exit_fail4;
   }

   io->io_Length=size;
   io->io_Data=ret;
   DoIO((struct IORequest *)io);
   if(io->io_Error || io->io_Actual!=io->io_Length) {
      *error=3;
      FreeVec(ret);
      ret=NULL;
      goto exit_fail4;
   }

   *error=0;

exit_fail4:
   if(io->io_Error==0) {
      io->io_Length=1000000;
      io->io_Data=NULL;

      do {
         DoIO((struct IORequest *)io);
      } while(io->io_ClipID>=0);
   }
   CloseDevice((struct IORequest *)io);
exit_fail3:
   DeleteExtIO((struct IORequest *)io);
exit_fail2:
   DeleteMsgPort(port);
exit_fail1:;
   return(ret);
}


