#include <exec/types.h>
#include <exec/memory.h>
#include <dos/dos.h>
#include <jbio.h>

#include <string.h>
#include <clib/alib_protos.h>
#include <clib/exec_protos.h>
#include <clib/dos_protos.h>

extern BOOL nomem;
extern BOOL diskfull;

/* OBS! Klarar _inte_ Read/Write mode */

struct jbFile *jbOpen(UBYTE *name,UWORD mode,ULONG bufsize)
{
   struct jbFile *jb;

   if(!(jb=(struct jbFile *)AllocMem(sizeof(struct jbFile),MEMF_CLEAR)))
   {
      nomem=TRUE;
      return(NULL);
   }

   if(!(jb->buf=(UBYTE *)AllocMem(bufsize,MEMF_ANY)))
   {
      nomem=TRUE;
      FreeMem(jb,sizeof(struct jbFile));
      return(NULL);
   }

   if(!(jb->fh=Open(name,mode)))
   {
      FreeMem(jb->buf,bufsize);
      FreeMem(jb,sizeof(struct jbFile));
      return(NULL);
   }

   jb->mode=mode;
   jb->bufsize=bufsize;

   return(jb);
}

jbClose(struct jbFile *jb)
{
   if((jb->mode==MODE_NEWFILE || jb->mode==MODE_READWRITE) && jb->pos!=0)
      Write(jb->fh,jb->buf,jb->pos);

   Close(jb->fh);
   FreeMem(jb->buf,jb->bufsize);
   FreeMem(jb,sizeof(struct jbFile));
}

jbGetChar(struct jbFile *jb)
{
   if(jb->pos==jb->len)
   {
      jb->pos=0;
      jb->len=Read(jb->fh,jb->buf,jb->bufsize);
      if(jb->len==0) return(-1);
   }
   return(jb->buf[jb->pos++]);
}

jbRead(struct jbFile *jb,void *buf,ULONG bytes)
{
   ULONG toread,copy;

   toread=bytes;
   copy=0;

   while(toread)
   {
      if(jb->pos==jb->len)
      {
         jb->len=Read(jb->fh,jb->buf,jb->bufsize);
         if(jb->len==0) return(bytes-toread);
         jb->pos=0;
      }

      if(toread<jb->len-jb->pos) copy=toread;
      else                       copy=jb->len-jb->pos;

      CopyMem((APTR)&jb->buf[jb->pos],&((UBYTE *)buf)[bytes-toread],copy);
      toread-=copy;
      jb->pos+=copy;
   }

   return(bytes);
}

jbPutChar(struct jbFile *jb, UBYTE ch)
{
   if(jb->pos==jb->bufsize)
   {
      Write(jb->fh,jb->buf,jb->pos);
      jb->pos=0;

      if(IoErr()!=0)
      {
         diskfull=TRUE;
         return;
      }
   }

   jb->buf[jb->pos]=ch;
   jb->pos++;
   jb->len++;
}

jbWrite(struct jbFile *jb,void *buf, ULONG bytes)
{
   ULONG towrite,copy;

   towrite=bytes;
   copy=0;

   while(towrite)
   {
      if(jb->pos==jb->bufsize)
      {
         Write(jb->fh,jb->buf,jb->pos);
         jb->pos=0;

         if(IoErr()!=0)
         {
            diskfull=TRUE;
            return;
         }
      }

      if(towrite<jb->bufsize-jb->pos) copy=towrite;
      else                            copy=jb->bufsize-jb->pos;

      CopyMem(&((UBYTE *)buf)[bytes-towrite],(APTR)&jb->buf[jb->pos],copy);
      towrite-=copy;
      jb->pos+=copy;
      jb->len+=copy;
   }
}

jbPuts(struct jbFile *jb, UBYTE *str)
{
   jbWrite(jb,str,strlen(str));
}

jbFGets(struct jbFile *jb,UBYTE *str,ULONG max)
{
   ULONG d;

   d=0;

   if(max==0)
      return(0);

   for(;;)
   {
      if(d==max-1)
      {
         str[d]=0;
         return(d);
      }

      if(jb->pos==jb->len)
      {
         jb->len=Read(jb->fh,jb->buf,jb->bufsize);
         jb->pos=0;

         if(jb->len==0)
         {
            str[d]=0;
            return(d);
         }
      }

      str[d]=jb->buf[jb->pos];

      if(str[d]==10 || str[d]==13)
      {
         d++;
         jb->pos++;
         str[d]=0;

         return(d);
      }

      d++;
      jb->pos++;
   }
}
