//#include	"conslib.h"
#include	"compat.h"
#include	"kctrl.h"

static	TCHAR	UnicodeStr[ MAX_PATH ] ;
static	TCHAR	FormatStr[ MAX_PATH ] ;
static	TCHAR	ValueStr[ MAX_PATH ] ;
static	char	SjisStr[ MAX_PATH ] ;

char *
strncpy( char *dst, const char *src, unsigned int len )
{
	char	*dstorg = dst ;

	while ( len -- && (*dst++ = *src++) ) {
	}
	return dstorg ;
}

char *
strncat( char *dst, const char *src, unsigned int len )
{
	char	*dstorg = dst ;

	while ( *dst ) {
		dst ++ ;
	}
	while ( len -- && (*dst++ = *src++) ) {
	}
	return dstorg ;
}

char *
strchr( const char *dst, int find_c )
{
	char	c ;

	while ( (c = *dst) && (c != find_c ) ) {
		dst ++ ;
	}
	return c == find_c ? (char*) dst : 0 ;
}

char *
strrchr( const char *dst, int find_c )
{
	char		c ;
	const char	*found = 0 ;

	while ( c = *dst ) {
		if ( c == find_c ) {
			found = dst ;
		}
		dst ++ ;
	}
	return (char*) (c == find_c ? dst : found) ;
}

char *
strpbrk( const char *dst, const char *src )
{
	char	c ;

	while ( c = *dst ) {
		if ( strchr( src, c ) ) {
			return (char*) dst ;
		}
		dst ++ ;
	}
	return 0 ;
}

char *
strstr( const char *dst, const char *src )
{
	int		len_dst = strlen( dst ) ;
	int		len_src = strlen( src ) ;

	if ( !len_dst || !len_src || len_dst < len_src ) {
		return 0 ;
	}
	len_dst -= len_src ;
	do {
		if ( !strncmp( dst, src, len_src ) ) {
			return (char*) dst ;
		}
		dst ++ ;
	} while ( len_dst -- ) ;
	return 0 ;
}

#ifdef	_WIN32_WCE
#define		islower(c)		((c)>='a' && (c)<='z')
#define		toupper(c)		(islower((c))?(c)-'a'+'A':(c))

int
strcmpi( const char *dst, const char *src )
{
	char	c1, c2 ;

	while ( c1 = *src++ ) {
		c2 = *dst++ ;
		c1 = toupper( c1 ), c2 = toupper( c2 ) ;
		if ( c1 != c2 ) {
			return c1 - c2 ;
		}
	}
	c2 = *dst++ ;
	c1 = toupper( c1 ), c2 = toupper( c2 ) ;
	return c1 - c2 ;
}

long
atol( const char *str )
{
	char	c ;
	long	ret = 0 ;

	while ( c = *str++ ) {
		if ( c < '0' || c > '9' ) {
			break ;
		}
		ret *= 10 ;
		ret += c - '0' ;
	}
	return ret ;
}
#endif	/* _WIN32_WCE */

double
atof( const char *str )
{
	return (double) atol( str ) ;
}

#ifdef	_WIN32_WCE
int
isalpha( int c )
{
	return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ;
}

int
isalnum( int c )
{
	return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ;
}

int
isdigit( int c )
{
	return c >= '0' && c <= '9' ;
}

int
isspace( int c )
{
	return c == ' ' || c == '\t' ;
}
#endif	/* _WIN32_WCE */

void
exception( unsigned long code )
{
	RaiseException( code, 0, 0, 0 ) ;
}

#define		MAX_FILE	(16)

FILE		Files[ MAX_FILE ] ;

void
init_compat( void )
{
	int		i ;
	FILE	*fp = Files ;

	for ( i = 0 ; i < MAX_FILE ; i ++, fp ++ ) {
		fp->f_inuse = FALSE ;
	}
}

void
release_compat( void )
{
	int		i ;
	FILE	*fp = Files ;

	for ( i = 0 ; i < MAX_FILE ; i ++, fp ++ ) {
		fclose( fp ) ;
	}
}

FILE *
fopenW( LPCTSTR path, LPCTSTR modestr )
{
	DWORD	i ;
	FILE	*fp = Files ;
	BOOL	f_binary = FALSE, f_trunc = FALSE, f_last = FALSE ;
	DWORD	access = GENERIC_READ ;
	DWORD	mode = FILE_SHARE_READ ;
	DWORD	dist = OPEN_EXISTING ;

	for ( i = 0 ; i < MAX_FILE ; i ++, fp ++ ) {
		if ( !fp->f_inuse ) {
			break ;
		}
	}
	if ( i == MAX_FILE ) {
		return NULL ;
	}
	if ( *modestr == TEXT('r') ) {
		access = GENERIC_READ ;
		dist = OPEN_EXISTING ;
		if ( modestr[1] == TEXT('+') ) {
			access = GENERIC_READ|GENERIC_WRITE ;
			dist = OPEN_ALWAYS ;
			if ( modestr[2] == TEXT('b') ) {
				f_binary = TRUE ;
			}
		} else if ( modestr[1] == TEXT('b') ) {
			f_binary = TRUE ;
		}
	} else if ( *modestr == TEXT('w') ) {
		access = GENERIC_WRITE ;
		dist = CREATE_ALWAYS ;
		f_trunc = TRUE ;
		if ( modestr[1] == TEXT('+') ) {
			access = GENERIC_READ|GENERIC_WRITE ;
			if ( modestr[2] == TEXT('b') ) {
				f_binary = TRUE ;
			}
		} else if ( modestr[1] == TEXT('b') ) {
			f_binary = TRUE ;
		}
	} else if ( *modestr == TEXT('a') ) {
		access = GENERIC_WRITE ;
		dist = CREATE_ALWAYS ;
		f_last = TRUE ;
		if ( modestr[1] == TEXT('+') ) {
			access = GENERIC_READ|GENERIC_WRITE ;
			if ( modestr[2] == TEXT('b') ) {
				f_binary = TRUE ;
			}
		} else if ( modestr[1] == TEXT('b') ) {
			f_binary = TRUE ;
		}
	} else {
		return NULL ;
	}
	fp->hFile = CreateFile( path, access, mode, NULL,
							dist, FILE_ATTRIBUTE_NORMAL, 0 ) ;
	if ( fp->hFile == INVALID_HANDLE_VALUE ) {
		return NULL ;
	}
	if ( f_trunc ) {
		SetEndOfFile( fp->hFile ) ;
	} else if ( f_last ) {
		SetFilePointer( fp->hFile, 0, NULL, FILE_END ) ;
	}
	fp->f_inuse = TRUE ;
	fp->f_eof = FALSE ;
	fp->f_binary = f_binary ;
	fp->r_in = fp->r_out = fp->w_in = 0 ;
	return fp ;
}

FILE *
fopen( const char *path, const char *modestr )
{
	sjis2unicode( path, UnicodeStr, sizeof UnicodeStr ) ;
	sjis2unicode( modestr, ValueStr, sizeof ValueStr ) ;
	return fopenW( UnicodeStr, ValueStr ) ;
}

int
fclose( FILE *fp )
{
	DWORD	nWrite ;

	if ( !fp->f_inuse ) {
		return EOF ;
	}
	if ( fp->w_in ) {
		WriteFile( fp->hFile, fp->wbuf, fp->w_in, &nWrite, NULL ) ;
	}
	CloseHandle( fp->hFile ) ;
	fp->f_inuse = FALSE ;
	return 0 ;
}

int
fexistW( LPCTSTR path )
{
	return GetFileAttributes( path ) != 0xFFFFFFFF ;
}

int
fexist( const char *path )
{
	sjis2unicode( path, UnicodeStr, sizeof UnicodeStr ) ;
	return fexistW( UnicodeStr ) ;
}

int
fexist_dirW( LPCTSTR path )
{
	DWORD	attr = GetFileAttributes( path ) ;
	return (attr != 0xFFFFFFFF) && (attr & FILE_ATTRIBUTE_DIRECTORY) ;
}

int
fexist_dir( const char *path )
{
	sjis2unicode( path, UnicodeStr, sizeof UnicodeStr ) ;
	return fexistW( UnicodeStr ) ;
}

int
fexist_fileW( LPCTSTR path )
{
	DWORD	attr = GetFileAttributes( path ) ;
	return (attr != 0xFFFFFFFF) && !(attr & FILE_ATTRIBUTE_DIRECTORY) ;
}

int
fexist_file( const char *path )
{
	sjis2unicode( path, UnicodeStr, sizeof UnicodeStr ) ;
	return fexistW( UnicodeStr ) ;
}

int
fgetc( FILE *fp )
{
	int		c ;
	BOOL	ret ;
	DWORD	nRead ;

	do {
		if ( fp->f_eof ) {
			return EOF ;
		}
		if ( fp->r_in == fp->r_out ) {
			fp->r_in = fp->r_out = 0 ;
			ret = ReadFile( fp->hFile, fp->rbuf, sizeof fp->rbuf, &nRead, NULL ) ;
			if ( !ret || !nRead ) {
				fp->f_eof = TRUE ;
				return EOF ;
			}
			fp->r_in = nRead ;
			fp->r_in %= sizeof fp->rbuf ;
		}
		c = (int) fp->rbuf[ fp->r_out ] ;
		fp->r_out ++ ;
		fp->r_out %= sizeof fp->rbuf ;
	} while ( !fp->f_binary && c == '\r' ) ;
	return c ;
}

static	int
fputc_sub( int c, FILE *fp )
{
	DWORD	tmp, nWrite ;

	fp->wbuf[ fp->w_in ] = c ;
	fp->w_in ++ ;
	fp->w_in %= sizeof fp->wbuf ;
	if ( !fp->w_in || c == '\n' ) {
		tmp = fp->w_in ? fp->w_in : sizeof fp->wbuf ;
		fp->w_in = 0 ;
		if ( !WriteFile( fp->hFile, fp->wbuf, tmp, &nWrite, NULL ) ) {
			return FALSE ;
		} else if ( nWrite == 0 ) {
			return FALSE ;
		}
	}
	return TRUE ;
}

int
fputc( int c, FILE* fp )
{
	if ( !fp->f_binary && c == '\n' ) {
		if ( !fputc_sub( '\r', fp ) ) {
			return EOF ;
		}
	}
	return fputc_sub( c, fp ) ? c : EOF ;
}

char *
fgets( char *buf, int size, FILE *fp )
{
	int		c ;
	LPBYTE	ptr = buf ;

	size -- ;
	while ( (c = fgetc( fp )) != EOF ) {
		if ( !size ) {
			break ;
		}
		*ptr++ = c ;
		if ( c == '\n' ) {
			break ;
		}
	}
	*ptr = 0 ;
	return ptr == buf ? NULL : buf ;
}

int
fputs( char *buf, FILE *fp )
{
	BYTE	c ;
	int		last = EOF ;

	while ( c = *buf++ ) {
		last = (int) c ;
		if ( fputc( last, fp ) == EOF ) {
			return EOF ;
		}
	}
	return last ;
}

int
ungetc( int c, FILE *fp )
{
	return c ;
}

int
feof( FILE *fp )
{
	return fp->f_eof ;
}

int
fseek( FILE *fp, long offset, int whence )
{
	DWORD	method ;

	if ( whence == 1 ) {
		method = FILE_CURRENT ;
	} else if ( whence == 2 ) {
		method = FILE_END ;
	} else {
		method = FILE_BEGIN ;
	}
	fp->r_in = fp->r_out = 0 ;
	return SetFilePointer( fp->hFile, offset, NULL, method ) ? 0 : -1 ;
}

void
sprintf_int( char *buf, char *fmt, int value )
{
	sjis2unicode( fmt, FormatStr, sizeof FormatStr ) ;
	wsprintf( UnicodeStr, FormatStr, value ) ;
	unicode2sjis( UnicodeStr, SjisStr, sizeof SjisStr ) ;
	strcpy( buf, SjisStr ) ;
}

void
sprintf_double( char *buf, char *fmt, double value )
{
#if 0
	sjis2unicode( fmt, FormatStr, sizeof FormatStr ) ;
	wsprintf( UnicodeStr, FormatStr, value ) ;
#else
	wsprintf( UnicodeStr, TEXT("%d"), (DWORD) value ) ;
#endif
	unicode2sjis( UnicodeStr, SjisStr, sizeof SjisStr ) ;
	strcpy( buf, SjisStr ) ;
}

void
sprintf_str( char *buf, char *fmt, const char *str )
{
	sjis2unicode( fmt, FormatStr, sizeof FormatStr ) ;
	sjis2unicode( str, ValueStr, sizeof ValueStr ) ;
	wsprintf( UnicodeStr, FormatStr, ValueStr ) ;
	unicode2sjis( UnicodeStr, SjisStr, sizeof SjisStr ) ;
	strcpy( buf, SjisStr ) ;
}

void
fprintf_int( FILE *fp, char *fmt, int value )
{
	sjis2unicode( fmt, FormatStr, sizeof FormatStr ) ;
	wsprintf( UnicodeStr, FormatStr, value ) ;
	unicode2sjis( UnicodeStr, SjisStr, sizeof SjisStr ) ;
	fputs( SjisStr, fp ) ;
}

void
fprintf_double( FILE *fp, char *fmt, double value )
{
#if 0
	sjis2unicode( fmt, FormatStr, sizeof FormatStr ) ;
	wsprintf( UnicodeStr, FormatStr, value ) ;
#else
	wsprintf( UnicodeStr, TEXT("%d"), (DWORD) value ) ;
#endif
	unicode2sjis( UnicodeStr, SjisStr, sizeof SjisStr ) ;
	fputs( SjisStr, fp ) ;
}
