/*
 * NG : NG用Cライブラリ互換ルーチン
 *
 * 1997/11/06:Eiichiroh Itoh
 *  (1) 作成開始
 * 修正履歴
 * 1998/04/03:Eiichiroh Itoh
 *  (1) IrCopyからPOBox用に変換
 *
 */
#define	STRICT
#include	<windows.h>
#include	<tchar.h>
#include	"kctrl.h"
#include	"cetools.h"

HANDLE		g_hfile1 = INVALID_HANDLE_VALUE ;
BOOL		g_bEof1 = FALSE ;
BOOL		g_bBinary1 = FALSE ;
BOOL		g_bError1 = FALSE ;
DWORD		g_dwRin1 = 0 ;
DWORD		g_dwRout1 = 0 ;
DWORD		g_dwWin1 = 0 ;
BYTE		g_rBuf1[ 256 ] ;
BYTE		g_sBuf1[ 256 ] ;

BOOL
Fopen( LPCTSTR path, LPCTSTR modestr )
{
	BOOL	f_trunc = FALSE, f_last = FALSE ;
	DWORD	access = GENERIC_READ ;
	DWORD	mode = FILE_SHARE_READ ;
	DWORD	dist = OPEN_EXISTING ;

	g_bBinary1 = FALSE ;
	g_bError1 = FALSE ;
	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') ) {
				g_bBinary1 = TRUE ;
			}
		} else if ( modestr[1] == TEXT('b') ) {
			g_bBinary1 = 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') ) {
				g_bBinary1 = TRUE ;
			}
		} else if ( modestr[1] == TEXT('b') ) {
			g_bBinary1 = 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') ) {
				g_bBinary1 = TRUE ;
			}
		} else if ( modestr[1] == TEXT('b') ) {
			g_bBinary1 = TRUE ;
		}
	} else {
		return FALSE ;
	}
	g_hfile1 = CreateFile( path, access, mode, NULL,
						 dist, FILE_ATTRIBUTE_NORMAL, 0 ) ;
	if ( g_hfile1 == INVALID_HANDLE_VALUE ) {
		return FALSE ;
	}
	if ( f_trunc ) {
		SetEndOfFile( g_hfile1 ) ;
	} else if ( f_last ) {
		SetFilePointer( g_hfile1, 0, NULL, FILE_END ) ;
	}
	g_bEof1 = FALSE ;
	g_dwRin1 = g_dwRout1 = g_dwWin1 = 0 ;
	return TRUE ;
}

void
Fclose( void )
{
	DWORD	nWrite ;

	if ( g_hfile1 != INVALID_HANDLE_VALUE ) {
		if ( g_dwWin1 ) {
			WriteFile( g_hfile1, g_sBuf1, g_dwWin1, &nWrite, NULL ) ;
		}
		CloseHandle( g_hfile1 ) ;
		g_hfile1 = INVALID_HANDLE_VALUE ;
	}
}

int
Fgetc( void )
{
	int		c ;
	BOOL	ret ;
	DWORD	nRead ;

	do {
		if ( g_bEof1 ) {
			return -1 ;
		}
		if ( g_dwRin1 == g_dwRout1 ) {
			g_dwRin1 = g_dwRout1 = 0 ;
			ret = ReadFile( g_hfile1, g_rBuf1, sizeof g_rBuf1, &nRead, NULL ) ;
			if ( !ret || !nRead ) {
				g_bEof1 = TRUE ;
				return -1 ;
			}
			g_dwRin1 = nRead ;
			g_dwRin1 %= sizeof g_rBuf1 ;
		}
		c = (int) g_rBuf1[ g_dwRout1 ] ;
		g_dwRout1 ++ ;
		g_dwRout1 %= sizeof g_rBuf1 ;
	} while ( !g_bBinary1 && c == '\r' ) ;
	return c ;
}

char *
Fgets( char *buf, int size )
{
	int		c ;
	LPBYTE	ptr = buf ;

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

static	int
Fputc_sub( int c )
{
	DWORD	tmp, nWrite ;

	g_sBuf1[ g_dwWin1 ] = c ;
	g_dwWin1 ++ ;
	g_dwWin1 %= sizeof g_sBuf1 ;
	if ( !g_dwWin1 || c == '\n' ) {
		tmp = g_dwWin1 ? g_dwWin1 : sizeof g_sBuf1 ;
		g_dwWin1 = 0 ;
		if ( !WriteFile( g_hfile1, g_sBuf1, tmp, &nWrite, NULL ) ) {
			g_bError1 = TRUE ;
			return FALSE ;
		} else if ( nWrite == 0 ) {
			g_bError1 = TRUE ;
			return FALSE ;
		}
	}
	return TRUE ;
}

int
Fputc( int c )
{
	if ( !g_bBinary1 && c == '\n' ) {
		if ( !Fputc_sub( '\r' ) ) {
			return -1 ;
		}
	}
	return Fputc_sub( c ) ? c : -1 ;
}

int
Fputs( const char *buf )
{
	BYTE	c ;
	int		last = -1 ;

	while ( c = *buf++ ) {
		last = (int) c ;
		if ( Fputc( last ) == -1 ) {
			return -1 ;
		}
	}
	return last ;
}

int
Fread( char *buf, int size )
{
	int		c, nRead = 0 ;

	if ( !size ) {
		return nRead ;
	}
	do {
		c = Fgetc() ;
		if ( c == -1 ) {
			return nRead ;
		}
		*buf++ = c ;
		nRead ++ ;
	} while ( -- size ) ;
	return nRead ;
}

void
Fwrite( const char *buf, int size )
{
	if ( !size ) {
		return ;
	}
	do {
		Fputc( *buf++ ) ;
	} while ( -- size ) ;
}

BOOL
Ferror( void )
{
	return g_bError1 ;
}

int
Fseek( long offset, int whence )
{
	DWORD   method ;

	if ( whence == 1 ) {
		method = FILE_CURRENT ;
	} else if ( whence == 2 ) {
		method = FILE_END ;
	} else {
		method = FILE_BEGIN ;
	}
	g_bEof1 = FALSE ;
	g_dwRin1 = g_dwRout1 = g_dwWin1 = 0 ;
	return SetFilePointer( g_hfile1, offset, NULL, method ) ? 0 : -1 ;
}

void
slash2backslash( LPTSTR str )
{
	LPTSTR	ptr ;

	/* '/'を'\'に変換する */
	while ( ptr = _tcschr( str, TEXT('/') ) ) {
		*ptr = TEXT('\\') ;
	}
}

void
catdir( LPTSTR body, LPCTSTR adddir, LPTSTR pPrevDir )
{
	DWORD	len ;
	LPTSTR	ptr ;

	slash2backslash( body ) ;
	if ( pPrevDir ) {
		_tcscpy( pPrevDir, TEXT("..") ) ;
	}
	while ( *adddir ) {
		if ( _tcschr( TEXT("/\\"), *adddir ) ) {
			/* 先頭が"/"か"\"の場合は読み飛ばす */
			adddir ++ ;
			continue ;
		}
		if ( adddir[0] == TEXT('.') && adddir[1] == TEXT('.') ) {
			ptr = _tcsrchr( body, TEXT('\\') ) ;
			if ( ptr && pPrevDir ) {
				_tcscpy( pPrevDir, ptr + 1 ) ;
			}
			if ( ptr && ptr != body ) {
				*ptr = 0 ;
			} else {
				_tcscpy( body, TEXT("\\") ) ;
			}
			adddir += 2 ;
		} else if ( adddir[0] == TEXT('.') ) {
			adddir ++ ;
		} else {
			break ;
		}
	}
	if ( !*adddir ) {
		return ;
	}
	len = _tcslen( body ) ;
	if ( !len || body[ len - 1 ] != TEXT('\\') ) {
		body[ len ++ ] = TEXT('\\') ;
	}
	_tcscpy( &body[ len ], adddir ) ;
	slash2backslash( body ) ;
}

void
rel2abs( LPTSTR newPath, LPCTSTR oldPath, LPCTSTR adddir )
{
	if ( _tcschr( TEXT("/\\"), *adddir ) ) {
		_tcscpy( newPath, adddir ) ;
		slash2backslash( newPath ) ;
	} else {
		_tcscpy( newPath, oldPath ) ;
		catdir( newPath, adddir, NULL ) ;
	}
}

int
sleep( int sec )
{
	Sleep( sec * 1000 ) ;
	return 0 ;
}

#ifndef	NO_STDIO
#undef		islower
#define		islower(c)		((c)>='a'&&(c)<='z')
#define		toupper(c)		(islower(c)?(c)-'a'+'A':(c))

int
stricmp( const char *src, const char *dst )
{
	char	c = 0, c1 ;

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

int
strnicmp( const char *src, const char *dst, unsigned int len )
{
	char	c = 0, c1 ;

	while ( len && (c = *src++) ) {
		c = toupper( c ) ;
		c1 = *dst++ ;
		c1 = toupper( c1 ) ;
		if ( c != c1 ) {
			return c - c1 ;
		}
		len -- ;
	}
	c = toupper( c ) ;
	c1 = *dst++ ;
	c1 = toupper( c1 ) ;
	return len ? c - c1 : 0 ;
}

#if 0
char *
strstr( const char *str1, const char *str2 )
{
	int		len = strlen( str2 ) ;

	while ( *str1 ) {
		if ( !strncmp( str1, str2, len ) ) {
			return (char*) str1 ;
		}
		str1 ++ ;
	}
	return NULL ;
}
#endif

int
bcmp( char *s1, char *s2, int len )
{
	return memcmp( s1, s2, len ) ;
}

int
bzero( char *s, int len )
{
	memset( s, 0, len ) ;
	return 0 ;
}

void
strcat_num( char *str, int num )
{
	CHAR	digits[ 10 ], *ptr = digits ;

	str += strlen( str ) ;
	if ( num < 0 ) {
		*str++ = '-' ;
		num = - num ;
	}
	if ( num ) {
		while ( num ) {
			*ptr++ = '0' + (CHAR) (num % 10) ;
			num /= 10 ;
		}
	} else {
		*ptr++ = '0' ;
	}
	while ( ptr -- != digits ) {
		*str++ = *ptr ;
	}
	*str = 0 ;
}

void
strcat_char( char *str, int c )
{
	str += strlen( str ) ;
	*str++ = (char) (c & 0xFF) ;
	*str = 0 ;
}

#ifdef	_WIN32_WCE
#if 0
long
atol( const char *str )
{
	char    c ;
	long    ret = 0 ;

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

#ifndef	NO_SPRINTF
static void
SprintfNum( char **buf, int i, int r )
{
	int		q ;

	if ( i < 0 ) {
		*(*buf) ++ = '-' ;
		i = -i ;
	}
	q = i / r ;
	if ( q ) {
		SprintfNum( buf, q, r ) ;
	}
	*(*buf) ++ = '0' + i % r ;
}

static int
SprintfSub( char *buf, const char *fmt, va_list *ap )
{
	int		c ;
	char	*orgbuf = buf ;

	while ( ( c = *fmt++ ) != '\0' ) {
		if ( c != '%') {
			*buf++ = c ;
		} else {
			c = *fmt++ ;
			switch ( c ) {
			case 'c':
				*buf++ = (char) (0xFF & va_arg( *ap, int )) ;
				break ;
			case 'l':
				c = *fmt++ ;
			case 'd':
				SprintfNum( &buf, va_arg( *ap, int ), 10 ) ;
				break ;
			case 'o':
				SprintfNum( &buf, va_arg( *ap, int ), 8 ) ;
				break ;
			case 's':
				strcpy( buf, va_arg( *ap, char * ) ) ;
				buf += strlen( buf ) ;
				break ;
			default:
				*buf++ = c ;
			}
		}
	}
	*buf = 0 ;
	return strlen( orgbuf ) ;
}

int
Sprintf( char *buf, const char *fmt, ... )
{
	int			ret ;
	va_list		pvar ;

	va_start( pvar, fmt ) ;
	ret = SprintfSub( buf, fmt, &pvar ) ;
	va_end( pvar ) ;
	return ret ;
}
#endif	/* NO_SPRINTF */

#ifndef	NO_CLIPBOARD
int
SendClipboard( const char *sjis )
{
	LPTSTR		ptr ;
	DWORD		size ;
#ifdef	_WIN32_WCE
	HLOCAL		hGMem ;
#else	/* _WIN32_WCE */
	HGLOBAL		hGMem ;
#endif	/* _WIN32_WCE */

	size = sjis2unicode( (LPBYTE) sjis, NULL, 0 ) ;
	if ( !size ) {
		return 1 ;
	}
	/* クリップボードオープン */
	if ( !OpenClipboard( 0 ) ) {
		return 0 ;
	} else if ( !EmptyClipboard() ) {
		CloseClipboard() ;
		return 0 ;
	}
	/* 必要な分だけメモリ確保を行う */
#ifdef	_WIN32_WCE
	hGMem = LocalAlloc( LMEM_FIXED, size ) ;
	ptr = (LPTSTR) hGMem ;
#else	/* _WIN32_WCE */
	hGMem = GlobalAlloc( GMEM_MOVEABLE|GMEM_DDESHARE, size ) ;
	ptr = (LPTSTR) GlobalLock( hGMem ) ;
#endif	/* _WIN32_WCE */
	/* UNICODE->JIS変換し結果をメモリに書き込む */
	sjis2unicode( (LPBYTE) sjis, ptr, size ) ;
	/* クリップボードに結果をセットする */
	SetClipboardData( CF_UNICODETEXT, hGMem ) ;
#ifndef	_WIN32_WCE
	GlobalUnlock( hGMem ) ;
#endif	/* _WIN32_WCE */
	/* クリップボードクローズ */
	CloseClipboard() ;
	return 1 ;
}

int
ReceiveClipboard( char *sjis )
{
	LPCTSTR		cbptr ;
	int			cbsize, ret = 0 ;
#ifdef  _WIN32_WCE
	HLOCAL		hGMem ;
#else   /* _WIN32_WCE */
	HGLOBAL		hGMem ;
#endif  /* _WIN32_WCE */

	if ( !OpenClipboard( 0 ) ) {
		return 0 ;
	}
#ifdef  _WIN32_WCE
	hGMem = GetClipboardData( CF_UNICODETEXT ) ;
	cbsize = LocalSize( hGMem ) ;
	cbptr = (LPCTSTR) hGMem ;
#else   /* _WIN32_WCE */
	hGMem = GetClipboardData( CF_UNICODETEXT ) ;
	cbsize = GlobalSize( hGMem ) ;
	cbptr = (LPCTSTR) GlobalLock( hGMem ) ;
#endif  /* _WIN32_WCE */
	if ( !cbsize ) {
		goto exit ;
	}
	ret = unicode2sjis( cbptr, (LPBYTE) sjis, cbsize ) ;

exit:
#ifndef _WIN32_WCE
	GlobalUnlock( hGMem ) ;
#endif  /* _WIN32_WCE */
	CloseClipboard() ;
	return ret ;
}
#endif	/* NO_CLIPBOARD */
