module y4d_aux.widestring;

private import std.string;
private import std.utf;
private import std.windows.charset;

version(Win32){
extern(Windows) export int WideCharToMultiByte(
	 uint	  CodePage,
	 uint	 dwFlags,
	 char*	lpWideCharStr,
	 int	  cchWideChar,
	 char*	 lpMultiByteStr,
	 int	  cbMultiByte,
	 char*	 lpDefaultChar,
	 bool*	lpUsedDefaultChar);

extern(Windows) export int MultiByteToWideChar(
	 uint	  CodePage,
	 uint	 dwFlags,
	 char*	 lpMultiByteStr,
	 int	 cchMultiByte,
	 wchar*	 lpWideCharStr,
	 int		cchWideChar);

} else {
	extern(C){
		enum { LC_ALL = 0 }
		char* setlocale(int, char*);
		int mbstowcs(wchar*, char*, int);
		int wcstombs(char*, wchar*, int);
	}
}

///	日本語のコード変換を提供する。
/**
日本語が出ないと嫌なので、簡単な変換関数を用意しました。
Unicode文字列を、マルチバイト(shift_jis等)へ変換します。

Y.Tさんのコード
http://hp.vector.co.jp/authors/VA028375/contents/D_try2.html
を利用させていただいています。

<PRE>
その他、参考ページ。

USC-2とUTF-8:
http://homepage1.nifty.com/nomenclator/unicode/ucs_utf.htm

ShiftJIS,Unicode(UTF-8):
http://kamoland.com/comp/unicode.html

漢字コードについて:
http://tohoho.wakusei.ne.jp/wwwkanji.htm
</PRE>
*/
char[] toMBS(wchar[] s)
{
	char[] result;
version(Win32){
	result.length = WideCharToMultiByte(0, 0, cast(char*)s, s.length,
		null, 0, null, null);
	WideCharToMultiByte(0, 0, cast(char*)s, s.length, cast(char*) result,
		result.length, null, null);
}else{
	synchronized (locale_sync_object) {
		char* o = setlocale(LC_ALL, null);
		setlocale(LC_ALL, "");
		result.length = wcstombs(null, s, 0);
		wcstombs(result, s, result.length);
		setlocale(LC_ALL, o);
	}
}
	return result;
}

///	マルチバイト→unicode変換
wchar[] toWCS(char[] s)
{
	wchar[] result;
version(Win32){
	if (0 != useWfuncs) {
		result.length = MultiByteToWideChar(0, 0, cast(char*)s, s.length,
			null, 0);
		MultiByteToWideChar(0, 0, cast(char*)s, s.length,cast(wchar*)result,
			result.length);
	} else {
		result = cast(wchar[]) .toUTF16(fromMBSz(cast(char*) s));
	}

}else{
	synchronized (locale_sync_object) {
		char* o = setlocale(LC_ALL, null);
		setlocale(LC_ALL, "");
		result.length = mbstowcs(null, s, 0);
		mbstowcs(result, s, result.length);
		setlocale(LC_ALL, o);
	}
}
	return result;
}


///	ゼロ終端なWCSを返す
char* toMBSz(wchar[] s) { return std.string.toStringz(toMBS(s)); }

///	ゼロ終端なMBSを返す
char* toMBSz(wchar* s) { return std.string.toStringz(toMBS(s[0..std.string.wcslen(s)])); }

/// UTF8からWCSを返す
char[] toMBS(char[] s) { return toMBS(cast(wchar[]) std.utf.toUTF16(s)); }

/// UTF8からゼロ終端なWCSを返す
char* toMBSz(char[] s) { return std.string.toStringz(toMBS(s)); }

/*
///	ゼロ終端なWCSを返す
wchar[] toWCSz(char[] s) { return std.string.toStringz(toWCS(s)); }
///	ゼロ終端なWCSを返す
wchar[] toWCSz(char* s) { return std.string.toStringz(toWCS(s[0..std.string.strlen(s)])); }
*/

version(Win32){
} else {
/// set localeでスレッド排他するための同期オブジェクト
private static Object locale_sync_object;
}
