/* 
   Copyright 2001-2003 Free Software Foundation, Inc.

   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.  

   You may contact the author at:

   mailto::camille@bluegrass.net

   or by snail mail at:

   David Lindauer
   850 Washburn Ave Apt 99
   Louisville, KY 40222
*/
#include <windows.h>
#include <dos.h>
#include <string.h>
#include <stdio.h>
#include <time.h>
#include <libp.h>

int _dos_getdrive(int *drive)
{
	char buf[256],buf1[6];
	GetCurrentDirectory(256,buf);
	if (drive)
		*drive = buf[0] - '@' ;
	buf1[0] = '=' ;
	buf1[1] = buf[0] ;
	buf1[2] = ':' ;
	buf1[3] = '\\' ;
	buf1[4] = 0 ;
	SetEnvironmentVariable(buf1,buf) ;
	return 0 ;
}
int _dos_setdrive(int drive, int *nd)
{
// FIXME - figure out how many drives.
	char buf[5],*a,equals[256];
	buf[0] = '=' ;
	buf[1] = drive + '@' ;
	buf[2] = ':' ;
	buf[3] = '\\' ;
	buf[4] = 0;
	if (!GetEnvironmentVariable(buf,equals,256)) {
		if (!SetEnvironmentVariable(buf,buf+1))
			return 1 ;
		if (!SetCurrentDirectory(buf+1))
			return 1 ;
	} else
		if (!SetCurrentDirectory(equals))
			return 1 ;
	return 0;
}
int _dos_getpwd(char *buf, int drive)
{
	char name[5],*a,equals[256];
	if (drive == 0) {
		GetCurrentDirectory(256,equals) ;
		goto finish ;
	}
	buf[0] = 0;
	name[0] = '=' ;      
	name[1] = drive + '@' ;
	name[2] = ':' ;
	name[3] = '\\' ;
	name[4] = 0;
	if (!GetEnvironmentVariable(name,equals,256)) {
		strcpy(equals,name+1) ;
finish:
		SetEnvironmentVariable(buf,equals) ;
  }	
	strcpy(buf,equals+3);
	return strlen(buf) ;
}
int _dos_setpwd(char *buf)
{
	char dir[256],name[6];
	dir[0] = _dos_getdrive(0) + '@';
	dir[1] = ':' ;
	if (buf[0] != '\\')
		_dos_getpwd(dir+2, dir[0] - '@');
	else {
		dir[2] = '\\';
		dir[3] = 0;
	}
	strcat(dir,buf);
	name[0] = '=' ;      
	name[1] = dir[0] ;
	name[2] = ':' ;
	name[3] = '\\' ;
	name[4] = 0;
	SetEnvironmentVariable(name,dir) ;
	return !SetCurrentDirectory(dir) ;
}
static void convert_file_time(LPFILETIME timet, unsigned short *xtime, unsigned short *xdate)
{
	FILETIME timex ;
	FileTimeToLocalFileTime(timet,&timex);
	FileTimeToDosDateTime(&timex, xdate, xtime) ;
}
static void format_finddata(struct find_t *buf, LPWIN32_FIND_DATA data)
{
	if (data->dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE)
		buf->attrib |= _A_ARCH ;
	if (data->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
		buf->attrib |= _A_SUBDIR ;
	if (data->dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)
		buf->attrib |= _A_HIDDEN ;
	if (data->dwFileAttributes & FILE_ATTRIBUTE_READONLY)
		buf->attrib |= _A_RDONLY ;
	if (data->dwFileAttributes & FILE_ATTRIBUTE_SYSTEM)
		buf->attrib |= _A_SYSTEM ;
	convert_file_time(&data->ftLastAccessTime,&buf->wr_time,&buf->wr_date);
	if (data->nFileSizeHigh)
		*(DWORD *)(&buf->size) = 0xffffffff ;
	else
		*(DWORD *)(&buf->size) = data->nFileSizeLow;
	strcpy(buf->name,data->cFileName);
}
static BOOL matchedattr(DWORD attr, DWORD mattr)
{
	if ((attr & mattr) == attr)
		return 1 ;
	return 0;
}
int _dos_findfirst(char *string, int attr, struct find_t *buf)
{
	WIN32_FIND_DATA find_data ;
	HANDLE val = FindFirstFile(string,&find_data);
	memset(buf,0,sizeof(*buf));
	if (val == INVALID_HANDLE_VALUE)
		return 1 ;
	*(HANDLE *)(buf->reserved) = val ;
	*(DWORD *)(buf->reserved + 4) = attr ;
	format_finddata(buf,&find_data);
	if (matchedattr(attr,buf->attrib))
		return 0;
	else
		return _dos_findnext(buf) ;
	
}
int _dos_findnext(struct find_t *buf)
{
	WIN32_FIND_DATA find_data ;
	HANDLE val = *(HANDLE *)(buf->reserved);
	DWORD attr = *(DWORD *)(buf->reserved + 4) ;
	do {
		if (!FindNextFile(val,&find_data)) {
			FindClose(val) ;
			return 1;
		}
		format_finddata(buf,&find_data) ;
	} while (!matchedattr(attr,buf->attrib));

	return 0 ;
}
unsigned _dos_open(char *name,int mode, int *fd)
{
	int flags = 0;
	switch(mode) {
		case 0:
			flags = GENERIC_READ ;
			break ;
		case 1:
			flags = GENERIC_WRITE ;
			break ;
		case 2:
			flags = GENERIC_READ | GENERIC_WRITE ;
         break ;
	}
	*fd = _ll_open(name,flags);
	if (*fd == 0)
		return 2;
	return 0;
}
unsigned _dos_close(int fd)
{
	_ll_close(fd);
	return 0;
}
unsigned _dos_setftime(int fd, unsigned short date, unsigned short time)
{
	FILETIME timex,timet ;
	DosDateTimeToFileTime(date,time,&timex) ;
	LocalFileTimeToFileTime(&timex,&timet);
	return (!SetFileTime((HANDLE)fd,0,0,&timet));
}
unsigned _dos_getftime(int fd, unsigned short *date, unsigned short *time)
{
	BY_HANDLE_FILE_INFORMATION info ;
	if (!GetFileInformationByHandle((HANDLE)fd,&info))
		return 2 ;
	
	convert_file_time(&info.ftLastWriteTime,time,date);
	return 0;
}
