#include "billingkom.h"

#include <libraries/ums.h>
#include <dos/dos.h>
#include <dos/dosextens.h>

#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/utility_protos.h>

#include	<exec/types.h>
#include	<exec/memory.h>
#include	<exec/ports.h>
#include	<exec/io.h>

#include	<devices/console.h>
#include	<devices/conunit.h>

#include	<intuition/intuitionbase.h>
#include	<intuition/intuition.h>

#ifdef __SASC

#include <dos.h>

extern struct DOSBase *DOSBase;
extern struct Library *UtilityBase;

#include <pragmas/exec_pragmas.h>
#include <pragmas/dos_pragmas.h>
#include <pragmas/utility_pragmas.h>

#endif

UMSAccount login;

#ifdef AMIGA
/* Dice uses AMIGA, SAS/C uses _AMIGA */
#define _AMIGA
#endif

#ifdef _AMIGA
/* Amiga version string */

#ifdef _DCC
/* In Dice format */
const char ver[]="\0$VER: "BASENAME" "VERSION" ("__COMMODORE_DATE__")";
#endif

#ifdef __SASC
/* In SAS/C format */
const char ver[]="\0$VER: "BASENAME" "VERSION" "__AMIGADATE__;
#endif

#endif

struct Library *UMSBase;

extern bool brk;

/* brk should be set to true if break signal was received. Should be checked
when reading/writing to stdio or chen oscheckbreak() is called */

int brkfunc(void)
{
   brk=TRUE;
   return(0);
}

bool osinit(void)
{
   if(!(UMSBase=(struct Library *)OpenLibrary(UMSNAME,UMSVERSION)))
   {
      printf("Unable to open %s %ld or higher\n",UMSNAME,UMSVERSION);
      return(FALSE);
   }

   onbreak(brkfunc);

   return(TRUE);
}

bool oscheckbreak(void)
{
   chkabort();
   return brk;
}

void osclose(void)
{
   CloseLibrary(UMSBase);
}

void osreadline(char *s,long len)
{
   long rlen;

   rlen=Read(Input(),s,len-1);

   if(rlen == 0 || rlen == -1)
   {
     /* Not even an EOL -> carrier lost */
      carrierlost=TRUE;
      brk=TRUE;
      return;
   }

   s[rlen]=0;
   chkabort();

   if(strlen(s)>0 && s[strlen(s)-1]=='\n')
      s[strlen(s)-1]=0;
}


char osreadch(void)
{
   char ch;
   long temp;

   SetMode(Input(),1);
   temp=Read(Input(),&ch,1);
   SetMode(Input(),0);

   if(!temp)
   {
      carrierlost=TRUE;
      return(0);
   }

   if(ch == 3)
      brk=TRUE;

   if(ch == 13)
      ch='\n';

   return(ch);
}

void osreadlineinvisible(char *s,long len)
{
   long c,temp;
   char ch;

   c=0;
   SetMode(Input(),1);

   for(;;)
   {
      temp=Read(Input(),&ch,1);

      if(temp == 0 || temp == -1)
         carrierlost=TRUE;

      chkabort();

      if(carrierlost || brk)
      {
         SetMode(Input(),0);
         return;
      }

      if(ch == 13)
      {
         s[c]=0;
         SetMode(Input(),0);
         printf("\n");
         return;
      }
      else if(ch == 8)
      {
         if(c) c--;
      }
      else
      {
         if(c < len-1)
            s[c++]=ch;
      }
   }
}

void ospause(char *str)
{
   char s[100];

   printf("%s",str);
   osreadline(s,100);
}

struct MsgPort iorp = { {0, 0, NT_MSGPORT, 0, 0},
                        0,
                        0,
                        0,
            				/* start with empty list */
                       {(struct Node *)&iorp.mp_MsgList.lh_Tail, 0, (struct Node *)&iorp.mp_MsgList.lh_Head, 0, 0}};

struct IOStdReq ior = { {{0, 0, 0, 0, 0}, &iorp, 0},
                        0		};		/* device is zero */

extern struct IntuitionBase *IntuitionBase;

bool osgetwindowsize(int *rows,int *cols)
{
   struct MsgPort *con;
   struct StandardPacket *packet;
   struct InfoData *id;
   struct Window *win;
   struct Screen *scr;
   struct FileHandle *fh;

   if(!IsInteractive(Output()))
      return(FALSE);

   /* open the console device */
   if ((OpenDevice("console.device", -1, (struct IORequest *)&ior, 0)) != 0)
   {
      return(FALSE);
   }

   /* set up the message port in the I/O request */
   if ((iorp.mp_SigBit = AllocSignal(-1)) < 0)
   {
      CloseDevice((struct IORequest *)&ior);
      return(FALSE);
   }

   iorp.mp_SigTask = (struct Task *) FindTask((char *) NULL);

   /* try to find console associated with calling process */
   /* if started from CLI, than is 			   */

	con = (struct MsgPort *) ((struct Process *) iorp.mp_SigTask) -> pr_ConsoleTask;

   fh=(struct FileHandle *)(((ULONG) Output()) << 2);

   con=fh->fh_Type;

   if(!con)
   {
      FreeSignal((ULONG)iorp.mp_SigBit);
      CloseDevice((struct IORequest *)&ior);
      return(FALSE);
   }

   if(!(packet = (struct StandardPacket *) AllocMem(sizeof(*packet), MEMF_CLEAR)))
   {
      FreeSignal((ULONG)iorp.mp_SigBit);
      CloseDevice((struct IORequest *)&ior);
      return(FALSE);
   }

   if(!(id = (struct InfoData *) AllocMem(sizeof(*id), MEMF_CLEAR)))
   {
		FreeMem(packet, sizeof(*packet));
      FreeSignal((ULONG)iorp.mp_SigBit);
      CloseDevice((struct IORequest *)&ior);
      return(FALSE);
   }

   /* this is the console handlers packet port */
   packet->sp_Msg.mn_Node.ln_Name = (UBYTE *) &(packet->sp_Pkt);
   packet->sp_Pkt.dp_Link = &(packet->sp_Msg);
   packet->sp_Pkt.dp_Port = &iorp;
   packet->sp_Pkt.dp_Type = ACTION_DISK_INFO;
   packet->sp_Pkt.dp_Arg1 = ((ULONG) id) >> 2;
   PutMsg(con,(struct Message *)packet);
   WaitPort(&iorp);

   /* make sure it's a real window */

   for(scr=IntuitionBase->FirstScreen;scr;scr=scr->NextScreen)
   {
      for(win=scr->FirstWindow;win;win=win->NextWindow)
         if(win == (struct Window *)id->id_VolumeNode) break;

      if(win)
         break;
   }

   if(!scr)
   {
		FreeMem(packet, sizeof(*packet));
      FreeMem(id, sizeof(*id));
      FreeSignal((ULONG)iorp.mp_SigBit);
      CloseDevice((struct IORequest *)&ior);
      return(FALSE);
   }

   *rows = (win->Height - win->BorderTop  - win->BorderBottom) / (win->RPort->Font->tf_YSize);
   *cols = (win->Width  - win->BorderLeft - win->BorderRight)  / (win->RPort->Font->tf_XSize);

   FreeMem(id, sizeof(*id));
   FreeMem(packet, sizeof(*packet));
   FreeSignal((ULONG)iorp.mp_SigBit);
   CloseDevice((struct IORequest *)&ior);
   return(TRUE);
}

char *osfilepart(char *str)
{
   return FilePart(str);
}

#define COPYBUFSIZE  10000

bool oscopyfile(char *file,char *newfile)
{
   BPTR ifh,ofh;
   ULONG len;
   char *copybuf;
   BOOL stop;

   if(!(copybuf=AllocMem(COPYBUFSIZE,MEMF_ANY)))
   {
      return(FALSE);
   }

   if(!(ifh=Open(file,MODE_OLDFILE)))
   {
      FreeMem(copybuf,COPYBUFSIZE);
      return(FALSE);
   }

   if(!(ofh=Open(newfile,MODE_NEWFILE)))
   {
      FreeMem(copybuf,COPYBUFSIZE);
      Close(ifh);
      return(FALSE);
   }

   stop=FALSE;

   while((len=Read(ifh,copybuf,COPYBUFSIZE)) && !stop)
   {
      if(len == -1)
      {
         stop=TRUE;
      }
      else
      {
         len=Write(ofh,copybuf,len);
         if(len == -1) stop=TRUE;
      }
   }

   FreeMem(copybuf,COPYBUFSIZE);
   Close(ofh);
   Close(ifh);

   if(!stop)
   {
      return(TRUE);
   }
   else
   {
      DeleteFile(newfile);
      return(FALSE);
   }
}

unsigned long oscurrentseconds(void)
{
	struct DateStamp ds;

	if (DateStamp(&ds))
	{
		return((unsigned long)(ds.ds_Days*24*60+ds.ds_Minute)*60+ds.ds_Tick/TICKS_PER_SECOND);
	}
	return(0);
}

unsigned char ostoupper(unsigned char ch)
{
   /* toupper() doesn't always handle high ASCII correctly.

      Note: this may also not handle high ASCII correctly if locale.library
            isn't installed on the computer */

   return ToUpper((unsigned long)ch);
}
