Index: Include/Classes/System/String.ab
===================================================================
--- Include/Classes/System/String.ab	(revision 135)
+++ Include/Classes/System/String.ab	(revision 139)
@@ -2,21 +2,45 @@
 
 #require <basic/function.sbp>
+
+#ifdef __STRING_IS_NOT_ALWAYS_UNICODE
+TypeDef StrChar = Char
+#ifndef UNICODE
+#define __STRING_IS_NOT_UNICODE
+#endif
+#else
+TypeDef StrChar = WCHAR
+#endif
 
 Class String
 	m_Length As Long
 Public
-	Chars As *Char
+	Chars As *StrChar
 
 	Sub String()
-		Chars = _System_calloc(SizeOf (Char) * 1)
+		Chars = 0
 		m_Length = 0
 	End Sub
 
-	Sub String(initStr As *Char)
+	Sub String(initStr As *Byte)
+		String()
+		Assign(initStr As PCTSTR)
+	End Sub
+
+	Sub String(initStr As PCSTR)
 		String()
 		Assign(initStr)
 	End Sub
 
-	Sub String(initStr As *Char, length As Long)
+	Sub String(initStr As PCSTR, length As Long)
+		String()
+		Assign(initStr, length)
+	End Sub
+
+	Sub String(initStr As PCWSTR)
+		String()
+		Assign(initStr)
+	End Sub
+
+	Sub String(initStr As PCWSTR, length As Long)
 		String()
 		Assign(initStr, length)
@@ -33,5 +57,5 @@
 	End Sub
 
-	Sub String(initChar As Char, length As Long)
+	Sub String(initChar As StrChar, length As Long)
 		ReSize(length, initChar)
 	End Sub
@@ -49,5 +73,5 @@
 	End Function
 
-	Function Operator() As *Char
+	Function Operator() As *StrChar
 		Return Chars
 	End Function
@@ -57,26 +81,59 @@
 	End Sub
 
-	Sub Operator = (text As *Char)
+	Sub Operator = (text As *Byte)
+		Assign(text As PCTSTR)
+	End Sub
+
+	Sub Operator = (text As PCSTR)
 		Assign(text)
 	End Sub
 
-	Const Function Operator [] (n As Long) As Char
+	Sub Operator = (text As PCWSTR)
+		Assign(text)
+	End Sub
+
+	Const Function Operator [] (n As Long) As StrChar
+#ifdef _DEBUG
+		If n > Length Then
+			'Throw ArgumentOutOfRangeException
+			Debug
+		End If
+#endif
 		Return Chars[n]
 	End Function
 
-	Sub Operator []= (n As Long, c As Char)
+	Sub Operator []= (n As Long, c As StrChar)
+#ifdef _DEBUG
+		If n >= Length Then
+			'Throw ArgumentOutOfRangeException
+			Debug
+		End If
+#endif
 		Chars[n] = c
 	End Sub
 
-	Const Function Operator + (pszText As *Char) As String
-		Return Concat(pszText, lstrlen(pszText))
+	Const Function Operator + (text As *Byte) As String
+		Return Concat(text As PCTSTR, lstrlen(text))
+	End Function
+
+	Const Function Operator + (text As PCSTR) As String
+		Return Concat(text, lstrlenA(text))
+	End Function
+
+	Const Function Operator + (text As PCWSTR) As String
+		Return Concat(text, lstrlenW(text))
 	End Function
 
 	Const Function Operator + (ByRef objString As String) As String
-		Return Concat(objString, objString.m_Length)
-	End Function
-
-	Const Function Operator & (pszText As *Char) As String
-		Dim tempString = This + pszText
+		Return Concat(objString.Chars, objString.m_Length)
+	End Function
+
+	Const Function Operator & (text As PCSTR) As String
+		Dim tempString = This + text
+		Return tempString
+	End Function
+
+	Const Function Operator & (text As PCWSTR) As String
+		Dim tempString = This + text
 		Return tempString
 	End Function
@@ -91,14 +148,14 @@
 	End Function
 
-	Const Function Operator == (text As *Char) As Long
+	Const Function Operator == (text As *StrChar) As Long
 		Return _System_StrCmp(This, text) = 0
 	End Function
 
 	Const Function Operator <> (ByRef objString As String) As Boolean
-		Return _System_StrCmp(This, objString)
-	End Function
-
-	Const Function Operator <> (text As *Char) As Boolean
-		Return _System_StrCmp(This, text)
+		Return _System_StrCmp(This, objString) <> 0
+	End Function
+
+	Const Function Operator <> (text As *StrChar) As Boolean
+		Return _System_StrCmp(This, text) <> 0
 	End Function
 
@@ -107,5 +164,5 @@
 	End Function
 
-	Const Function Operator < (text As *Char) As Boolean
+	Const Function Operator < (text As *StrChar) As Boolean
 		Return _System_StrCmp(This, text) < 0
 	End Function
@@ -115,5 +172,5 @@
 	End Function
 
-	Const Function Operator > (text As *Char) As Boolean
+	Const Function Operator > (text As *StrChar) As Boolean
 		Return _System_StrCmp(This, text) > 0
 	End Function
@@ -123,17 +180,17 @@
 	End Function
 
-	Const Function Operator <= (text As *Char) As Boolean
+	Const Function Operator <= (text As *StrChar) As Boolean
 		Return _System_StrCmp(This, text) <= 0
 	End Function
 
 	Const Function Operator >= (ByRef objString As String) As Boolean
-		Return _System_StrCmp(This, objString) => 0
-	End Function
-
-	Const Function Operator >= (text As *Char) As Boolean
-		Return _System_StrCmp(This, text) => 0
-	End Function
-
-	Const Function StrPtr() As *Char
+		Return _System_StrCmp(This, objString) >= 0
+	End Function
+
+	Const Function Operator >= (text As *StrChar) As Boolean
+		Return _System_StrCmp(This, text) >= 0
+	End Function
+
+	Const Function StrPtr() As *StrChar
 		Return Chars
 	End Function
@@ -145,5 +202,5 @@
 			oldLength = m_Length
 			If AllocStringBuffer(allocLength) <> 0 Then
-				ZeroMemory(VarPtr(Chars[oldLength]), SizeOf (Char) * (m_Length - oldLength + 1))
+				ZeroMemory(VarPtr(Chars[oldLength]), SizeOf (StrChar) * (m_Length - oldLength + 1))
 			End If
 		Else
@@ -153,5 +210,5 @@
 	End Sub
 
-	Sub ReSize(allocLength As Long, c As Char)
+	Sub ReSize(allocLength As Long, c As StrChar)
 		If allocLength < 0 Then
 			Exit Sub
@@ -160,5 +217,5 @@
 			oldLength = m_Length
 			If AllocStringBuffer(allocLength) <> 0 Then
-				Dim p = VarPtr(Chars[oldLength]) As *Char
+				Dim p = VarPtr(Chars[oldLength]) As *StrChar
 				Dim fillLen = m_Length - oldLength
 				Dim i As Long
@@ -173,10 +230,40 @@
 	End Sub
 
-	Sub Assign(text As *Char, textLength As Long)
+	Sub AssignFromStrChar(text As *StrChar, textLength As Long)
 		If text = Chars Then Exit Sub
 		If AllocStringBuffer(textLength) <> 0 Then
-			memcpy(Chars, text, SizeOf (Char) * textLength)
+			memcpy(Chars, text, SizeOf (StrChar) * textLength)
 			Chars[m_Length] = 0
-		End If		
+		End If
+	End Sub
+#ifdef __STRCHAR_IS_NOT_UNICODE
+	Sub AssignFromWideChar(text As PCWSTR, textLengthW As Long)
+		Dim textLengthA = WideCharToMultiByte(CP_THREAD_ACP, 0, text, textLengthW, 0, 0, 0, 0)
+		If AllocStringBuffer(textLengthA) <> 0 Then
+			WideCharToMultiByte(CP_THREAD_ACP, 0, text, textLengthW, Chars, textLengthA, 0, 0)
+		End If
+	End Sub
+#else
+	Sub AssignFromMultiByte(text As PCSTR, textLengthA As Long)
+		Dim textLengthW = MultiByteToWideChar(CP_THREAD_ACP, 0, text, textLengthA, 0, 0)
+		If AllocStringBuffer(textLengthW) <> 0 Then
+			MultiByteToWideChar(CP_THREAD_ACP, 0, text, textLengthA, Chars, textLengthW)
+		End If
+	End Sub
+#endif
+	Sub Assign(text As PCSTR, textLength As Long)
+#ifdef __STRING_IS_NOT_UNICODE
+		AssignFromStrChar(text, textLength)
+#else
+		AssignFromMultiByte(text, textLength)
+#endif
+	End Sub
+
+	Sub Assign(text As PCWSTR, textLength As Long)
+#ifdef __STRING_IS_NOT_UNICODE
+		AssignFromWideChar(text, textLength)
+#else
+		AssignFromStrChar(text, textLength)
+#endif
 	End Sub
 
@@ -185,24 +272,36 @@
 	End Sub
 
-	Sub Assign(text As *Char)
+	Sub Assign(text As PCSTR)
 		If text Then
-			Assign(text, lstrlen(text))
+			Assign(text, lstrlenA(text))
 		Else
-			'Chars=_System_realloc(Chars,1)
-			Chars[0] = 0
+			If Chars <> 0 Then
+				Chars[0] = 0
+			End If
 			m_Length = 0
 		End If
 	End Sub
 
-	Sub Append(text As *Char, textLength As Long)
+	Sub Assign(text As PCWSTR)
+		If text Then
+			Assign(text, lstrlenW(text))
+		Else
+			If Chars <> 0 Then
+				Chars[0] = 0
+			End If
+			m_Length = 0
+		End If
+	End Sub
+
+	Sub Append(text As *StrChar, textLength As Long)
 		Dim prevLen As Long
 		prevLen = m_Length
 		If AllocStringBuffer(m_Length + textLength) <> 0 Then
-			memcpy(VarPtr(Chars[prevLen]), text, SizeOf (Char) * textLength)
+			memcpy(VarPtr(Chars[prevLen]), text, SizeOf (StrChar) * textLength)
 			Chars[m_Length] = 0
 		End If
 	End Sub
 
-	Sub Append(text As *Char)
+	Sub Append(text As *StrChar)
 		Append(text, lstrlen(text))
 	End Sub
@@ -215,33 +314,58 @@
 		Return This
 	End Function
-
-	Const Function Concat(lpszText As *Char, textLength As Long) As String
-		Dim tempString As String
-		With tempString
-			.AllocStringBuffer(This.m_Length + textLength)
-			memcpy(.Chars, This.Chars, SizeOf (Char) * This.m_Length)
-			memcpy(VarPtr(.Chars[This.m_Length]), lpszText, SizeOf (Char) * textLength)
-			.Chars[.m_Length] = 0
+Private
+	Static Const Function ConcatStrChar(text1 As *StrChar, text1Length As Long, text2 As *StrChar, text2Length As Long) As String
+		With ConcatStrChar
+			.AllocStringBuffer(text1Length + text2Length)
+			memcpy(.Chars, text1, SizeOf (StrChar) * text1Length)
+			memcpy(VarPtr(.Chars[text1Length]), text2, SizeOf (StrChar) * text2Length)
+			.Chars[text1Length + text2Length] = 0
 		End With
-		Return tempString
-	End Function
-
+	End Function
+Public
+	Const Function Concat(text As PCSTR, len As Long) As String
+#ifdef __STRING_IS_NOT_UNICODE
+		Return ConcatStrChar(This.Chars, m_Length, text, len)
+#else
+		With Concat
+			Dim lenW = MultiByteToWideChar(CP_THREAD_ACP, 0, text, len, 0, 0)
+			.AllocStringBuffer(m_Length + lenW)
+			memcpy(.Chars, This.Chars, m_Length)
+			MultiByteToWideChar(CP_THREAD_ACP, 0, text, len, VarPtr(.Chars[m_Length]), lenW)
+			.Chars[m_Length + lenW] = 0
+		End With
+#endif
+	End Function
+
+	Const Function Concat(text As PCWSTR, len As Long) As String
+#ifdef __STRING_IS_NOT_UNICODE
+		With Concat
+			Dim lenA = MultiByteToWideChar(CP_THREAD_ACP, 0, text, len, 0, 0, 0, 0)
+			.AllocStringBuffer(m_Length + lenA)
+			memcpy(.Chars, This.Chars, m_Length)
+			MultiByteToWideChar(CP_THREAD_ACP, 0, text, len, VarPtr(.Chars[m_Length]), lenA, 0, 0)
+			.Chars[m_Length + lenA] = 0
+		End With
+#else
+		Return ConcatStrChar(This.Chars, m_Length, text, len)
+#endif
+	End Function
 	Const Function Contains(ByRef objString As String) As Boolean
 		Return IndexOf(objString, 0, m_Length) >= 0
 	End Function
 
-	Const Function Contains(lpszText As *Char) As Boolean
+	Const Function Contains(lpszText As *StrChar) As Boolean
 		Return IndexOf(lpszText, 0, m_Length) >= 0
 	End Function
 
-	Const Function IndexOf(lpszText As *Char) As Long
+	Const Function IndexOf(lpszText As *StrChar) As Long
 		Return IndexOf(lpszText, 0, m_Length)
 	End Function
 
-	Const Function IndexOf(lpszText As *Char, startIndex As Long) As Long
+	Const Function IndexOf(lpszText As *StrChar, startIndex As Long) As Long
 		Return IndexOf(lpszText, startIndex, m_Length - startIndex)
 	End Function
 
-	Const Function IndexOf(lpszText As *Char, startIndex As Long, count As Long) As Long
+	Const Function IndexOf(lpszText As *StrChar, startIndex As Long, count As Long) As Long
 		Dim length = lstrlen(lpszText)
 
@@ -265,13 +389,13 @@
 	End Function
 
-	Const Function LastIndexOf(lpszText As *Char) As Long
+	Const Function LastIndexOf(lpszText As *StrChar) As Long
 		Return LastIndexOf(lpszText, m_Length - 1, m_Length)
 	End Function
 
-	Const Function LastIndexOf(lpszText As *Char, startIndex As Long) As Long
-		Return LastIndexOf(lpszText As *Char, startIndex, startIndex + 1)
-	End Function
-
-	Const Function LastIndexOf(lpszText As *Char, startIndex As Long, count As Long) As Long
+	Const Function LastIndexOf(lpszText As *StrChar, startIndex As Long) As Long
+		Return LastIndexOf(lpszText As *StrChar, startIndex, startIndex + 1)
+	End Function
+
+	Const Function LastIndexOf(lpszText As *StrChar, startIndex As Long, count As Long) As Long
 		Dim length = lstrlen(lpszText)
 
@@ -295,9 +419,9 @@
 	End Function
 
-	Const Function StartsWith(lpszText As *Char) As Boolean
+	Const Function StartsWith(lpszText As *StrChar) As Boolean
 		Return IndexOf(lpszText) = 0
 	End Function
 
-	Const Function EndsWith(lpszText As *Char) As Boolean
+	Const Function EndsWith(lpszText As *StrChar) As Boolean
 		Return LastIndexOf(lpszText) = m_Length - lstrlen(lpszText)
 	End Function
@@ -307,9 +431,9 @@
 	End Function
 
-	Const Function Insert(startIndex As Long, text As *Char) As String
+	Const Function Insert(startIndex As Long, text As *StrChar) As String
 		Return Insert(startIndex, text, lstrlen(text))
 	End Function
 
-	Const Function Insert(startIndex As Long, text As *Char, length As Long) As String
+	Const Function Insert(startIndex As Long, text As *StrChar, length As Long) As String
 		If startIndex < 0 Or startIndex > m_Length Or length < 0 Then
 			Debug 'ArgumentOutOfRangeException
@@ -317,7 +441,7 @@
 		End If
 		Insert.ReSize(m_Length + length)
-		memcpy(Insert.Chars, Chars, SizeOf (Char) * startIndex)
-		memcpy(VarPtr(Insert.Chars[startIndex]), text, SizeOf (Char) * length)
-		memcpy(VarPtr(Insert.Chars[startIndex + length]), VarPtr(Chars[startIndex]), SizeOf (Char) * (m_Length - startIndex + 1))
+		memcpy(Insert.Chars, Chars, SizeOf (StrChar) * startIndex)
+		memcpy(VarPtr(Insert.Chars[startIndex]), text, SizeOf (StrChar) * length)
+		memcpy(VarPtr(Insert.Chars[startIndex + length]), VarPtr(Chars[startIndex]), SizeOf (StrChar) * (m_Length - startIndex + 1))
 	End Function
 
@@ -332,5 +456,5 @@
 		Dim temp As String
 		temp.AllocStringBuffer(length)
-		memcpy(temp.Chars, VarPtr(Chars[startIndex]), SizeOf (Char) * length)
+		memcpy(temp.Chars, VarPtr(Chars[startIndex]), SizeOf (StrChar) * length)
 		Chars[m_Length] = 0
 		Return temp
@@ -343,5 +467,5 @@
 
 		Remove.ReSize(startIndex)
-		memcpy(Remove.Chars, This.Chars, SizeOf (Char) * startIndex)
+		memcpy(Remove.Chars, This.Chars, SizeOf (StrChar) * startIndex)
 	End Function
 
@@ -352,6 +476,6 @@
 
 		Remove.ReSize(m_Length - count)
-		memcpy(Remove.Chars, This.Chars, SizeOf (Char) * startIndex)
-		memcpy(VarPtr(Remove.Chars[startIndex]), VarPtr(This.Chars[startIndex + count]), SizeOf (Char) * (m_Length - startIndex - count))
+		memcpy(Remove.Chars, This.Chars, SizeOf (StrChar) * startIndex)
+		memcpy(VarPtr(Remove.Chars[startIndex]), VarPtr(This.Chars[startIndex + count]), SizeOf (StrChar) * (m_Length - startIndex - count))
 	End Function
 /*
@@ -365,5 +489,5 @@
 	End Function
 */
-	Const Function Replace(oldChar As Char, newChar As Char) As String
+	Const Function Replace(oldChar As StrChar, newChar As StrChar) As String
 		Replace = Copy(This)
 		With Replace
@@ -387,5 +511,5 @@
 	End Function
 
-	Const Function Replace(oldStr As *Char, newStr As *Char)
+	Const Function Replace(oldStr As *StrChar, newStr As *StrChar)
 		If oldStr = 0 Then Debug 'Throw ArgumentNullException
 		If newStr = 0 Then newStr = ""
@@ -393,5 +517,5 @@
 	End Function
 
-	Const Function Replace(oldStr As *Char, oldLen As Long, newStr As *Char, newLen As Long) As String
+	Const Function Replace(oldStr As *StrChar, oldLen As Long, newStr As *StrChar, newLen As Long) As String
 		If oldStr = 0 Then Debug 'Throw ArgumentNullException
 		If newStr = 0 Then
@@ -420,5 +544,5 @@
 	Sub Swap(ByRef x As String)
 		Dim tempLen As Long
-		Dim tempChars As *Char
+		Dim tempChars As *StrChar
 		tempLen = x.m_Length
 		tempChars = x.Chars
@@ -435,14 +559,14 @@
 	Static Function Copy(s As String) As String
 		Copy.Resize(s.m_Length)
-		memcpy(Copy.Chars, This.Chars, SizeOf (Char) * m_Length)
+		memcpy(Copy.Chars, This.Chars, SizeOf (StrChar) * m_Length)
 	End Function
 
 Private
 	' メモリ確保に失敗すると元の文字列は失われない。（例外安全でいう強い保障）
-	Function AllocStringBuffer(textLength As Long) As *Char
+	Function AllocStringBuffer(textLength As Long) As *StrChar
 		If textLength < 0 Then
 			Return 0
 		ElseIf textLength > m_Length Then
-			AllocStringBuffer = _System_realloc(Chars, SizeOf(Char) * (textLength + 1))
+			AllocStringBuffer = _System_realloc(Chars, SizeOf(StrChar) * (textLength + 1))
 			If AllocStringBuffer <> 0 Then
 				m_Length = textLength
@@ -455,5 +579,5 @@
 	End Function
 
-	Function ReplaceCore(oldStr As *Char, oldLen As Long, newStr As *Char, newLen As Long) As String
+	Function ReplaceCore(oldStr As *StrChar, oldLen As Long, newStr As *StrChar, newLen As Long) As String
 		If oldLen = 0 Then
 			Debug 'Throw ArgumentException
@@ -478,2 +602,22 @@
 End Class
 
+Function GetMultiByteStr(ByRef s As String) As PCSTR
+#ifdef __STRING_IS_NOT_UNICODE
+	GetMultiByteStr = s.Chars
+#else
+	Dim sizeA = WideCharToMultiByte(CP_THREAD_ACP, 0, s.Chars, s.Length + 1, 0, 0, 0, 0)
+	GetMultiByteStr = GC_malloc_atomic(SizeOf (SByte) * sizeA)
+	WideCharToMultiByte(CP_THREAD_ACP, 0, s.Chars, s.Length + 1, GetMultiByteStr, sizeA, 0, 0)
+#endif
+End Function
+
+Function GetWideCharStr(ByRef s As String) As PCSTR
+#ifdef __STRING_IS_NOT_UNICODE
+	Dim sizeW = MultiByteToWideChar(CP_THREAD_ACP, 0, s.Chars, s.Length + 1, 0, 0)
+	GetWideCharStr = GC_malloc_atomic(SizeOf (WCHAR) * sizeW)
+	MultiByteToWideChar(CP_THREAD_ACP, 0, s.Chars, s.Length + 1, GetWideCharStr, sizeW)
+#else
+	GetMultiByteStr = s.Chars
+#endif
+End Function
+
