/*ProfiPacket - packet radio terminal program
  Copyright (C) 1999  Alexander Feigl

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

  Author:

  Alexander Feigl
  Burachstraße 51

  D-88250 Weingarten

  Mail : Alexander.Feigl@gmx.de
*/


#ifdef HAVE_CONFIG_H
#include "config.h"
#endif


#include "global.h"
#include "GUIProtos.h"

#include <stdlib.h>
#include <time.h>

#ifdef AmigaOS
#include <dos/dos.h>
#include <dos/exall.h>
#include <utility/date.h>
#include <exec/memory.h>

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

#ifdef __GNUC__

#include <inline/exec.h>
#include <inline/utility.h>
#include <inline/dos.h>

extern void *UtilityBase;
extern void *SysBase;
extern void *DOSBase;
#undef RawDoFmt

#endif

#else /*AmigaOS*/

#include "amigaemu.h"

#endif /*AmigaOS*/

void UTIL_MsDateAmiga(unsigned long msdate,struct DateStamp *date)

 {
  struct ClockData cdat;

  unsigned long xsecs;


  cdat.year=1980+ ( (msdate>>25) & 0x7f);
  cdat.month=((msdate>>21) & 0x0f);
  cdat.mday=((msdate>>16) & 0x1f);
  cdat.hour=((msdate>>11) & 0x1f);
  cdat.min=((msdate>>5) & 0x2f);
  cdat.sec=( msdate&0x1f) * 2;
  xsecs=Date2Amiga(&cdat);

  date->ds_Tick=(xsecs%60)*50;
  date->ds_Minute=(xsecs/60)%(60*24);
  date->ds_Days=xsecs/(60*60*24);
  return;
 }
unsigned long UTIL_AmigaDateMs(const struct DateStamp *date)
 {
  struct ClockData cdat;

  Amiga2Date(
    ((date->ds_Tick/50)+(date->ds_Minute*60)+(date->ds_Days*60*60*24)),
    &cdat);

  return(
    (( (cdat.year-1980) %128) << 25) |
    ((  cdat.month          ) << 21) |
    ((  cdat.mday           ) << 16) |
    ((  cdat.hour           ) << 11) |
    ((  cdat.min            ) <<  5) |
    ((  cdat.sec / 2        )      ) );

 }

int UTIL_TestTimeRange(int starthour,int startmin,int stophour,int stopmin)
 {
  unsigned long start,stop,current;

  start=starthour*60+startmin;
  stop=stophour*60+stopmin;
  current=CurrentDateStamp.ds_Minute;
  if (start>stop)
   {
    if (current>=start) return(1);
    if (current<=stop) return(1);
    return(0);
   }
   else
   {
    if ( (current>=start) && (current<=stop) ) return(1);
    return(0);
   }

 }

int UTIL_MakeBinHead(unsigned char *binline,unsigned long bytes,
                     unsigned long crc,const struct DateStamp *time,
                     const unsigned char *filepath,int extendedbin)
 {

  unsigned char xcache[40];
  unsigned char *dptr;
  unsigned char *sptr;

  dptr=binline;

  *(dptr++)='#';
  *(dptr++)='B';
  *(dptr++)='I';
  *(dptr++)='N';
  *(dptr++)='#';
  RawDoFmt("%ld",&bytes,PutRawDoFmt,xcache);
  sptr=xcache;
  while (*sptr!='\0') *(dptr++)=*(sptr++);
  if (crc!=-1) /* -1 disables CRC output */
   {
    *(dptr++)='#';
    *(dptr++)='|';
    RawDoFmt("%ld",&crc,PutRawDoFmt,xcache);
    sptr=xcache;
    while (*sptr!='\0') *(dptr++)=*(sptr++);
   }
  if (time!=NULL) /* no time struct disables time output */
   {
    unsigned long msdate;
    *(dptr++)='#';
    *(dptr++)='$';
    msdate=UTIL_AmigaDateMs(time);
    RawDoFmt("%08lx",&msdate,PutRawDoFmt,xcache);
    sptr=xcache;
    while (*sptr!='\0') *(dptr++)=*(sptr++);
   }
  if (filepath!=NULL) /* supplying no file path disables filename output*/
   {
    unsigned long flen;
    const unsigned char *fptr;
    fptr=filepath;
    while (1)
     {
      const unsigned char *cfp;

      flen=0;
      cfp=fptr;
      while (*cfp!='\0')
       {
        ++flen;
        if ( *(cfp++)==':') ++flen;
       }
      if (flen<=40) break;

      ++fptr;
      while (*fptr!='\0')
       {
        if ( (*fptr==':') || (*fptr=='/'))
         {
          break;
         }
        ++fptr;
       }
     }

    /* output cut down filepath */
    if (*fptr!='\0')
     {
      if (extendedbin) *(dptr++)='?';
      *(dptr++)='#';
      while (*fptr!='\0')
       {
        *(dptr++)=*(fptr++);
        if (*(fptr-1)==':') *(dptr++)='\\';
        if (*(dptr-1)=='/') *(dptr-1)='\\';
       }
     }
   }
  *(dptr++)=0x0d;
  *dptr=0;
  return(dptr-binline);
 }

unsigned long UTIL_ParseAutobinLine(const unsigned char *binline,
                                    signed long *bytes,
                                    signed long *crc,
                                    struct DateStamp *time,
                                    unsigned char *filepath,
                                    int *extendedbin)

/* Bit 0 = Length - autobin parsed */
/* Bit 1 = CRC */
/* Bit 2 = time */
/* Bit 3 = filepath */

 {
  const unsigned char *xxp;
  unsigned long ltsr;
  unsigned long parsed;


  if (!CompareStringLimit("#BIN#",binline,5)) return(0);

  parsed=0;
  *bytes=0;
  *crc=-1;

  time->ds_Days=0;
  time->ds_Minute=0;
  time->ds_Tick=0;

  filepath[0]='\0';
  *extendedbin=FALSE;



  xxp=binline+5;
  ltsr=StrToLong((unsigned char *) xxp,bytes);
  if ( (ltsr==-1) || (ltsr==0)) return(0); /*parse error*/

  parsed|=1;

  xxp=xxp+ltsr;

  while (1)
   {
    if (*xxp=='?')
     {
      *extendedbin=TRUE;
      ++xxp;
      continue;
     }
    if (*xxp=='\r') return(parsed);
    if (*xxp=='\0') return(parsed);
    if (*xxp!='#') return(0); /* parse error*/
    xxp++;
    switch (*xxp)
     {
      case '|':
        xxp++;
        ltsr=StrToLong((unsigned char *) xxp,crc);
        if ( (ltsr==0) || (ltsr==-1) ) return(0);
        xxp+=ltsr;
        parsed|=4;
        break;
      case '$':
        xxp++;
         {
          unsigned long i,val,digit;

          val=0;
          for (i=0;i<8;++i,++xxp)
           {

            digit=99;
            if ( (*xxp>='0') && (*xxp<='9') ) digit=*xxp-'0';
            if ( (*xxp>='A') && (*xxp<='F') ) digit=*xxp-'A'+10;
            if ( (*xxp>='a') && (*xxp<='f') ) digit=*xxp-'a'+10;
            if (digit==99) return(0);
            val=val*16+digit;
           }
          UTIL_MsDateAmiga(val,time);
          parsed|=2;
         }
        break;
      default:
         {
          unsigned char *dptr;
          dptr=filepath;
          while ( (*xxp!='\r') && (*xxp!='\0'))
           {
            if (*xxp==':')
             {
              *(dptr++)=':';
              ++xxp;
              if (*xxp=='\\') ++xxp;
              continue;
             }
            if (*xxp=='\\')
             {
              *(dptr++)='/';
             }
             else
             {
              *(dptr++)=*(xxp);
             }
            xxp++;
           }
         }
        parsed|=8;
        break;
     }
   }


 }

unsigned long UTIL_Test7PlusLine(const unsigned char *tline)
 {
  if (CompareStringLimit(" go_7p",tline,6)) return(1);
  if (CompareStringLimit(" stop_7p",tline,8)) return(2);
  if (CompareStringLimit(" go_text",tline,8)) return(3);
  if (CompareStringLimit(" stop_text",tline,10)) return(4);
  if (CompareStringLimit(" go_info",tline,8)) return(5);
  if (CompareStringLimit(" stop_info",tline,10)) return(6);
  return(0);
 }

unsigned long MAIN_GetSecondsAgo(const struct DateStamp *date)
 {
  signed long d1,m1,s1;
  signed long d2,m2,s2;
  
  d1=date->ds_Days;
  m1=date->ds_Minute;
  s1=date->ds_Tick;
  
  d2=CurrentDateStamp.ds_Days;
  m2=CurrentDateStamp.ds_Minute;
  s2=CurrentDateStamp.ds_Tick;
  
  return (    ( (s2-s1) / 50) +
              ( (m2-m1) * 60) +
              ( (d2-d1) * 60 * 60 * 24) );
              
 }


void UTIL_InitRandom(void)
 {
  srand(time(NULL));
 }

void UTIL_RandomizeBytes(unsigned char *random,int bytes)
 {
  int i;
  unsigned char *rptr;

  rptr=random;
  for (i=0;i<bytes;++i,++rptr)
   {
    *rptr=rand()%256;
   }

 }

unsigned char *GUI_LongToString(unsigned char *str,unsigned long Value,
                                unsigned long Digits,unsigned long Mode)
 {
  unsigned char *sptr;
  unsigned long tval;
  unsigned long digits;
  int tmod,digit;
  unsigned char dchar;
  int fildig=0;

  tmod=Mode;
  digits=Digits;
  tval=Value;
  sptr=str;

  while (digits>0)
   {
    digit=tval/digits;
    tval-=digit*digits;
    digits/=10;
    dchar=' ';
    if ( (tmod==0) || (digits==0) || (digit!=0) )
     {
      tmod=0;
      dchar='0'+digit;
     }  
    if ( ( (tmod==2) || (tmod==3) ) && (digits!=0) && (digit==0) )
     {
      if (tmod==2) fildig++;
      continue;
     }
    *(sptr++)=dchar;
   } 
  while (fildig)
   {
    *(sptr++)=' ';
    --fildig; 
   }
  *sptr=0;
  return(sptr);
 }
