#ifndef	STRICT
#define	STRICT
#endif	/* STRICT */
#ifndef	UNICODE
#define	UNICODE
#endif	/* UNICODE */
#ifndef	_UNICODE
#define	_UNICODE
#endif	/* _UNICODE */
#include	<windows.h>
#include	<windowsx.h>
#include	<winuser.h>
#include	<string.h>
#include	<commctrl.h>
#include	<commdlg.h>
#include	<tchar.h>
#include	"kctrl.h"

extern	DWORD	FontZenVW ;
extern	DWORD	FontHanVW ;
extern	DWORD	FontVH ;
extern	DWORD	TabWidth ;
extern	DWORD	F_convmode ;

#ifdef	_WIN32_WCE
HINSTANCE	hLib = 0 ;
typedef	int(*WCTMB)(UINT,DWORD,LPCWSTR,int,LPSTR ,int,LPCSTR,LPBOOL) ;
typedef	int(*MBTWC)(UINT,DWORD,LPCSTR ,int,LPWSTR,int) ;
int (*WideCharToMultiByte)( UINT CodePage, DWORD dwFlags, LPCWSTR lpWideCharStr, int cchWideChar, LPSTR lpMultiByteStr, int cchMultiByte, LPCSTR lpDefaultChar, LPBOOL lpUserDefaultChar ) ;
int (*MultiByteToWideChar)( UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr, int cchMultiByte, LPWSTR lpWideCharStr, int cchWideChar ) ;
#endif	/* _WIN32_WCE */

#define		MAX_FONT		2
#define		BaseKey			TEXT("Software\\Gawaro\\Kctrl")
#define		VAR_TTFONT		TEXT("TTFont")
#define		VAR_FONTWIDTH	TEXT("FontWidth")
#define		VAR_FONTHEIGHT	TEXT("FontHeight")

static	BOOL	get_reg( void ) ;

HFONT		hFont[ MAX_FONT ] ;
LOGFONT		LF_MSG[ MAX_FONT ] = {
	{ 14, 7, 0, 0, 0x190, 0x00, 0x00, 0x00, 0x80, 0x01, 0x02, 0x01, 0x37,
		{0xFF2D, 0xFF33, 0x0020, 0x30B4, 0x30B7, 0x30C3, 0x30AF, 0x0000} },
	{ 12, 6, 0, 0, 0x190, 0x00, 0x00, 0x00, 0x80, 0x01, 0x02, 0x01, 0x37,
		{0xFF2D, 0xFF33, 0x0020, 0x30B4, 0x30B7, 0x30C3, 0x30AF, 0x0000} },
} ;

DWORD		g_dwCurFont = 0 ;

BOOL
InitLocal( void )
{
	int		i ;

#ifdef	_WIN32_WCE
	hLib = LoadLibrary( TEXT("COREDLL.DLL") ) ;
	if ( hLib == NULL ) {
		return FALSE ;
	}
	WideCharToMultiByte = (WCTMB) GetProcAddress( hLib, TEXT("WideCharToMultiByte") ) ;
	if ( WideCharToMultiByte == NULL ) {
		return FALSE ;
	}
	MultiByteToWideChar = (MBTWC) GetProcAddress( hLib, TEXT("MultiByteToWideChar") ) ;
	if ( MultiByteToWideChar == NULL ) {
		return FALSE ;
	}
#endif	/* _WIN32_WCE */
	get_reg() ;
	for ( i = 0 ; i < MAX_FONT ; i ++ ) {
		hFont[i] = LF_MSG[i].lfWidth ? CreateFontIndirect( &LF_MSG[i] ) : 0 ;
	}
	if ( !hFont[0] ) {
		return FALSE ;
	}
	g_dwCurFont = 0 ;
	FontHanVW = LF_MSG[g_dwCurFont].lfWidth ;
	FontZenVW = LF_MSG[g_dwCurFont].lfWidth * 2 ;
	FontVH    = LF_MSG[g_dwCurFont].lfHeight + 1 ;
	/* 日本語版ではコード変換しない */
	F_convmode = MODE_NOCONV ;
	SetLastError( 0 ) ;
	return TRUE ;
}

void
ReleaseLocal( void )
{
	int		i ;

	for ( i = 0 ; i < MAX_FONT ; i ++ ) {
		if ( hFont[i] ) {
			DeleteObject( hFont[i] ) ;
		}
	}
#ifdef	_WIN32_WCE
	if ( hLib ) {
		FreeLibrary( hLib ) ;
	}
#endif	/* _WIN32_WCE */
}

void
KDrawText( HDC hDC, LPCTSTR str, int len, LPRECT pos, UINT format )
{
	RECT	rect ;
	DWORD	col = 0, cw = 0, num = 0, max  ;
	TCHAR	c, outbuf[ 256 ], *dst = outbuf ;
	HFONT	oldfont = SelectObject( hDC, hFont[g_dwCurFont] ) ;

	max = (sizeof outbuf / sizeof *outbuf) - TabWidth - 8 ;
	while ( (c = *str++) && (num < max) ) {
		if ( c == 9 ) {
			cw = TabWidth - (col % TabWidth) ;
			col += cw ;
			do {
				*dst++ = TEXT(' ') ;
				num ++ ;
			} while ( -- cw ) ;
			continue ;
		} else if ( c & 0xFF00 ) {
			col ++ ;
		}
		col ++ ;
		*dst++ = c ;		num ++ ;
	}
	*dst = 0 ;
	memcpy( &rect, pos, sizeof (RECT) ) ;
	if ( !(rect.top > rect.bottom && rect.right == 640 && rect.bottom == 16) ) {
		rect.bottom = rect.top + FontVH - 1 ;
	}
	FillRect( hDC, &rect, GetStockObject( WHITE_BRUSH ) ) ;
	DrawText( hDC, outbuf, len, &rect, format|DT_NOPREFIX ) ;
	SelectObject( hDC, oldfont ) ;
}

void
KDrawTextW( HDC hDC, LPCTSTR str, int len, LPRECT pos, UINT format )
{
	KDrawText( hDC, str, len, pos, format ) ;
}

void
KDrawTextI( HDC hDC, LPCTSTR str, int len, LPRECT pos, UINT format )
{
	RECT	rect ;
	DWORD	col = 0, cw = 0, num = 0, max  ;
	TCHAR	c, outbuf[ 256 ], *dst = outbuf ;
	HFONT	oldfont = SelectObject( hDC, hFont[g_dwCurFont] ) ;
	HBRUSH	hOldBrush = SelectObject( hDC, WHITE_BRUSH ) ;

	max = (sizeof outbuf / sizeof *outbuf) - TabWidth - 8 ;
	while ( (c = *str++) && (num < max) ) {
		if ( c == 9 ) {
			cw = TabWidth - (col % TabWidth) ;
			col += cw ;
			do {
				*dst++ = TEXT(' ') ;
				num ++ ;
			} while ( -- cw ) ;
			continue ;
		} else if ( c & 0xFF00 ) {
			col ++ ;
		}
		col ++ ;
		*dst++ = c ;		num ++ ;
	}
	*dst = 0 ;
	memcpy( &rect, pos, sizeof (RECT) ) ;
	DrawText( hDC, outbuf, len, &rect, DT_CALCRECT|DT_NOPREFIX ) ;
	FillRect( hDC, pos, GetStockObject( WHITE_BRUSH ) ) ;
	DrawText( hDC, outbuf, len, pos, format|DT_NOPREFIX ) ;
	PatBlt( hDC,
			rect.left, rect.top, rect.right - rect.left + 1, rect.bottom - rect.top + 1,
			PATINVERT ) ;
	SelectObject( hDC, hOldBrush ) ;
	SelectObject( hDC, oldfont ) ;
}

#define		CP_ACP		0

/*
 * 　名称：Unicode→SJISコード変換
 * 　略称：unicode2sjis
 * 　概要：Unicode文字列をSJIS文字列に変換する
 * 引き数：src = Unicode文字列
 * 　　　：dst = SJIS文字列を格納する領域へのポインタ
 * 　　　：max = SJIS文字列を格納する領域の最大バイト数
 * 戻り値：DWORD = 変換結果のバイト数(dst=0の時は必要バイト数)\0も含む
 */
DWORD
unicode2sjis( LPCTSTR src, BYTE *dst, DWORD max )
{
	return WideCharToMultiByte( CP_ACP, 0, src, -1, dst, dst ? max : 0, NULL, NULL ) ;
}

/*
 * 　名称：SJIS→Unicodeコード変換
 * 　略称：sjis2unicode
 * 　概要：SJIS文字列をUnicode文字列に変換する
 * 引き数：src = SJIS文字列
 * 　　　：dst = Unicode文字列を格納する領域へのポインタ
 * 　　　：max = Unicode文字列を格納する領域の最大バイト数
 * 戻り値：DWORD = 変換結果のバイト数(dst=0の時は必要バイト数)\0も含む
 */
DWORD
sjis2unicode( const BYTE *src, LPTSTR dst, DWORD max )
{
	DWORD	required, count ;

	required = dst ? max / sizeof (TCHAR) : 0 ;
	count = MultiByteToWideChar( CP_ACP, 0, src, -1, dst, required ) ;
	return count * sizeof (TCHAR) ;
}

/*
 * 　名称：シフトＪＩＳコード→UNICODE変換
 * 　略称：sjis2unicode_char
 * 　概要：シフトＪＩＳコード文字をUNICODEに変換する
 * 引き数：sjis(WORD) = シフトＪＩＳコード
 * 戻り値：TCHAR = UNICODE
 */
TCHAR
sjis2unicode_char( WORD sjis )
{
	BYTE	sjisstr[ 3 ] ;
	TCHAR	unicode[ 3 ] ;

	if ( sjis / 256 ) {
		sjisstr[0] = (BYTE) (sjis / 256) ;
		sjisstr[1] = (BYTE) (sjis % 256) ;
		sjisstr[2] = 0 ;
	} else {
		sjisstr[0] = (BYTE) (sjis % 256) ;
		sjisstr[1] = 0 ;
	}
	sjis2unicode( sjisstr, unicode, sizeof unicode ) ;
	return *unicode ;
}

/*
 * 　名称：UNICODE→シフトＪＩＳコード変換
 * 　略称：unicode2sjis_char
 * 　概要：UNICODE文字をシフトＪＩＳコードに変換する
 * 引き数：unicode(TCHAR) = UNICODE
 * 戻り値：WORD = シフトＪＩＳコード
 */
WORD
unicode2sjis_char( TCHAR unicode )
{
	BYTE	sjis[ 3 ] ;
	TCHAR	unicodestr[ 2 ] ;

	unicodestr[0] = unicode ;
	unicodestr[1] = 0 ;
	unicode2sjis( unicodestr, sjis, sizeof sjis ) ;
	if ( sjis[1] ) {
		return ((WORD) sjis[0]) << 8 | (WORD) sjis[1] ;
	}
	return (WORD) sjis[0] ;
}

/*
 * 　名称：半角文字チェック
 * 　略称：is_hankaku
 * 　概要：Unicode文字が半角かどうか調べる
 * 引き数：c = Unicode文字
 * 戻り値：BOOL = TRUE:半角, FALSE:全角
 */
BOOL
is_hankaku( TCHAR c )
{
	return (c >= 0xFF60 && c <= 0xFF9F) || (c < 0x0080) ;
}

/*
 * 　名称：KCTRLロケール取得
 * 　略称：GetKLocale
 * 　概要：KCTRL(US)やKCTRL(JP)などの区別を返す
 * 引き数：なし
 * 戻り値：DWORD = 0:US, 1:JP, ...
 */
DWORD
GetKLocale( void )
{
	return LOCALE_JAPAN ;
}

/*
 * 　名称：フォント数取得
 * 　略称：GetNumFont
 * 　概要：表示に使用できるフォント数を調べる
 * 引き数：なし
 * 戻り値：DWORD = フォント数
 */
DWORD
GetNumFont( void )
{
	return MAX_FONT ;
}

/*
 * 　名称：利用フォント設定
 * 　略称：SetCurFont
 * 　概要：表示に使用するフォントを決める
 * 引き数：index(DWORD) = 番号(0..1)
 * 戻り値：なし
 */
void
SetCurFont( DWORD index )
{
	g_dwCurFont = index ;
	FontHanVW = LF_MSG[g_dwCurFont].lfWidth ;
	FontZenVW = LF_MSG[g_dwCurFont].lfWidth * 2 ;
	FontVH    = LF_MSG[g_dwCurFont].lfHeight + 1 ;
}

/*
 * 　名称：現在フォント取得
 * 　略称：GetCurFont
 * 　概要：表示に使用しているフォントを調べる
 * 引き数：なし
 * 戻り値：DWORD = 0..1
 */
DWORD
GetCurFont( void )
{
	return g_dwCurFont ;
}

static	BOOL
get_reg( void )
{
	HKEY	hk ;
	LONG	lret ;
	LPBYTE	lpData ;
	DWORD	dwType, cbData, dValue, i ;
	TCHAR	name[ 64 ], sValue[ 256 ] ;

	/* レジストリキーをオープンする */
	lret = RegOpenKeyEx( HKEY_CURRENT_USER, BaseKey, 0,
						 KEY_QUERY_VALUE, &hk ) ;
	if ( lret != ERROR_SUCCESS ) {
		return FALSE ;
	}
	for ( i = 0 ; i < MAX_FONT ; i ++ ) {
		/* TrueTypeフォント名 */
		wsprintf( name, TEXT("%s%d"), VAR_TTFONT, i ) ;
		dwType = REG_SZ ;
		lpData = (LPBYTE) sValue ;
		cbData = sizeof sValue ;
		if ( RegQueryValueEx( hk, name, NULL, &dwType, lpData, &cbData ) == ERROR_SUCCESS ) {
			_tcscpy( LF_MSG[i].lfFaceName, sValue ) ;
		}
		/* フォント幅 */
		wsprintf( name, TEXT("%s%d"), VAR_FONTWIDTH, i ) ;
		dwType = REG_DWORD ;
		lpData = (LPBYTE) &dValue ;
		cbData = sizeof dValue ;
		if ( RegQueryValueEx( hk, name, NULL, &dwType, lpData, &cbData ) == ERROR_SUCCESS ) {
			LF_MSG[i].lfWidth = dValue ;
		}
		/* フォント高 */
		wsprintf( name, TEXT("%s%d"), VAR_FONTHEIGHT, i ) ;
		dwType = REG_DWORD ;
		lpData = (LPBYTE) &dValue ;
		cbData = sizeof dValue ;
		if ( RegQueryValueEx( hk, name, NULL, &dwType, lpData, &cbData ) == ERROR_SUCCESS ) {
			LF_MSG[i].lfHeight = dValue ;
		}
	}
	/* レジストリクローズ */
	RegCloseKey( hk ) ;
	return TRUE ;
}
