#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <dos.h>
#include <process.h>
#include <dir.h>
#include <conio.h>
#include <sys\stat.h>
#include <share.h>
#include <io.h>
#include <fcntl.h>
#include <string.h>

#include "misc.h"

/**********************************************************
 * Determine if a file or path exists.
 * Returns 1 if true and 0 if false.
 * To check a path do NOT include the trailing backslash.
 * Note: You could use "findfirst()" for this also.
 *
 * eg: if(exists(filepath)) do_something(); else is_error();
 **********************************************************/
int exists(char *filepath)
{
    return( access( filepath, 0 ) == 0 );
}

/**********************************************************
 * Check if file path has a trailing backslash.
 * It is assumed you won't be stupid enough to pass a NULL
 * length string.
 *
 * eg: fixslash(pathstring);
 **********************************************************/
void fixslash(char *s)
{
     while(*s) s++;                      // Move to EOS
     if(*(--s) == '\\') return;          // If Ok return
    *(++s) = '\\';                       // Else Add Slash
    *(++s) = '\0';                       // Terminate String
}

/**********************************************************
 * Check for a valid date
 *
 * Returns 1 if a valid date and 0 if not.
 *
 * eg: if(!checkdate(1992,1,1)) do_nothing();
 **********************************************************/
int checkdate(unsigned int yy, unsigned int mm, unsigned int dd)
{
    int days[] = {31,29,31,30,31,30,31,31,30,31,30,31};

    if( mm < 1 || mm > 12) return(0);                        // Invalid Month
    if( dd < 1 || dd > days[mm-1]) return(0);                // Invalid Day
    if(yy < 1900) return(0);                                 // Your to Old
    if(((yy%4) != 0) && (dd == 29) &&  (mm == 2)) return(0); // Tryin to fool me

    return(1);                                               // Everything must be valid
}

/**********************************************************
 * Convert a Date to an Int
 *
 * Returns the converted date on success or 65535 on failure.
 *
 * eg: intdate = dat2int(1992,1,1);
 **********************************************************/
unsigned int dat2int(unsigned int yy, unsigned int mm, unsigned int dd)
{
    unsigned int  tofield=0;

    if(!checkdate(yy,mm,dd) || yy < 1980 || yy > 2107) return(65535);

    tofield = dd-1;
    tofield = tofield + ((mm-1) << 5);
    tofield = tofield + ((yy-1980) << 9);

    return(tofield);
}

/**********************************************************
 * Convert an Int to a Date
 *
 * Returns the converted date in the variables yy,mm,dd
 * and a true false value in relation to the conversion.
 *
 * eg: if(!int2dat(intdate,&year,&mon,&day)) is_error();
 **********************************************************/
int int2dat(unsigned int dat, unsigned int *yy, unsigned int *mm, unsigned int *dd)
{
    unsigned int temp=dat;

    if(dat == 65535) return(0);          /* Invalid Date */

    *dd = (temp & 31) + 1;
    temp >>= 5;
    *mm = (temp & 15) + 1;
    temp >>= 4;
    *yy = (temp & 127) + 1980;
    return(1);                         /* Conversion OK */
}

/**********************************************************
 * Convert a Date and Time to a Long (DOS Packed DateTime)
 *
 * Returns the converted date on success or 0 on failure.
 *
 * eg: longdate = dat2int(1992,1,1,12,53,50);
 *********************************************************/
unsigned long dat2long(unsigned int year, unsigned int month, unsigned int day,
                       unsigned int hour, unsigned int min,   unsigned int sec)
{
    unsigned long todatefield,totimefield;

    if(!checkdate(year,month,day) || year < 1980 || year > 2107) return(0);

    todatefield = day;
    todatefield = todatefield + ((month) << 5);
    todatefield = todatefield + ((year-1980) << 9);

    totimefield = (sec >> 1) + (min << 5) + (hour << 12);

    totimefield = totimefield + (todatefield << 16);

    return(totimefield);
}

/* Print at row,col w/attr and 'printf' like arguements */
void prints(int col, int row, int attr, char *control, ...)
{
va_list parms;
unsigned char buff[256], *ptr;

struct text_info ti;       // window left      ti.winleft
gettextinfo(&ti);          // window top       ti.wintop
                           // window right     ti.winright
                           // window bottom    ti.winbottom
                           // attribute        ti.attribute
                           // normal attribute ti.normattr
                           // current mode     ti.currmode
                           // screen height    ti.screenheight
                           // screen width     ti.screenwidth
gotoxy(col,row);
textcolor(attr);
ptr = buff;
va_start(parms, control);
vsprintf(buff, control, parms);
while(*ptr) {
    putch(*ptr++);
    }
va_end(parms);
gotoxy(ti.curx,ti.cury);
textattr(ti.attribute);

}

/*
Returns Free space on a drive as a long integer (%ld)

Drives:
0 = A
1 = B
2 = C
3 = D
*/

long used_space(int drive)
{
return(total_space(drive) - free_space(drive));
}

long free_space(int drive)
{
struct dfree free;
long avail;
getdfree(drive + 1, &free);

if (free.df_sclus == 0xFFFF) {
    return(-1); }
avail = (long) free.df_avail *
    (long) free.df_bsec *
    (long) free.df_sclus;

return(avail);
}

long total_space(int drive)
{
struct dfree free;
long total;
getdfree(drive + 1, &free);

if (free.df_sclus == 0xFFFF) {
    return(-1); }

total = (long) free.df_total *
    (long) free.df_bsec *
    (long) free.df_sclus;
return(total);
}

/* replaces all underscores's with ' ''s */
void change_(char *String)
{
        int X,Length;

Length = strlen(String);

    for(X=0;X<Length;X++)                /* Search        */
       if (String[X] == '_')             /* for +'s       */
          if (String[X+1] == '_') {      /* and change    */
            scoot_down((X+1),String);    /* em' to spaces */
                       --Length;  }
          else
              String[X] = ' ';
}

void scoot_down(int Local,char *Array) /* scoot down all letters 1 in array (starting at [Local] */
{
    int X;
    X=Local;

    while (Array[X++] != '\0')
        Array[X-1]=Array[X];
}

char *stripcr (char *a) {  /* Strips trailing CR's & LF's & ctrl-z's */

      while (a[strlen(a)-1]=='\n' || a[strlen(a)-1]=='\r' || a[strlen(a)-1]==26) a[strlen(a)-1]=0;
        return a;
    }
