/*--------------------------------------------------------------------------*/
/* Include files															*/
/*--------------------------------------------------------------------------*/

#include	<ctype.h>
#include	<errno.h>

#include	<stdlib.h>
#include	<fcntl.h>
#include	<sys/types.h>
#include	<sys/stat.h>
#include	<string.h>
#include	<time.h>

#ifdef unix
#include <sys/dir.h>
#include <sys/param.h>
#include <stdio.h>
#ifndef Sony
#include <regex.h>
#endif
#include "bink.h" /* for FILEINFO */
#else
#ifndef LATTICE
#include	<io.h>
#endif

#define 	INCL_DOSPROCESS
#include	<os2.h>

#include	<dos.h>
#endif

/*--------------------------------------------------------------------------*/
/* Static function declarations 											*/
/*--------------------------------------------------------------------------*/

/*	... NONE ...  */

/*--------------------------------------------------------------------------*/
/* Static variable definitions												*/
/*--------------------------------------------------------------------------*/

#ifdef unix

#define far

#ifndef max
#define max(a,b)        ((a)>=(b)?(a):(b))
#endif

DIR *dirp = NULL;

#define FILENAMELEN 13

/****************************************************************************/

void unixize(char *dos, char *un)
{
	char *s, *d, ch;

	s = dos;	/* source */
	d = un;		/* dest */
	while(*s) {
		ch = *s++;
		switch(ch) {
			case '\\':
				*d++ = '/';		/* first change all \ into / */
				break;
			case '?':
				*d++ = '.';		/* any char as ? */
				break;
			case '.':
				*d++ = '\\';	/* dot as \. */
				*d++ = '.';
				break;
			case '*':
				*d++ = '.';		/* any seq of char as .* */
				*d++ = '*';
				break;
			default:
				*d++ = ch;
				break;
		}
	}
	*d++ = '$';	/* end of line marker */
	*d = '\0';
#ifdef DEBUG
	fprintf(stderr, "unixize:\n  dos name = '%s', unix name = '%s'\n", dos, un);
#endif
}

void splitpath(char *path, char *file, char *dir)
{
	char *pos;
	char copypath[MAXPATHLEN];

	file[0] = '\0';
	dir[0] = '\0';
	strcpy(copypath,path);

	pos = rindex(copypath, '/');
	if (pos == 0)
		strcpy(file, copypath);
	else {
		*pos = '\0';
		strcpy(dir, copypath);
		pos++;
		strcpy(file, pos);
	}
#ifdef DEBUG
	fprintf(stderr, "splitpath:\n  dir = '%s', file = '%s'\n", dir, file);
#endif
}

/* checkfile returns TRUE when filename is correct */
int checkfile(struct direct *dp, char *mask)
{
	char name[20];
	int res;

#if defined(Sony) || defined(USG)
    re_comp(mask);
#endif

	if(dp->d_namlen > FILENAMELEN)
		res = 0;
	else 
		{
		strncpy(name, dp->d_name, dp->d_namlen);
		name[dp->d_namlen] = '\0';
#if defined(Sony) || defined(USG)
        res = re_exec(name);
#else
        res = !recmp(mask, name);
#endif
		}
#ifdef DEBUG 
	fprintf(stderr, "checkfile: '%s' returns %d for mask %s\n", name, res, mask);
#endif 

	return res;
}

void convert2dta(struct direct *dp, struct FILEINFO *dta)
{
	char name[256];
	struct stat buf;
	struct tm *tim;

	strncpy(dta->name, dp->d_name, max(FILENAMELEN, dp->d_namlen));
	strcpy(name, dta->_path);
	strcat(name, "/");
	strcat(name, dta->name);
	if(stat(name, &buf) == -1) {
		bt_perror("convert2dta stat failed");
		status_line("dp->d_name = %s\n", dp->d_name);
		status_line("curr_pathname = %s\n", dta->_path);
		status_line("name = %s\n", name);
		status_line("name = %s\n", name);
		dta->size = 0;
		dta->time = 0;
	} else {
		dta->size = buf.st_size;
		/* time info depends on GENERIC being defined.
		 * See for example xmsend.c and look for ifdef GENERIC's...
		 */
#ifdef DEBUG
		tim = localtime(&buf.st_mtime);
		fprintf(stderr, "filedate = %s\n", asctime(tim));
#endif
		dta->time = buf.st_mtime;
	}
}

/*--------------------------------------------------------------------------*/
/* DIR_FINDFIRST									 FOR PORTABILITY		*/
/*--------------------------------------------------------------------------*/

int dir_findfirst(char far * filename, int attribute, struct FILEINFO * dta)
{
	char un[256];
	struct direct *dp;
	
#ifdef DEBUG
	fprintf(stderr, "dir_findfirst filename = %s, attr = %d\n",
		filename, attribute);
#endif
	unixize(filename, un);
    splitpath(filename, un, dta->_path);
    unixize(un, dta->_mask);

	dta->_dirp = opendir(dta->_path);
	if(dta->_dirp) {
		for (dp = readdir(dta->_dirp); dp != NULL; dp = readdir(dta->_dirp))
			if (checkfile(dp, dta->_mask)) {
				convert2dta(dp, dta);
				return 0;
			}
		closedir(dta->_dirp);
		dta->_dirp = NULL;
	}
	return -1;
}

/*--------------------------------------------------------------------------*/
/* DIR_FINDNEXT 									 FOR PORTABILITY		*/
/*--------------------------------------------------------------------------*/

int dir_findnext(struct FILEINFO * dta)
{
	struct direct *dp;

#ifdef DEBUG
	fprintf(stderr, "dir_findnext\n");
#endif

	if(!dta->_dirp)
		return -1;

	for (dp = readdir(dta->_dirp); dp != NULL; dp = readdir(dta->_dirp))
		if (checkfile(dp, dta->_mask)) {
			convert2dta(dp, dta);
			return 0;
		}
	closedir(dta->_dirp);
	dta->_dirp = NULL;
	return -1;
}


#else /* unix */

struct FILEINFO {
   char rsvd[21];
   char attrib;
   unsigned wr_date;
   unsigned wr_time;
   long size;
   char name[13];
   char nill;
   };

struct FileFindBuf {
		unsigned create_date;			/* date of file creation */
		unsigned create_time;			/* time of file creation */
		unsigned access_date;			/* date of last access */
		unsigned access_time;			/* time of last access */
		unsigned wr_date;				/* date of last write */
		unsigned wr_time;				/* time of last write */
		unsigned long size; 			/* file size (end of data) */
		unsigned long falloc_size;		/* file allocated size */
		unsigned attrib;				/* attributes of the file */
		unsigned char string_len;		/* returned length of ascii name str. */
										/* length does not include null byte */
		char name[13];					/* name string */
		};

static struct FileFindBuf InfoBuf;
static struct FileFindBuf InfoBufA;

/*--------------------------------------------------------------------------*/
/* External variable declarations											*/
/*--------------------------------------------------------------------------*/

/*	... NONE ...  */

/*--------------------------------------------------------------------------*/
/* Locally defined globals													*/
/*--------------------------------------------------------------------------*/

HDIR					hDir;
HDIR					hDirA;
USHORT					cSearch;
USHORT					usAttrib;

/*--------------------------------------------------------------------------*/
/* Local constants															*/
/*--------------------------------------------------------------------------*/

#define FILENAMELEN 13

/****************************************************************************/


/*--------------------------------------------------------------------------*/
/* DIR_FINDFIRST									 FOR PORTABILITY		*/
/*--------------------------------------------------------------------------*/

int dir_findfirst(char far * filename, int attribute, struct FILEINFO * dta)
{
	hDir	 = 0x0001;
	usAttrib = attribute;
	cSearch  = 1;

	if ((DosFindFirst( filename
					 , &hDir
					 , usAttrib
					 , (struct FILEFINDBUF far *) &InfoBuf
					 , (USHORT) (sizeof(InfoBuf) * cSearch)
					 , &cSearch
					 , (ULONG) NULL) != 0) || cSearch != 1)
	{
		(void) DosFindClose( hDir );
		errno = ENOENT;
		return (1);
	} else {
		dta->wr_date   = InfoBuf.wr_date;
		dta->wr_time   = InfoBuf.wr_time;
		dta->attrib    = (char) InfoBuf.attrib;
		dta->size	   = InfoBuf.size;
		strcpy( dta->name, InfoBuf.name);
		errno = 0;
		return (0);
	}
}

int dir_findfirsta(char far * filename, int attribute, struct FILEINFO * dta)
{
	hDirA	 = 0xffff;
	usAttrib = attribute;
	cSearch  = 1;

	if ((DosFindFirst( filename
					 , &hDirA
					 , usAttrib
					 , (struct FILEFINDBUF far *) &InfoBufA
					 , (USHORT) (sizeof(InfoBufA) * cSearch)
					 , &cSearch
					 , (ULONG) NULL) != 0) || cSearch != 1)
	{
		(void) DosFindClose( hDirA );
		errno = ENOENT;
		return (1);
	} else {
		dta->wr_date   = InfoBufA.wr_date;
		dta->wr_time   = InfoBufA.wr_time;
		dta->attrib    = (char) InfoBufA.attrib;
		dta->size	   = InfoBufA.size;
		strcpy( dta->name, InfoBufA.name);
		errno = 0;
		return (0);
	}
}

/*--------------------------------------------------------------------------*/
/* DIR_FINDNEXT 									 FOR PORTABILITY		*/
/*--------------------------------------------------------------------------*/

int dir_findnext(struct FILEINFO * dta)
{

	cSearch  = 1;

	if ((DosFindNext( hDir
					, (struct FILEFINDBUF far *) &InfoBuf
					, (USHORT) (sizeof(InfoBuf) * cSearch)
					, &cSearch) != 0) || (cSearch < 1))
	{
		(void) DosFindClose( hDir );
		errno = ENOENT;
		return (1);
	} else {
		dta->wr_date   = InfoBuf.wr_date;
		dta->wr_time   = InfoBuf.wr_time;
		dta->attrib    = (char) InfoBuf.attrib;
		dta->size	   = InfoBuf.size;
		strcpy( dta->name, InfoBuf.name);
		errno = 0;
		return (0);
	}
}

int dir_findnexta(struct FILEINFO * dta)
{

	cSearch  = 1;

	if ((DosFindNext( hDirA
					, (struct FILEFINDBUF far *) &InfoBufA
					, (USHORT) (sizeof(InfoBufA) * cSearch)
					, &cSearch) != 0) || (cSearch < 1))
	{
		(void) DosFindClose( hDirA );
		errno = ENOENT;
		return (1);
	} else {
		dta->wr_date   = InfoBufA.wr_date;
		dta->wr_time   = InfoBufA.wr_time;
		dta->attrib    = (char) InfoBufA.attrib;
		dta->size	   = InfoBufA.size;
		strcpy( dta->name, InfoBufA.name);
		errno = 0;
		return (0);
	}
}

#endif /* unix */
/*--------------------------------------------------------------------------*/
/*								  END OF FILE								*/
/*--------------------------------------------------------------------------*/
