[ttssh2-commit] [9471] TTProxyのログをログフォルダへ出力

Back to archive index
scmno****@osdn***** scmno****@osdn*****
2021年 10月 14日 (木) 23:52:23 JST


Revision: 9471
          https://osdn.net/projects/ttssh2/scm/svn/commits/9471
Author:   zmatsuo
Date:     2021-10-14 23:52:23 +0900 (Thu, 14 Oct 2021)
Log Message:
-----------
TTProxyのログをログフォルダへ出力

- ファイル保存(コモンダイアログ)をUnicode版に変更
  - GetSaveFileNameW()
- logger
  - logger::open() を Unicodeファイル名に変更
  - ログフォルダ設定を追加
    - logger::set_folder()
- IniFile
  - IniFile::getStringW() を追加
  - Unicode文字列を取得
    - Unicode版エスケープ文字展開が必要になった
    - StringUtil::escapeW(), unescapeW()
- StringUtil
  - StringUtil::escapeW() unescapeW() 追加
  - WStringBuffer クラスが必要になった
- WStringBuffer
  - 追加
  - StringBufferのwchar_t版
- YCL/Windows.h
  - GetWindowTextLengthW(),SetWindowTextLengthW() を追加
    - Unicode文字列の設定,取得
- ttlib_static.cpp
  - IsRelativePathW() を追加

Modified Paths:
--------------
    trunk/TTProxy/CMakeLists.txt
    trunk/TTProxy/Logger.h
    trunk/TTProxy/ProxyWSockHook.h
    trunk/TTProxy/TTProxy.h
    trunk/TTProxy/YCL/include/YCL/IniFile.h
    trunk/TTProxy/YCL/include/YCL/StringUtil.h
    trunk/TTProxy/YCL/include/YCL/Window.h
    trunk/teraterm/common/ttlib.h
    trunk/teraterm/common/ttlib_static_cpp.cpp

Added Paths:
-----------
    trunk/TTProxy/YCL/include/YCL/WString.h
    trunk/TTProxy/YCL/include/YCL/WStringBuffer.h

Removed Paths:
-------------
    trunk/TTProxy/YCL/include/YCL/wstring.h

-------------- next part --------------
Modified: trunk/TTProxy/CMakeLists.txt
===================================================================
--- trunk/TTProxy/CMakeLists.txt	2021-10-14 14:52:13 UTC (rev 9470)
+++ trunk/TTProxy/CMakeLists.txt	2021-10-14 14:52:23 UTC (rev 9471)
@@ -70,7 +70,6 @@
   PRIVATE
   YCL/include/YCL/Array.h
   YCL/include/YCL/ComboBoxCtrl.h
-  YCL/include/YCL/common.h
   YCL/include/YCL/Dialog.h
   YCL/include/YCL/DynamicLinkLibrary.h
   YCL/include/YCL/EditBoxCtrl.h
@@ -88,8 +87,10 @@
   YCL/include/YCL/StringUtil.h
   YCL/include/YCL/ValueCtrl.h
   YCL/include/YCL/Vector.h
+  YCL/include/YCL/WString.h
+  YCL/include/YCL/WStringBuffer.h
   YCL/include/YCL/Window.h
-  YCL/include/YCL/wstring.h
+  YCL/include/YCL/common.h
   )
 
 source_group(

Modified: trunk/TTProxy/Logger.h
===================================================================
--- trunk/TTProxy/Logger.h	2021-10-14 14:52:13 UTC (rev 9470)
+++ trunk/TTProxy/Logger.h	2021-10-14 14:52:23 UTC (rev 9471)
@@ -7,6 +7,7 @@
 class Logger {
 private:
 	HANDLE logfile;
+	WString folder_;
 	Logger():logfile(INVALID_HANDLE_VALUE) {
 	}
 public:
@@ -78,15 +79,26 @@
 	}
 
 public:
-	static void open(String filename) {
+	static void open(WString filename) {
 		close();
-		if (filename != NULL) {
-			HANDLE logfile = ::CreateFile(filename, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
-			if (logfile != INVALID_HANDLE_VALUE) {
-				::SetFilePointer(logfile, 0, NULL, FILE_END);
-				instance().logfile = logfile;
-			}
+
+		if (filename == NULL) {
+			return;
 		}
+
+		WString full_filename;
+		if (IsRelativePathW(filename)) {
+			full_filename = instance().folder_ + L"\\" + filename;
+		}
+		else {
+			full_filename = filename;
+		}
+
+		HANDLE logfile = ::CreateFileW(full_filename, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+		if (logfile != INVALID_HANDLE_VALUE) {
+			::SetFilePointer(logfile, 0, NULL, FILE_END);
+			instance().logfile = logfile;
+		}
 	}
 	static void close() {
 		if (instance().logfile != INVALID_HANDLE_VALUE) {
@@ -100,6 +112,9 @@
 	static void log(const char* label, const unsigned char* data, int size) {
 		instance().debuglog_binary(label, data, size);
 	}
+	static void set_folder(const WString &folder) {
+		instance().folder_ = folder;
+	}
 };
 
 #endif//_YEBISOCKS_LOGGER_H_

Modified: trunk/TTProxy/ProxyWSockHook.h
===================================================================
--- trunk/TTProxy/ProxyWSockHook.h	2021-10-14 14:52:13 UTC (rev 9470)
+++ trunk/TTProxy/ProxyWSockHook.h	2021-10-14 14:52:23 UTC (rev 9471)
@@ -726,30 +726,29 @@
     protected:
         virtual bool dispatch(UINT message, WPARAM wParam, LPARAM lParam) {
             if (message == WM_COMMAND && wParam == MAKEWPARAM(IDC_REFER, BN_CLICKED)) {
-                char buffer[1024];
-                char uimsg[MAX_UIMSG];
-                OPENFILENAME ofn = {
-                    sizeof ofn,
-                    *this,
-                };
+                wchar_t buffer[1024];
+                wchar_t uimsg[MAX_UIMSG];
+				OPENFILENAMEW ofn = {};
+                ofn.lStructSize = get_OPENFILENAME_SIZEW();
+                ofn.hwndOwner = *this;
                 ofn.lpstrFile = buffer;
-                ofn.nMaxFile = countof(buffer);
+                ofn.nMaxFile = _countof(buffer);
                 ofn.Flags = OFN_LONGNAMES | OFN_NONETWORKBUTTON | OFN_PATHMUSTEXIST | OFN_NOREADONLYRETURN | OFN_HIDEREADONLY;
-                UTIL_get_lang_msg("MSG_LOGFILE_SELECT", uimsg, sizeof(uimsg),
-                                  "Select Logfile");
+                UTIL_get_lang_msgW("MSG_LOGFILE_SELECT", uimsg, _countof(uimsg),
+                                   L"Select Logfile");
                 ofn.lpstrTitle = uimsg;
                 if (logfile != NULL) {
-                    strcpy_s(buffer, sizeof buffer, logfile);
+                    wcscpy_s(buffer, _countof(buffer), logfile);
                 }else{
                     buffer[0] = '\0';
                 }
-                if (::GetSaveFileName(&ofn)) {
+                if (::GetSaveFileNameW(&ofn)) {
                     if (buffer[0] != '\0') {
                         logfile = buffer;
                     }else{
                         logfile = NULL;
                     }
-                    log.SetWindowText(buffer);
+                    log.SetWindowTextW(buffer);
                 }
                 return true;
             }
@@ -806,7 +805,7 @@
             erro.SetWindowText(ErrorMessage);
 
             if (logfile != NULL)
-                log.SetWindowText(logfile);
+                log.SetWindowTextW(logfile);
 
             CenterWindow((HWND)*this, GetParent());
 
@@ -835,7 +834,7 @@
             ConnectedMessage = conn.GetWindowText();
             ErrorMessage     = erro.GetWindowText();
 
-            logfile = log.GetWindowTextLength() > 0 ? log.GetWindowText() : NULL;
+            logfile = log.GetWindowTextLengthW() > 0 ? log.GetWindowTextW() : NULL;
 
             Dialog::onOK();
         }
@@ -843,7 +842,7 @@
             Dialog::onCancel();
         }
     public:
-        String logfile;
+        WString logfile;
         int timeout;
         int resolve;
 
@@ -1089,11 +1088,11 @@
             };
             SetI18nDlgStrsW(hWnd, "TTProxy", text_info, _countof(text_info), UILanguageFileW);
 
-            UTIL_get_lang_msgW("DLG_ABOUT_EXTENSION", uimsg, sizeof(uimsg),
+            UTIL_get_lang_msgW("DLG_ABOUT_EXTENSION", uimsg, _countof(uimsg),
                                L"Tera Term proxy extension");
-            UTIL_get_lang_msgW("DLG_ABOUT_YEBISUYA", uimsg2, sizeof(uimsg2),
+            UTIL_get_lang_msgW("DLG_ABOUT_YEBISUYA", uimsg2, _countof(uimsg2),
                                L"YebisuyaHompo");
-            UTIL_get_lang_msgW("DLG_ABOUT_HOMEPAGE", uimsg3, sizeof(uimsg3),
+            UTIL_get_lang_msgW("DLG_ABOUT_HOMEPAGE", uimsg3, _countof(uimsg3),
                                L"TTProxy home page");
             GetDlgItemTextW(hWnd, IDC_VERSION, buf, _countof(buf));
             len = wcslen(buf) + 50;
@@ -2146,7 +2145,7 @@
         return ORIG_closesocket(s);
     }
 
-    String logfile;
+    WString logfile;
     int timeout;
     enum SocksResolve {
         RESOLVE_AUTO,
@@ -2218,7 +2217,7 @@
         prompt_table[3] = ini.getString("TelnetConnectedMessage", "-- Connected to ");
         prompt_table[4] = ini.getString("TelnetErrorMessage", "!!!!!!!!");
 
-        logfile = ini.getString("DebugLog");
+        logfile = ini.getStringW(L"DebugLog");
         Logger::open(logfile);
     }
     void _save(IniFile& ini) {
@@ -2269,7 +2268,7 @@
         ini.setString("TelnetConnectedMessage", prompt_table[3]);
         ini.setString("TelnetErrorMessage",     prompt_table[4]);
 
-        ini.setString("DebugLog", logfile);
+        ini.setString(L"DebugLog", logfile);
     }
 public:
     static void setOwner(HWND owner) {
@@ -2348,7 +2347,7 @@
     static String generateURL() {
         return instance().defaultProxy.generateURL();
     }
-        static String parseURL(const char* url, BOOL prefix) {
+    static String parseURL(const char* url, BOOL prefix) {
         ProxyInfo proxy;
         String realhost = ProxyInfo::parse(url, proxy);
         if (realhost != NULL) {

Modified: trunk/TTProxy/TTProxy.h
===================================================================
--- trunk/TTProxy/TTProxy.h	2021-10-14 14:52:13 UTC (rev 9470)
+++ trunk/TTProxy/TTProxy.h	2021-10-14 14:52:23 UTC (rev 9471)
@@ -206,6 +206,7 @@
 	static void PASCAL TTXInit(PTTSet ts, PComVar cv) {
 		getInstance().ts = ts;
 		getInstance().cv = cv;
+		Logger::set_folder(ts->LogDirW);
 
 		ProxyWSockHook::setMessageShower(&getInstance().shower);
 	}

Modified: trunk/TTProxy/YCL/include/YCL/IniFile.h
===================================================================
--- trunk/TTProxy/YCL/include/YCL/IniFile.h	2021-10-14 14:52:13 UTC (rev 9470)
+++ trunk/TTProxy/YCL/include/YCL/IniFile.h	2021-10-14 14:52:23 UTC (rev 9471)
@@ -16,9 +16,11 @@
 #include <YCL/Enumeration.h>
 #include <YCL/Vector.h>
 #include <YCL/Hashtable.h>
-#include <YCL/wstring.h>
+#include <YCL/WString.h>
 
 #include "inifile_com.h"
+#include "asprintf.h"
+#include "codeconv.h"
 
 namespace yebisuya {
 
@@ -171,6 +173,23 @@
 		exists = true;
 		return NULL;
 	}
+	static WString getStringW(const wchar_t* filename, const char* section, const wchar_t* name, bool& exists, size_t size) {
+		wchar_t* buffer = (wchar_t*) alloca(sizeof(wchar_t) * size);
+		wchar_t* sectionW = ToWcharA(section);
+		size_t len = GetPrivateProfileStringW(sectionW, name, L"\n:", buffer, size, filename);
+		free(sectionW);
+		if (len < size - 2) {
+			// \x89\xFC\x8Ds\x82\xF0\x8A܂񂾕\xB6\x8E\x9A\x97\xF1\x82\xCDini\x83t\x83@\x83C\x83\x8B\x82\xA9\x82\xE7\x82͎擾\x82ł\xAB\x82Ȃ\xA2\x82̂Ŏ擾\x8E\xB8\x94s\x82\xB5\x82\xBD\x82\xB1\x82Ƃ\xAA\x95\xAA\x82\xA9\x82\xE9
+			if (buffer[0] == '\n') {
+				exists = false;
+				return NULL;
+			}
+			// \x83G\x83X\x83P\x81[\x83v\x95\xB6\x8E\x9A\x82\xF0\x93W\x8AJ
+			return StringUtil::unescapeW(buffer);
+		}
+		exists = true;
+		return NULL;
+	}
 	static String generateSectionName(const char* parentSection, const char* subkeyName) {
 		StringBuffer buffer = parentSection;
 		buffer.append('\\');
@@ -234,6 +253,21 @@
 		}
 		return defaultValue;
 	}
+	WString getStringW(const wchar_t* name)const {
+		return getStringW(name, NULL);
+	}
+	WString getStringW(const wchar_t* name, WString defaultValue)const {
+		if (filename != NULL && section != NULL && name != NULL) {
+			size_t size = 256;
+			WString string;
+			bool exists;
+			while ((string = getStringW(filename, section, name, exists, size)) == NULL && exists)
+				size += 256;
+			if (string != NULL)
+				return string;
+		}
+		return defaultValue;
+	}
 	bool getBoolean(const char* name, bool defaultValue = false)const {
 		String string = getString(name);
 		if (string != NULL) {
@@ -263,6 +297,25 @@
 		}
 		return false;
 	}
+	bool setString(const wchar_t* name, WString value) {
+		if (filename == NULL || section == NULL || name == NULL) {
+			return false;
+		}
+
+		// NULL\x82łȂ\xAF\x82\xEA\x82΃G\x83X\x83P\x81[\x83v\x82\xB5\x82Ă\xA9\x82\xE7""\x82Ŋ\x87\x82\xE9
+		if (value != NULL) {
+			WStringBuffer buffer;
+			buffer.append('"');
+			if (!StringUtil::escapeW(buffer, value))
+				buffer.append(value);
+			buffer.append('"');
+			value = buffer.toString();
+		}
+		wchar_t *sectionW = ToWcharA(section);
+		BOOL r = ::WritePrivateProfileStringW(sectionW, name, value, filename);
+		free(sectionW);
+		return r != FALSE;
+	}
 	bool setBoolean(const char* name, bool value) {
 		return setString(name, value ? YES() : NO());
 	}

Modified: trunk/TTProxy/YCL/include/YCL/StringUtil.h
===================================================================
--- trunk/TTProxy/YCL/include/YCL/StringUtil.h	2021-10-14 14:52:13 UTC (rev 9470)
+++ trunk/TTProxy/YCL/include/YCL/StringUtil.h	2021-10-14 14:52:23 UTC (rev 9471)
@@ -11,12 +11,13 @@
 
 #include <YCL/String.h>
 #include <YCL/StringBuffer.h>
+#include <YCL/wStringBuffer.h>
 
 namespace yebisuya {
 
 class StringUtil {
 private:
-	static int hexadecimal(char c) {
+	static int hexadecimal(wchar_t c) {
 		if ('0' <= c && c <= '9') {
 			return c - '0';
 		}else if ('A' <= c && c <= 'F') {
@@ -27,9 +28,15 @@
 			return -1;
 		}
 	}
-	static int octet(char c) {
+	static int hexadecimal(char c) {
+		return hexadecimal((wchar_t)c);
+	}
+	static int octet(wchar_t c) {
 		return '0' <= c && c <= '7' ? c - '0' : -1;
 	}
+	static int octet(char c) {
+		return octet((wchar_t)c);
+	}
 	static const char* ESCAPE_CHARS() {
 		static const char string[] = "abfnrtv";
 		return string;
@@ -44,7 +51,7 @@
 			return NULL;
 		return escape(string, 0, string.length());
 	}
-	static String escape(String string, int offset, int length) {
+	static String escape(String string, int offset, size_t length) {
 		if (string == NULL)
 			return NULL;
 		StringBuffer buffer;
@@ -55,7 +62,7 @@
 			return false;
 		return escape(buffer, string, 0, string.length());
 	}
-	static bool escape(StringBuffer& buffer, String string, int offset, int length) {
+	static bool escape(StringBuffer& buffer, String string, size_t offset, size_t length) {
 		if (string == NULL)
 			return false;
 		const char* start = string;
@@ -64,7 +71,7 @@
 		const char* end = start + length;
 		while (p < end && *p != '\0') {
 			char ch = *p;
-			if ('\0' < ch && ch < ' ' || ch == '\'' || ch == '"' || ch == '?' || ch == '\\') {
+			if (('\0' < ch && ch < ' ') || ch == '\'' || ch == '"' || ch == '?' || ch == '\\') {
 				bool useOctet;
 				if (ch < ' ') {
 					useOctet = true;
@@ -105,6 +112,70 @@
 		return true;
 	}
 
+	static WString escapeW(WString string) {
+		if (string == NULL)
+			return NULL;
+		return escapeW(string, 0, string.length());
+	}
+	static WString escapeW(WString string, size_t offset, size_t length) {
+		if (string == NULL)
+			return NULL;
+		WStringBuffer buffer;
+		return escapeW(buffer, string, offset, length) ? buffer.toString() : string;
+	}
+	static bool escapeW(WStringBuffer& buffer, WString string) {
+		if (string == NULL)
+			return false;
+		return escapeW(buffer, string, 0, string.length());
+	}
+	static bool escapeW(WStringBuffer& buffer, WString string, size_t offset, size_t length) {
+		if (string == NULL)
+			return false;
+		const wchar_t* start = string;
+		start += offset;
+		const wchar_t* p = start;
+		const wchar_t* end = start + length;
+		while (p < end && *p != '\0') {
+			wchar_t ch = *p;
+			if (('\0' < ch && ch < ' ') || ch == '\'' || ch == '"' || ch == '?' || ch == '\\') {
+				bool useOctet;
+				if (ch < ' ') {
+					useOctet = true;
+					for (int index = 0; CONTROL_CHARS()[index] != '\0'; index++) {
+						if (ch == CONTROL_CHARS()[index]) {
+							ch = ESCAPE_CHARS()[index];
+							useOctet = false;
+							break;
+						}
+					}
+				}else{
+					useOctet = false;
+				}
+				if (p > start) {
+					buffer.append(start, p - start);
+				}
+				buffer.append('\\');
+				if (useOctet) {
+					int octet = 6;
+					while (octet >= 0) {
+						buffer.append((char) ('0' + ((ch >> octet) & 0x07)));
+						octet -= 3;
+					}
+				}else{
+					buffer.append(ch);
+				}
+				start = ++p;
+			}else{
+				p++;
+			}
+		}
+		if (start == (const wchar_t*) string) {
+			return false;
+		}
+		buffer.append(start);
+		return true;
+	}
+
 	static String unescape(String string) {
 		if (string == NULL)
 			return NULL;
@@ -198,6 +269,97 @@
 		buffer.append(start);
 		return true;
 	}
+
+	static WString unescapeW(WString string) {
+		if (string == NULL)
+			return NULL;
+		return unescapeW(string, 0, string.length());
+	}
+	static WString unescapeW(WString string, int offset, int length) {
+		if (string == NULL)
+			return NULL;
+		WStringBuffer buffer;
+		return unescapeW(buffer, string) ? buffer.toString() : string;
+	}
+	static bool unescapeW(WStringBuffer& buffer, WString string) {
+		if (string == NULL)
+			return false;
+		return unescapeW(buffer, string, 0, string.length());
+	}
+	static bool unescapeW(WStringBuffer& buffer, WString string, size_t offset, size_t length) {
+		if (string == NULL)
+			return false;
+		const wchar_t* start = string;
+		start += offset;
+		const wchar_t* p = start;
+		const wchar_t* end = start + length;
+		while (p < end && *p != '\0') {
+			if (*p == '\\') {
+				if (p > start) {
+					buffer.append(start, p - start);
+					start = p;
+				}
+				wchar_t ch = '\0';
+				switch (*++p) {
+				case '\'':
+				case '"':
+				case '\\':
+				case '?':
+					ch = *p++;
+					break;
+				case 'x':
+				case 'X':
+					{
+						int ch1 = hexadecimal(*++p);
+						if (ch1 != -1) {
+							int ch2 = hexadecimal(*++p);
+							if (ch2 != -1) {
+								p++;
+								ch = (char) (ch1 << 4 | ch2);
+							}else{
+								ch = (char) ch1;
+							}
+						}
+					}
+					break;
+				case '0': case '1': case '2': case '3':
+				case '4': case '5': case '6': case '7':
+					{
+						ch = octet(*p);
+						int d = octet(*++p);
+						if (d != -1) {
+							ch = (ch << 3 | d);
+							d = octet(*++p);
+							if (d != -1) {
+								ch = (ch << 3 | d);
+								p++;
+							}
+						}
+					}
+					break;
+				default:
+					for (int index = 0; ESCAPE_CHARS()[index] != '\0'; index++) {
+						if (*p == ESCAPE_CHARS()[index]) {
+							ch = CONTROL_CHARS()[index];
+							p++;
+							break;
+						}
+					}
+				}
+				if (ch != '\0') {
+					buffer.append(ch);
+					start = p;
+				}
+			}else{
+				p++;
+			}
+		}
+		if (start == (const wchar_t*) string) {
+			return false;
+		}
+		buffer.append(start);
+		return true;
+	}
 };
 
 }

Copied: trunk/TTProxy/YCL/include/YCL/WString.h (from rev 9470, trunk/TTProxy/YCL/include/YCL/wstring.h)
===================================================================
--- trunk/TTProxy/YCL/include/YCL/WString.h	                        (rev 0)
+++ trunk/TTProxy/YCL/include/YCL/WString.h	2021-10-14 14:52:23 UTC (rev 9471)
@@ -0,0 +1,686 @@
+/*
+ * Copyright (C) 2021- TeraTerm Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* String.h \x82\xF0\x8A\xEE\x82ɍ쐬 */
+
+#ifndef _YCL_WSTRING_H_
+#define _YCL_WSTRING_H_
+
+#pragma once
+
+#include <YCL/common.h>
+
+#include <string.h>
+#include <wchar.h>
+
+namespace yebisuya {
+
+// \x95\xB6\x8E\x9A\x97\xF1\x82̊Ǘ\x9D\x81E\x91\x80\x8D\xEC\x82\xF0\x8Ds\x82\xA4\x83N\x83\x89\x83X\x81B
+class WString {
+private:
+	// \x95\xB6\x8E\x9A\x97\xF1\x82\xF0\x8Ai\x94[\x82\xB7\x82\xE9\x83o\x83b\x83t\x83@\x81B
+	// \x95\xB6\x8E\x9A\x97\xF1\x82̑O\x82ɂ͎Q\x8FƃJ\x83E\x83\x93\x83^\x82\xF0\x8E\x9D\x82\xBF\x81A
+	// \x91\xE3\x93\xFC\x82\xE2\x94j\x8A\xFC\x82̍ۂɂ͂\xBB\x82\xB1\x82\xF0\x95ύX\x82\xB7\x82\xE9\x81B
+	const wchar_t* string;
+
+	// utilities
+	// \x95\xB6\x8E\x9A\x97\xF1\x82\xF0\x8Ai\x94[\x82\xB7\x82\xE9\x83o\x83b\x83t\x83@\x82\xF0\x8D쐬\x82\xB7\x82\xE9\x81B
+	// \x95\xB6\x8E\x9A\x97\xF1\x82ƎQ\x8FƃJ\x83E\x83\x93\x83^\x82̕\xAA\x82̗̈\xE6\x82\xF0\x8Am\x95ۂ\xB7\x82\xE9\x81B
+	// \x8EQ\x8FƃJ\x83E\x83\x93\x83^\x82\xCD0\x82ɂȂ\xC1\x82Ă\xA2\x82\xE9\x81B
+	// \x88\xF8\x90\x94:
+	//	length \x95\xB6\x8E\x9A\x97\xF1\x82̒\xB7\x82\xB3\x81B
+	// \x95Ԓl:
+	//	\x8D쐬\x82\xB5\x82\xBD\x83o\x83b\x83t\x83@\x82̕\xB6\x8E\x9A\x97񕔂̃A\x83h\x83\x8C\x83X\x81B
+	static wchar_t* createBuffer(size_t length) {
+		size_t* count = (size_t*) new unsigned char[sizeof (size_t) + sizeof (wchar_t) * (length + 1)];
+		*count = 0;
+		return (wchar_t*) (count + 1);
+	}
+	// \x95\xB6\x8E\x9A\x97\xF1\x82\xF0\x8Ai\x94[\x82\xB5\x82\xBD\x83o\x83b\x83t\x83@\x82\xF0\x8D쐬\x82\xB7\x82\xE9\x81B
+	// \x88\xF8\x90\x94:
+	//	source \x8Ai\x94[\x82\xB7\x82镶\x8E\x9A\x97\xF1\x81B
+	// \x95Ԓl:
+	//	\x8D쐬\x82\xB5\x82\xBD\x83o\x83b\x83t\x83@\x82̕\xB6\x8E\x9A\x97񕔂̃A\x83h\x83\x8C\x83X\x81B
+	static const wchar_t* create(const wchar_t* source) {
+		return source != NULL ? create(source, wcslen(source)) : NULL;
+	}
+	// \x95\xB6\x8E\x9A\x97\xF1\x82\xF0\x8Ai\x94[\x82\xB5\x82\xBD\x83o\x83b\x83t\x83@\x82\xF0\x8D쐬\x82\xB7\x82\xE9\x81B
+	// \x88\xF8\x90\x94:
+	//	source \x8Ai\x94[\x82\xB7\x82镶\x8E\x9A\x97\xF1\x81B
+	//	length \x95\xB6\x8E\x9A\x97\xF1\x82̒\xB7\x82\xB3\x81B
+	// \x95Ԓl:
+	//	\x8D쐬\x82\xB5\x82\xBD\x83o\x83b\x83t\x83@\x82̕\xB6\x8E\x9A\x97񕔂̃A\x83h\x83\x8C\x83X\x81B
+	static const wchar_t* create(const wchar_t* source, size_t length) {
+		if (source != NULL) {
+			wchar_t* buffer = createBuffer(length);
+			wmemcpy(buffer, source, length);
+			buffer[length] = '\0';
+			return buffer;
+		}
+		return NULL;
+	}
+	// \x93\xF1\x82‚̕\xB6\x8E\x9A\x97\xF1\x82\xF0\x98A\x8C\x8B\x82\xB5\x8Ai\x94[\x82\xB5\x82\xBD\x83o\x83b\x83t\x83@\x82\xF0\x8D쐬\x82\xB7\x82\xE9\x81B
+	// \x88\xF8\x90\x94:
+	//	str1 \x98A\x8C\x8B\x82\xB7\x82镶\x8E\x9A\x97\xF1(\x91O)\x81B
+	//	str2 \x98A\x8C\x8B\x82\xB7\x82镶\x8E\x9A\x97\xF1(\x8C\xE3)\x81B
+	// \x95Ԓl:
+	//	\x8D쐬\x82\xB5\x82\xBD\x83o\x83b\x83t\x83@\x82̕\xB6\x8E\x9A\x97񕔂̃A\x83h\x83\x8C\x83X\x81B
+	static const wchar_t* concat(const wchar_t* str1, const wchar_t* str2) {
+		size_t len1 = wcslen(str1);
+		size_t len2 = wcslen(str2);
+		wchar_t* buffer = createBuffer(len1 + len2);
+		wmemcpy(buffer, str1, len1);
+		wmemcpy(buffer + len1, str2, len2);
+		buffer[len1 + len2] = '\0';
+		return buffer;
+	}
+	// private methods
+	// \x8EQ\x8FƃJ\x83E\x83\x93\x83^\x82\xF0\x8C\xB8\x82炵\x81A0\x82ɂȂ\xC1\x82\xBD\x82\xE7\x83o\x83b\x83t\x83@\x82\xF0\x94j\x8A\xFC\x82\xB7\x82\xE9\x81B
+	void release() {
+		if (string != NULL) {
+			size_t* count = (size_t*) string - 1;
+			if (--*count == 0)
+				delete[] (unsigned char*) count;
+		}
+	}
+	// \x8EQ\x8FƃJ\x83E\x83\x93\x83^\x82𑝂₷\x81B
+	void add() {
+		if (string != NULL) {
+			size_t* count = (size_t*) string - 1;
+			++*count;
+		}
+	}
+	// \x95ʂ̃o\x83b\x83t\x83@\x82ƒu\x82\xAB\x8A\xB7\x82\xA6\x82\xE9\x81B
+	// \x8C\xB3\x82̃o\x83b\x83t\x83@\x82̎Q\x8FƃJ\x83E\x83\x93\x83^\x82\xF0\x8C\xB8\x82炵\x81A
+	// \x90V\x82\xB5\x82\xA2\x83o\x83b\x83t\x83@\x82̎Q\x8FƃJ\x83E\x83\x93\x83^\x82𑝂₷\x81B
+	// \x88\xF8\x90\x94:
+	//	source \x92u\x82\xAB\x8A\xB7\x82\xA6\x82\xE9\x90V\x82\xB5\x82\xA2\x83o\x83b\x83t\x83@\x81B
+	void set(const wchar_t* source) {
+		if (string != source) {
+			release();
+			string = source;
+			add();
+		}
+	}
+public:
+	// constructor
+	// \x83f\x83t\x83H\x83\x8B\x83g\x83R\x83\x93\x83X\x83g\x83\x89\x83N\x83^\x81B
+	// NULL\x82\xAA\x93\xFC\x82\xC1\x82Ă\xA2\x82\xE9\x82̂ŁA\x82\xB1\x82̂܂܂ŕ\xB6\x8E\x9A\x97񑀍삷\x82\xE9\x82ƃA\x83N\x83Z\x83X\x88ᔽ\x82ɂȂ\xE9\x82̂Œ\x8D\x88ӁB
+	WString():string(NULL) {
+	}
+	// \x8C\xB3\x82̕\xB6\x8E\x9A\x97\xF1\x82\xF0\x8Ew\x92肷\x82\xE9\x83R\x83\x93\x83X\x83g\x83\x89\x83N\x83^\x81B
+	// \x88\xF8\x90\x94:
+	//	source \x8C\xB3\x82̕\xB6\x8E\x9A\x97\xF1\x81B
+	WString(const wchar_t* source):string(NULL) {
+		set(create(source));
+	}
+	// \x8C\xB3\x82̕\xB6\x8E\x9A\x97\xF1\x82𒷂\xB3\x95t\x82\xAB\x82Ŏw\x92肷\x82\xE9\x83R\x83\x93\x83X\x83g\x83\x89\x83N\x83^\x81B
+	// \x88\xF8\x90\x94:
+	//	source \x8C\xB3\x82̕\xB6\x8E\x9A\x97\xF1\x81B
+	//	length \x95\xB6\x8E\x9A\x97\xF1\x82̒\xB7\x82\xB3\x81B
+	WString(const wchar_t* source, size_t length):string(NULL) {
+		set(create(source, length));
+	}
+	// \x83R\x83s\x81[\x83R\x83\x93\x83X\x83g\x83\x89\x83N\x83^\x81B
+	// \x88\xF8\x90\x94:
+	//	source \x8C\xB3\x82̕\xB6\x8E\x9A\x97\xF1\x81B
+	WString(const WString& source):string(NULL) {
+		set(source.string);
+	}
+	// \x93\xF1\x82‚̕\xB6\x8E\x9A\x97\xF1\x82\xF0\x98A\x8C\x8B\x82\xB7\x82\xE9\x83R\x83\x93\x83X\x83g\x83\x89\x83N\x83^\x81B
+	// \x88\xF8\x90\x94:
+	//	str1 \x91O\x82ɂȂ镶\x8E\x9A\x97\xF1\x81B
+	//	str2 \x8C\xE3\x82ɂȂ镶\x8E\x9A\x97\xF1\x81B
+	WString(const wchar_t* str1, const wchar_t* str2):string(NULL) {
+		set(concat(str1, str2));
+	}
+	// \x93\xF1\x82‚̕\xB6\x8E\x9A\x97\xF1\x82\xF0\x98A\x8C\x8B\x82\xB7\x82\xE9\x83R\x83\x93\x83X\x83g\x83\x89\x83N\x83^\x81B
+	// \x88\xF8\x90\x94:
+	//	str1 \x91O\x82ɂȂ镶\x8E\x9A\x97\xF1\x81B
+	//	str2 \x8C\xE3\x82ɂȂ镶\x8E\x9A\x97\xF1\x81B
+	WString(const WString& str1, const wchar_t* str2):string(NULL) {
+		set(*str2 != '\0' ? concat(str1.string, str2) : str1.string);
+	}
+	// destructor
+	// \x83f\x83X\x83g\x83\x89\x83N\x83^\x81B
+	// \x94h\x90\xB6\x82\xB7\x82邱\x82Ƃ͍l\x82\xA6\x82Ă\xA2\x82Ȃ\xA2\x82̂ʼn\xBC\x91z\x8A֐\x94\x82ɂ͂\xB5\x82Ȃ\xA2\x81B
+	~WString() {
+		release();
+	}
+	// public methods
+	// \x82\xB1\x82̕\xB6\x8E\x9A\x97\xF1\x82̌\xE3\x82Ɏw\x92\xE8\x82̕\xB6\x8E\x9A\x97\xF1\x82\xF0\x98A\x8C\x8B\x82\xB7\x82\xE9\x81B
+	// \x88\xF8\x90\x94:
+	//	source \x98A\x8C\x8B\x82\xB7\x82镶\x8E\x9A\x97\xF1\x81B
+	// \x95Ԓl:
+	//	\x98A\x8C\x8B\x82\xB3\x82ꂽ\x95\xB6\x8E\x9A\x97\xF1\x81B
+	WString concat(const wchar_t* source)const {
+		return WString(*this, source);
+	}
+	// \x95\xB6\x8E\x9A\x97\xF1\x82Ƃ̔\xE4\x8Ar\x82\xF0\x8Ds\x82\xA4\x81B
+	// NULL\x82Ƃ\xE0\x94\xE4\x8Ar\x82ł\xAB\x82\xE9\x81B
+	// \x88\xF8\x90\x94:
+	//	str \x94\xE4\x8Ar\x82\xB7\x82镶\x8E\x9A\x97\xF1\x81B
+	// \x95Ԓl:
+	//	\x93\x99\x82\xB5\x82\xAF\x82\xEA\x82\xCE0\x81Astr\x82̕\xFB\x82\xAA\x91傫\x82\xAF\x82\xEA\x82Ε\x89\x81A\x8F\xAC\x82\xB3\x82\xAF\x82\xEA\x82ΐ\xB3\x81B
+	int compareTo(const wchar_t* str)const {
+		if (str == NULL)
+			return string == NULL ? 0 : 1;
+		else if (string == NULL)
+			return -1;
+		return wcscmp(string, str);
+	}
+	// \x95\xB6\x8E\x9A\x97\xF1\x82Ƃ̔\xE4\x8Ar\x82\xF0\x91啶\x8E\x9A\x8F\xAC\x95\xB6\x8E\x9A\x82̋\xE6\x95ʂȂ\xB5\x82ōs\x82\xA4\x81B
+	// NULL\x82Ƃ\xE0\x94\xE4\x8Ar\x82ł\xAB\x82\xE9\x81B
+	// \x88\xF8\x90\x94:
+	//	str \x94\xE4\x8Ar\x82\xB7\x82镶\x8E\x9A\x97\xF1\x81B
+	// \x95Ԓl:
+	//	\x93\x99\x82\xB5\x82\xAF\x82\xEA\x82\xCE0\x81Astr\x82̕\xFB\x82\xAA\x91傫\x82\xAF\x82\xEA\x82Ε\x89\x81A\x8F\xAC\x82\xB3\x82\xAF\x82\xEA\x82ΐ\xB3\x81B
+	int compareToIgnoreCase(const wchar_t* str)const {
+		if (str == NULL)
+			return string == NULL ? 0 : 1;
+		else if (string == NULL)
+			return -1;
+		return _wcsicmp(string, str);
+	}
+	// \x95\xB6\x8E\x9A\x97\xF1\x82Ƃ̔\xE4\x8Ar\x82\xF0\x8Ds\x82\xA4\x81B
+	// NULL\x82Ƃ\xE0\x94\xE4\x8Ar\x82ł\xAB\x82\xE9\x81B
+	// \x88\xF8\x90\x94:
+	//	str \x94\xE4\x8Ar\x82\xB7\x82镶\x8E\x9A\x97\xF1\x81B
+	// \x95Ԓl:
+	//	\x93\x99\x82\xB5\x82\xAF\x82\xEA\x82ΐ^\x81B
+	bool equals(const wchar_t* str)const {
+		return compareTo(str) == 0;
+	}
+	// \x95\xB6\x8E\x9A\x97\xF1\x82Ƃ̔\xE4\x8Ar\x82\xF0\x91啶\x8E\x9A\x8F\xAC\x95\xB6\x8E\x9A\x82̋\xE6\x95ʂȂ\xB5\x82ōs\x82\xA4\x81B
+	// NULL\x82Ƃ\xE0\x94\xE4\x8Ar\x82ł\xAB\x82\xE9\x81B
+	// \x88\xF8\x90\x94:
+	//	str \x94\xE4\x8Ar\x82\xB7\x82镶\x8E\x9A\x97\xF1\x81B
+	// \x95Ԓl:
+	//	\x93\x99\x82\xB5\x82\xAF\x82\xEA\x82ΐ^\x81B
+	bool equalsIgnoreCase(const wchar_t* str)const {
+		return compareToIgnoreCase(str) == 0;
+	}
+	// \x8Ew\x92肳\x82ꂽ\x95\xB6\x8E\x9A\x97\xF1\x82Ŏn\x82܂\xC1\x82Ă\xA2\x82邩\x82ǂ\xA4\x82\xA9\x82𔻒肷\x82\xE9\x81B
+	// \x88\xF8\x90\x94:
+	//	str \x94\xE4\x8Ar\x82\xB7\x82镶\x8E\x9A\x97\xF1\x81B
+	// \x95Ԓl:
+	//	\x8Ew\x92肳\x82ꂽ\x95\xB6\x8E\x9A\x97\xF1\x82Ŏn\x82܂\xC1\x82Ă\xA2\x82\xEA\x82ΐ^\x81B
+	bool startsWith(const wchar_t* str)const {
+		return startsWith(str, 0);
+	}
+	// \x8Ew\x92\xE8\x82̈ʒu\x82\xA9\x82\xE7\x8Ew\x92肳\x82ꂽ\x95\xB6\x8E\x9A\x97\xF1\x82Ŏn\x82܂\xC1\x82Ă\xA2\x82邩\x82ǂ\xA4\x82\xA9\x82𔻒肷\x82\xE9\x81B
+	// \x88\xF8\x90\x94:
+	//	str \x94\xE4\x8Ar\x82\xB7\x82镶\x8E\x9A\x97\xF1\x81B
+	// \x95Ԓl:
+	//	\x8Ew\x92肳\x82ꂽ\x95\xB6\x8E\x9A\x97\xF1\x82Ŏn\x82܂\xC1\x82Ă\xA2\x82\xEA\x82ΐ^\x81B
+	bool startsWith(const wchar_t* str, int offset)const {
+		return wcsncmp(string, str, wcslen(str)) == 0;
+	}
+	// \x8Ew\x92肳\x82ꂽ\x95\xB6\x8E\x9A\x97\xF1\x82ŏI\x82\xED\x82\xC1\x82Ă\xA2\x82邩\x82ǂ\xA4\x82\xA9\x82𔻒肷\x82\xE9\x81B
+	// \x88\xF8\x90\x94:
+	//	str \x94\xE4\x8Ar\x82\xB7\x82镶\x8E\x9A\x97\xF1\x81B
+	// \x95Ԓl:
+	//	\x8Ew\x92肳\x82ꂽ\x95\xB6\x8E\x9A\x97\xF1\x82ŏI\x82\xED\x82\xC1\x82Ă\xA2\x82\xEA\x82ΐ^\x81B
+	//
+	bool endsWith(const wchar_t* str)const {
+		size_t str_length = wcslen(str);
+		size_t string_length = length();
+		if (string_length < str_length)
+			return false;
+		return wcscmp(string + string_length - str_length, str) == 0;
+	}
+	// \x8Ew\x92\xE8\x82̕\xB6\x8E\x9A\x82\xAA\x82ǂ̈ʒu\x82ɂ\xA0\x82邩\x82\xF0\x92T\x82\xB7\x81B
+	// \x88\xF8\x90\x94:
+	//	chr \x92T\x82\xB7\x95\xB6\x8E\x9A\x81B
+	// \x95Ԓl:
+	//	\x95\xB6\x8E\x9A\x82̌\xA9\x82‚\xA9\x82\xC1\x82\xBD\x83C\x83\x93\x83f\x83b\x83N\x83X\x81B\x8C\xA9\x82‚\xA9\x82\xE7\x82Ȃ\xAF\x82\xEA\x82\xCE-1\x81B
+	int indexOf(char chr)const {
+		return indexOf(chr, 0);
+	}
+	// \x8Ew\x92\xE8\x82̕\xB6\x8E\x9A\x82\xAA\x82ǂ̈ʒu\x82ɂ\xA0\x82邩\x82\xF0\x8Ew\x92\xE8\x82̈ʒu\x82\xA9\x82\xE7\x92T\x82\xB7\x81B
+	// \x88\xF8\x90\x94:
+	//	chr \x92T\x82\xB7\x95\xB6\x8E\x9A\x81B
+	//	from \x92T\x82\xB5\x8En\x82߂\xE9\x88ʒu\x81B
+	// \x95Ԓl:
+	//	\x95\xB6\x8E\x9A\x82̌\xA9\x82‚\xA9\x82\xC1\x82\xBD\x83C\x83\x93\x83f\x83b\x83N\x83X\x81B\x8C\xA9\x82‚\xA9\x82\xE7\x82Ȃ\xAF\x82\xEA\x82\xCE-1\x81B
+	int indexOf(wchar_t chr, size_t from)const {
+		if (from >= length())
+			return -1;
+		const wchar_t* found = wcschr(string + from, chr);
+		if (found == NULL)
+			return -1;
+		return found - string;
+	}
+	// \x8Ew\x92\xE8\x82̕\xB6\x8E\x9A\x97񂪂ǂ̈ʒu\x82ɂ\xA0\x82邩\x82\xF0\x92T\x82\xB7\x81B
+	// \x88\xF8\x90\x94:
+	//	str \x92T\x82\xB7\x95\xB6\x8E\x9A\x97\xF1\x81B
+	// \x95Ԓl:
+	//	\x95\xB6\x8E\x9A\x97\xF1\x82̌\xA9\x82‚\xA9\x82\xC1\x82\xBD\x83C\x83\x93\x83f\x83b\x83N\x83X\x81B\x8C\xA9\x82‚\xA9\x82\xE7\x82Ȃ\xAF\x82\xEA\x82\xCE-1\x81B
+	int indexOf(const wchar_t* str)const {
+		return indexOf(str, 0);
+	}
+	// \x8Ew\x92\xE8\x82̕\xB6\x8E\x9A\x97񂪂ǂ̈ʒu\x82ɂ\xA0\x82邩\x82\xF0\x8Ew\x92\xE8\x82̈ʒu\x82\xA9\x82\xE7\x92T\x82\xB7\x81B
+	// \x88\xF8\x90\x94:
+	//	str \x92T\x82\xB7\x95\xB6\x8E\x9A\x97\xF1\x81B
+	//	from \x92T\x82\xB5\x8En\x82߂\xE9\x88ʒu\x81B
+	// \x95Ԓl:
+	//	\x95\xB6\x8E\x9A\x97\xF1\x82̌\xA9\x82‚\xA9\x82\xC1\x82\xBD\x83C\x83\x93\x83f\x83b\x83N\x83X\x81B\x8C\xA9\x82‚\xA9\x82\xE7\x82Ȃ\xAF\x82\xEA\x82\xCE-1\x81B
+	//
+	int indexOf(const wchar_t* str, size_t from)const {
+		if (from >= length())
+			return -1;
+		const wchar_t* found = wcsstr(string + from, str);
+		if (found == NULL)
+			return -1;
+		return found - string;
+	}
+	// \x95\xB6\x8E\x9A\x97\xF1\x82̒\xB7\x82\xB3\x82\xF0\x95Ԃ\xB7\x81B
+	size_t length()const {
+		return wcslen(string);
+	}
+	// \x8Ew\x92\xE8\x82̕\xB6\x8E\x9A\x82\xAA\x8DŌ\xE3\x82Ɍ\xA9\x82‚\xA9\x82\xE9\x88ʒu\x82\xF0\x8E擾\x82\xB7\x82\xE9\x81B
+	// \x88\xF8\x90\x94:
+	//	chr \x92T\x82\xB7\x95\xB6\x8E\x9A\x81B
+	// \x95Ԓl:
+	//	\x95\xB6\x8E\x9A\x82̌\xA9\x82‚\xA9\x82\xC1\x82\xBD\x83C\x83\x93\x83f\x83b\x83N\x83X\x81B\x8C\xA9\x82‚\xA9\x82\xE7\x82Ȃ\xAF\x82\xEA\x82\xCE-1\x81B
+	int lastIndexOf(char chr)const {
+		return lastIndexOf(chr, (size_t) -1);
+	}
+	// \x8Ew\x92\xE8\x82̕\xB6\x8E\x9A\x82\xAA\x8Ew\x92\xE8\x82̈ʒu\x82\xE6\x82\xE8\x82\xE0\x91O\x82ōŌ\xE3\x82Ɍ\xA9\x82‚\xA9\x82\xE9\x88ʒu\x82\xF0\x8E擾\x82\xB7\x82\xE9\x81B
+	// \x88\xF8\x90\x94:
+	//	chr \x92T\x82\xB7\x95\xB6\x8E\x9A\x81B
+	//	from \x92T\x82\xB5\x8En\x82߂\xE9\x88ʒu\x81B
+	// \x95Ԓl:
+	//	\x95\xB6\x8E\x9A\x82̌\xA9\x82‚\xA9\x82\xC1\x82\xBD\x83C\x83\x93\x83f\x83b\x83N\x83X\x81B\x8C\xA9\x82‚\xA9\x82\xE7\x82Ȃ\xAF\x82\xEA\x82\xCE-1\x81B
+	int lastIndexOf(wchar_t chr, size_t from)const {
+		size_t len = length();
+		if (from > len - 1)
+			from = len - 1;
+		const wchar_t* s = string;
+		const wchar_t* end = string + from;
+		const wchar_t* found = NULL;
+		while (*s != '0' && s <= end) {
+			if (*s == chr)
+				found = s;
+			s++;
+		}
+		return found != NULL ? found - string : -1;
+	}
+	// \x8Ew\x92\xE8\x82̕\xB6\x8E\x9A\x97񂪍Ō\xE3\x82Ɍ\xA9\x82‚\xA9\x82\xE9\x88ʒu\x82\xF0\x8E擾\x82\xB7\x82\xE9\x81B
+	// \x88\xF8\x90\x94:
+	//	str \x92T\x82\xB7\x95\xB6\x8E\x9A\x97\xF1\x81B
+	// \x95Ԓl:
+	//	\x95\xB6\x8E\x9A\x97\xF1\x82̌\xA9\x82‚\xA9\x82\xC1\x82\xBD\x83C\x83\x93\x83f\x83b\x83N\x83X\x81B\x8C\xA9\x82‚\xA9\x82\xE7\x82Ȃ\xAF\x82\xEA\x82\xCE-1\x81B
+	int lastIndexOf(const wchar_t* str)const {
+		return lastIndexOf(str, (size_t) -1);
+	}
+	// \x8Ew\x92\xE8\x82̕\xB6\x8E\x9A\x97񂪎w\x92\xE8\x82̈ʒu\x82\xE6\x82\xE8\x82\xE0\x91O\x82ōŌ\xE3\x82Ɍ\xA9\x82‚\xA9\x82\xE9\x88ʒu\x82\xF0\x8E擾\x82\xB7\x82\xE9\x81B
+	// \x88\xF8\x90\x94:
+	//	str \x92T\x82\xB7\x95\xB6\x8E\x9A\x97\xF1\x81B
+	//	from \x92T\x82\xB5\x8En\x82߂\xE9\x88ʒu\x81B
+	// \x95Ԓl:
+	//	\x95\xB6\x8E\x9A\x97\xF1\x82̌\xA9\x82‚\xA9\x82\xC1\x82\xBD\x83C\x83\x93\x83f\x83b\x83N\x83X\x81B\x8C\xA9\x82‚\xA9\x82\xE7\x82Ȃ\xAF\x82\xEA\x82\xCE-1\x81B
+	int lastIndexOf(const wchar_t* str, size_t from)const {
+		size_t len = length();
+		size_t str_len = wcslen(str);
+		if (from > len - str_len)
+			from = len - str_len;
+		const wchar_t* s = string + from;
+		while (s >= string) {
+			if (wcsncmp(s, str, str_len) == 0)
+				return s - string;
+			s--;
+		}
+		return -1;
+	}
+	// \x95\xB6\x8E\x9A\x97\xF1\x82̈ꕔ\x82\xF0\x8E\xE6\x82\xE8\x8Fo\x82\xB7\x81B
+	// \x88\xF8\x90\x94:
+	//	start \x8E\xE6\x82\xE8\x8Fo\x82\xB7\x95\xB6\x8E\x9A\x97\xF1\x82̐擪\x82̈ʒu\x81B
+	// \x95Ԓl:
+	//	\x95\xB6\x8E\x9A\x97\xF1\x82̈ꕔ\x81B
+	WString substring(int start)const {
+		return WString(string + start);
+	}
+	// \x95\xB6\x8E\x9A\x97\xF1\x82̈ꕔ\x82\xF0\x8E\xE6\x82\xE8\x8Fo\x82\xB7\x81B
+	// \x88\xF8\x90\x94:
+	//	start \x8E\xE6\x82\xE8\x8Fo\x82\xB7\x95\xB6\x8E\x9A\x97\xF1\x82̐擪\x82̈ʒu\x81B
+	//	end \x8E\xE6\x82\xE8\x8Fo\x82\xB7\x95\xB6\x8E\x9A\x97\xF1\x82̌\xE3\x82̈ʒu\x81B
+	// \x95Ԓl:
+	//	\x95\xB6\x8E\x9A\x97\xF1\x82̈ꕔ\x81B
+	WString substring(int start, int end)const {
+		return WString(string + start, end - start);
+	}
+	// \x8Ew\x92\xE8\x82̈ʒu\x82ɂ\xA0\x82镶\x8E\x9A\x82\xF0\x8E\xE6\x82\xE8\x8Fo\x82\xB7\x81B
+	// \x88\xF8\x90\x94:
+	//	index \x8E\xE6\x82\xE8\x8Fo\x82\xB7\x95\xB6\x8E\x9A\x82̈ʒu\x81B
+	// \x95Ԓl:
+	//	\x8Ew\x92\xE8\x82̈ʒu\x82ɂ\xA0\x82镶\x8E\x9A\x81B
+	char charAt(size_t index)const {
+		return index < length() ? string[index] : '\0';
+	}
+	// \x8Ew\x92\xE8\x82̕\xB6\x8E\x9A\x82\xF0\x8Ew\x92\xE8\x82̕\xB6\x8E\x9A\x82ɒu\x82\xAB\x8A\xB7\x82\xA6\x82܂\xB7\x81B
+	// \x88\xF8\x90\x94:
+	//	oldChr \x8C\xB3\x82̕\xB6\x8E\x9A\x81B
+	//	newChr \x92u\x82\xAB\x8A\xB7\x82\xA6\x82镶\x8E\x9A\x81B
+	// \x95Ԓl:
+	//	\x92u\x8A\xB7\x8C\xE3\x82̕\xB6\x8E\x9A\x97\xF1\x81B
+	WString replace(char oldChr, char newChr)const {
+		WString result(string);
+		char* s = (char*) result.string;
+		while (*s != '\0'){
+			if (WString::isLeadByte(*s))
+				s++;
+			else if (*s == oldChr)
+				*s = newChr;
+			s++;
+		}
+		return result;
+	}
+	// \x95\xB6\x8E\x9A\x97񒆂̑啶\x8E\x9A\x82\xF0\x8F\xAC\x95\xB6\x8E\x9A\x82ɕϊ\xB7\x82\xB7\x82\xE9\x81B
+	// \x95Ԓl:
+	//	\x95ϊ\xB7\x8C\xE3\x82̕\xB6\x8E\x9A\x97\xF1\x81B
+	WString toLowerCase()const {
+		WString result(string);
+		char* s = (char*) result.string;
+		while (*s != '\0'){
+			if (WString::isLeadByte(*s))
+				s++;
+			else if ('A' <= *s && *s <= 'Z')
+				*s += 'a' - 'A';
+			s++;
+		}
+		return result;
+	}
+	// \x95\xB6\x8E\x9A\x97񒆂̏\xAC\x95\xB6\x8E\x9A\x82\xF0\x91啶\x8E\x9A\x82ɕϊ\xB7\x82\xB7\x82\xE9\x81B
+	// \x95Ԓl:
+	//	\x95ϊ\xB7\x8C\xE3\x82̕\xB6\x8E\x9A\x97\xF1\x81B
+	WString toUpperCase()const {
+		WString result(string);
+		char* s = (char*) result.string;
+		while (*s != '\0'){
+			if (WString::isLeadByte(*s))
+				s++;
+			else if ('a' <= *s && *s <= 'z')
+				*s += 'A' - 'a';
+			s++;
+		}
+		return result;
+	}
+	// \x95\xB6\x8E\x9A\x97\xF1\x82̑O\x8C\xE3\x82̋󔒕\xB6\x8E\x9A\x82\xF0\x8D폜\x82\xB7\x82\xE9\x81B
+	// \x95Ԓl:
+	//	\x8D폜\x8C\xE3\x82̕\xB6\x8E\x9A\x97\xF1\x81B
+	WString trim()const {
+		const wchar_t* s = string;
+		while (*s != '\0' && (unsigned char) *s <= ' ')
+			s++;
+		const wchar_t* start = s;
+		s = string + length();
+		while (s > start && (*s != '\0' && (unsigned char) *s <= ' '))
+			s--;
+		return WString(start, s - start);
+	}
+
+	// operators
+
+	// const char*\x82ւ̃L\x83\x83\x83X\x83g\x89\x89\x8EZ\x8Eq
+	// \x95Ԓl:
+	//	\x95\xB6\x8E\x9A\x97\xF1\x82ւ̃A\x83h\x83\x8C\x83X\x81B
+	operator const wchar_t*()const {
+		return string;
+	}
+	// char\x94z\x97\xF1\x82̂悤\x82Ɉ\xB5\x82\xA4\x82\xBD\x82߂\xCC[]\x89\x89\x8EZ\x8Eq\x81B
+	// \x88\xF8\x90\x94:
+	//	index \x8E擾\x82\xB7\x82镶\x8E\x9A\x82̃C\x83\x93\x83f\x83b\x83N\x83X\x81B
+	// \x95Ԓl:
+	//	\x8Ew\x92\xE8\x82̃C\x83\x93\x83f\x83b\x83N\x83X\x82ɂ\xA0\x82镶\x8E\x9A\x81B
+	char operator[](size_t index)const {
+		return charAt(index);
+	}
+	// \x95\xB6\x8E\x9A\x97\xF1\x82\xF0\x98A\x8C\x8B\x82\xB7\x82邽\x82߂\xCC+\x89\x89\x8EZ\x8Eq\x81B
+	// \x88\xF8\x90\x94:
+	//	source \x98A\x8C\x8B\x82\xB7\x82镶\x8E\x9A\x97\xF1\x81B
+	// \x95Ԓl:
+	//	\x98A\x8C\x8B\x82\xB5\x82\xBD\x95\xB6\x8E\x9A\x97\xF1\x81B
+	WString operator+(const wchar_t* source)const {
+		return WString(string, source);
+	}
+	// \x95\xB6\x8E\x9A\x97\xF1\x82\xF0\x98A\x8C\x8B\x82\xB7\x82邽\x82߂\xCC+\x89\x89\x8EZ\x8Eq\x81B
+	// \x88\xF8\x90\x94:
+	//	source \x98A\x8C\x8B\x82\xB7\x82镶\x8E\x9A\x97\xF1\x81B
+	// \x95Ԓl:
+	//	\x98A\x8C\x8B\x82\xB5\x82\xBD\x95\xB6\x8E\x9A\x97\xF1\x81B
+	WString operator+(const WString& source)const {
+		return *string != '\0' ? WString(string, source.string) : source;
+	}
+	// \x95\xB6\x8E\x9A\x97\xF1\x82\xF0\x98A\x8C\x8B\x82\xB7\x82邽\x82߂\xCC+\x89\x89\x8EZ\x8Eq\x81B
+	// \x88\xF8\x90\x94:
+	//	str1 \x98A\x8C\x8B\x82\xB7\x82镶\x8E\x9A\x97\xF1(\x91O)\x81B
+	//	str2 \x98A\x8C\x8B\x82\xB7\x82镶\x8E\x9A\x97\xF1(\x8C\xE3)\x81B
+	// \x95Ԓl:
+	//	\x98A\x8C\x8B\x82\xB5\x82\xBD\x95\xB6\x8E\x9A\x97\xF1\x81B
+	friend WString operator+(const wchar_t* str1, const WString& str2) {
+		return *str1 != '\0' ? WString(str1, str2.string) : str2;
+	}
+	// \x91\xE3\x93\xFC\x89\x89\x8EZ\x8Eq\x81B
+	// \x88\xF8\x90\x94:
+	//	source \x91\xE3\x93\xFC\x82\xB7\x82镶\x8E\x9A\x97\xF1\x81B
+	// \x95Ԓl:
+	//	\x91\xE3\x93\xFC\x8C\x8B\x89ʁB
+	WString& operator=(const wchar_t* source) {
+		set(create(source));
+		return *this;
+	}
+	// \x91\xE3\x93\xFC\x89\x89\x8EZ\x8Eq\x81B
+	// \x88\xF8\x90\x94:
+	//	source \x91\xE3\x93\xFC\x82\xB7\x82镶\x8E\x9A\x97\xF1\x81B
+	// \x95Ԓl:
+	//	\x91\xE3\x93\xFC\x8C\x8B\x89ʁB
+	WString& operator=(const WString& source) {
+		set(source.string);
+		return *this;
+	}
+	// \x98A\x8C\x8B\x82\xB5\x82\xBD\x8C\x8B\x89ʂ\xF0\x91\xE3\x93\xFC\x82\xB7\x82鉉\x8EZ\x8Eq\x81B
+	// \x88\xF8\x90\x94:
+	//	source \x98A\x8C\x8B\x82\xB7\x82镶\x8E\x9A\x97\xF1\x81B
+	// \x95Ԓl:
+	//	\x98A\x8C\x8B\x8C\x8B\x89ʁB
+	WString& operator+=(const wchar_t* source) {
+		if (*source != '\0')
+			set(concat(string, source));
+		return *this;
+	}
+	// \x94\xE4\x8Ar\x89\x89\x8EZ\x8Eq\x81B
+	// \x88\xF8\x90\x94:
+	//	str \x94\xE4\x8Ar\x91Ώۂ̕\xB6\x8E\x9A\x97\xF1\x81B
+	// \x95Ԓl:
+	//	str\x82̕\x{30AA4D9}\x82\xB5\x82\xAF\x82\xEA\x82ΐ^\x81B
+	bool operator==(const WString& str)const {
+		return compareTo(str.string) == 0;
+	}
+	// \x94\xE4\x8Ar\x89\x89\x8EZ\x8Eq\x81B
+	// \x88\xF8\x90\x94:
+	//	str \x94\xE4\x8Ar\x91Ώۂ̕\xB6\x8E\x9A\x97\xF1\x81B
+	// \x95Ԓl:
+	//	str\x82̕\x{30AA4D9}\x82\xB5\x82\xAF\x82\xEA\x82ΐ^\x81B
+	bool operator==(const wchar_t* str)const {
+		return compareTo(str) == 0;
+	}
+	// \x94\xE4\x8Ar\x89\x89\x8EZ\x8Eq\x81B
+	// \x88\xF8\x90\x94:
+	//	str1 \x94\xE4\x8Ar\x82\xB7\x82镶\x8E\x9A\x97\xF1\x81B
+	//	str2 \x94\xE4\x8Ar\x82\xB7\x82镶\x8E\x9A\x97\xF1\x81B
+	// \x95Ԓl:
+	//	str1\x82\xE6\x82\xE8str2\x82̕\x{30AA4D9}\x82\xB5\x82\xAF\x82\xEA\x82ΐ^\x81B
+	friend bool operator==(const wchar_t* str1, const WString& str2) {
+		return str2.compareTo(str1) == 0;
+	}
+	// \x94\xE4\x8Ar\x89\x89\x8EZ\x8Eq\x81B
+	// \x88\xF8\x90\x94:
+	//	str \x94\xE4\x8Ar\x91Ώۂ̕\xB6\x8E\x9A\x97\xF1\x81B
+	// \x95Ԓl:
+	//	str\x82̕\x{30AA4D9}\x82\xB5\x82\xAD\x82Ȃ\xAF\x82\xEA\x82ΐ^\x81B
+	bool operator!=(const WString& str)const {
+		return compareTo(str) != 0;
+	}
+	// \x94\xE4\x8Ar\x89\x89\x8EZ\x8Eq\x81B
+	// \x88\xF8\x90\x94:
+	//	str \x94\xE4\x8Ar\x91Ώۂ̕\xB6\x8E\x9A\x97\xF1\x81B
+	// \x95Ԓl:
+	//	str\x82̕\x{30AA4D9}\x82\xB5\x82\xAD\x82Ȃ\xAF\x82\xEA\x82ΐ^\x81B
+	bool operator!=(const wchar_t* str)const {
+		return compareTo(str) != 0;
+	}
+	// \x94\xE4\x8Ar\x89\x89\x8EZ\x8Eq\x81B
+	// \x88\xF8\x90\x94:
+	//	str1 \x94\xE4\x8Ar\x82\xB7\x82镶\x8E\x9A\x97\xF1\x81B
+	//	str2 \x94\xE4\x8Ar\x82\xB7\x82镶\x8E\x9A\x97\xF1\x81B
+	// \x95Ԓl:
+	//	str1\x82\xE6\x82\xE8str2\x82̕\x{30AA4D9}\x82\xB5\x82\xAD\x82Ȃ\xAF\x82\xEA\x82ΐ^\x81B
+	friend bool operator!=(const wchar_t* str1, const WString& str2) {
+		return str2.compareTo(str1) != 0;
+	}
+	// \x94\xE4\x8Ar\x89\x89\x8EZ\x8Eq\x81B
+	// \x88\xF8\x90\x94:
+	//	str \x94\xE4\x8Ar\x91Ώۂ̕\xB6\x8E\x9A\x97\xF1\x81B
+	// \x95Ԓl:
+	//	str\x82̕\xFB\x82\xAA\x91傫\x82\xAF\x82\xEA\x82ΐ^\x81B
+	bool operator<(const WString& str)const {
+		return compareTo(str) < 0;
+	}
+	// \x94\xE4\x8Ar\x89\x89\x8EZ\x8Eq\x81B
+	// \x88\xF8\x90\x94:
+	//	str \x94\xE4\x8Ar\x91Ώۂ̕\xB6\x8E\x9A\x97\xF1\x81B
+	// \x95Ԓl:
+	//	str\x82̕\xFB\x82\xAA\x91傫\x82\xAF\x82\xEA\x82ΐ^\x81B
+	bool operator<(const wchar_t* str)const {
+		return compareTo(str) < 0;
+	}
+	// \x94\xE4\x8Ar\x89\x89\x8EZ\x8Eq\x81B
+	// \x88\xF8\x90\x94:
+	//	str1 \x94\xE4\x8Ar\x82\xB7\x82镶\x8E\x9A\x97\xF1\x81B
+	//	str2 \x94\xE4\x8Ar\x82\xB7\x82镶\x8E\x9A\x97\xF1\x81B
+	// \x95Ԓl:
+	//	str1\x82\xE6\x82\xE8str2\x82̕\xFB\x82\xAA\x91傫\x82\xAF\x82\xEA\x82ΐ^\x81B
+	friend bool operator<(const wchar_t* str1, const WString& str2) {
+		return str2.compareTo(str1) > 0;
+	}
+	// \x94\xE4\x8Ar\x89\x89\x8EZ\x8Eq\x81B
+	// \x88\xF8\x90\x94:
+	//	str \x94\xE4\x8Ar\x91Ώۂ̕\xB6\x8E\x9A\x97\xF1\x81B
+	// \x95Ԓl:
+	//	str\x82̕\xFB\x82\xAA\x91傫\x82\xA2\x82\xA9\x93\x99\x82\xB5\x82\xAF\x82\xEA\x82ΐ^\x81B
+	bool operator<=(const WString& str)const {
+		return compareTo(str) <= 0;
+	}
+	// \x94\xE4\x8Ar\x89\x89\x8EZ\x8Eq\x81B
+	// \x88\xF8\x90\x94:
+	//	str \x94\xE4\x8Ar\x91Ώۂ̕\xB6\x8E\x9A\x97\xF1\x81B
+	// \x95Ԓl:
+	//	str\x82̕\xFB\x82\xAA\x91傫\x82\xA2\x82\xA9\x93\x99\x82\xB5\x82\xAF\x82\xEA\x82ΐ^\x81B
+	bool operator<=(const wchar_t* str)const {
+		return compareTo(str) <= 0;
+	}
+	// \x94\xE4\x8Ar\x89\x89\x8EZ\x8Eq\x81B
+	// \x88\xF8\x90\x94:
+	//	str1 \x94\xE4\x8Ar\x82\xB7\x82镶\x8E\x9A\x97\xF1\x81B
+	//	str2 \x94\xE4\x8Ar\x82\xB7\x82镶\x8E\x9A\x97\xF1\x81B
+	// \x95Ԓl:
+	//	str1\x82\xE6\x82\xE8str2\x82̕\xFB\x82\xAA\x91傫\x82\xA2\x82\xA9\x93\x99\x82\xB5\x82\xAF\x82\xEA\x82ΐ^\x81B
+	friend bool operator<=(const wchar_t* str1, const WString& str2) {
+		return str2.compareTo(str1) >= 0;
+	}
+	// \x94\xE4\x8Ar\x89\x89\x8EZ\x8Eq\x81B
+	// \x88\xF8\x90\x94:
+	//	str \x94\xE4\x8Ar\x91Ώۂ̕\xB6\x8E\x9A\x97\xF1\x81B
+	// \x95Ԓl:
+	//	str\x82̕\x{30AA3EC}\x82\xB3\x82\xAF\x82\xEA\x82ΐ^\x81B
+	bool operator>(const WString& str)const {
+		return compareTo(str) > 0;
+	}
+	// \x94\xE4\x8Ar\x89\x89\x8EZ\x8Eq\x81B
+	// \x88\xF8\x90\x94:
+	//	str \x94\xE4\x8Ar\x91Ώۂ̕\xB6\x8E\x9A\x97\xF1\x81B
+	// \x95Ԓl:
+	//	str\x82̕\x{30AA3EC}\x82\xB3\x82\xAF\x82\xEA\x82ΐ^\x81B
+	bool operator>(const wchar_t* str)const {
+		return compareTo(str) > 0;
+	}
+	// \x94\xE4\x8Ar\x89\x89\x8EZ\x8Eq\x81B
+	// \x88\xF8\x90\x94:
+	//	str1 \x94\xE4\x8Ar\x82\xB7\x82镶\x8E\x9A\x97\xF1\x81B
+	//	str2 \x94\xE4\x8Ar\x82\xB7\x82镶\x8E\x9A\x97\xF1\x81B
+	// \x95Ԓl:
+	//	str1\x82\xE6\x82\xE8str2\x82̕\x{30AA3EC}\x82\xB3\x82\xAF\x82\xEA\x82ΐ^\x81B
+	friend bool operator>(const wchar_t* str1, const WString& str2) {
+		return str2.compareTo(str1) < 0;
+	}
+	// \x94\xE4\x8Ar\x89\x89\x8EZ\x8Eq\x81B
+	// \x88\xF8\x90\x94:
+	//	str \x94\xE4\x8Ar\x91Ώۂ̕\xB6\x8E\x9A\x97\xF1\x81B
+	// \x95Ԓl:
+	//	str\x82̕\x{30AA3EC}\x82\xB3\x82\xA2\x82\xA9\x93\x99\x82\xB5\x82\xAF\x82\xEA\x82ΐ^\x81B
+	bool operator>=(const WString& str)const {
+		return compareTo(str) >= 0;
+	}
+	// \x94\xE4\x8Ar\x89\x89\x8EZ\x8Eq\x81B
+	// \x88\xF8\x90\x94:
+	//	str \x94\xE4\x8Ar\x91Ώۂ̕\xB6\x8E\x9A\x97\xF1\x81B
+	// \x95Ԓl:
+	//	str\x82̕\x{30AA3EC}\x82\xB3\x82\xA2\x82\xA9\x93\x99\x82\xB5\x82\xAF\x82\xEA\x82ΐ^\x81B
+	bool operator>=(const wchar_t* str)const {
+		return compareTo(str) >= 0;
+	}
+	// \x94\xE4\x8Ar\x89\x89\x8EZ\x8Eq\x81B
+	// \x88\xF8\x90\x94:
+	//	str1 \x94\xE4\x8Ar\x82\xB7\x82镶\x8E\x9A\x97\xF1\x81B
+	//	str2 \x94\xE4\x8Ar\x82\xB7\x82镶\x8E\x9A\x97\xF1\x81B
+	// \x95Ԓl:
+	//	str1\x82\xE6\x82\xE8str2\x82̕\x{30AA3EC}\x82\xB3\x82\xA2\x82\xA9\x93\x99\x82\xB5\x82\xAF\x82\xEA\x82ΐ^\x81B
+	friend bool operator>=(const wchar_t* str1, const WString& str2) {
+		return str2.compareTo(str1) <= 0;
+	}
+
+	// public utilities
+
+	// 2\x83o\x83C\x83g\x95\xB6\x8E\x9A\x82̍ŏ\x89\x82\xCC1\x83o\x83C\x83g\x82\xA9\x82ǂ\xA4\x82\xA9\x82𔻒肷\x82\xE9\x81B
+	// \x88\xF8\x90\x94:
+	//	\x94\xBB\x92肷\x82\xE9\x83o\x83C\x83g\x81B
+	// \x95Ԓl:
+	//	2\x83o\x83C\x83g\x95\xB6\x8E\x9A\x82̍ŏ\x89\x82\xCC1\x83o\x83C\x83g\x82ł\xA0\x82\xEA\x82ΐ^\x81B
+	static bool isLeadByte(char ch) {
+	#ifdef _INC_WINDOWS
+		return ::IsDBCSLeadByte(ch) != 0;
+	#else
+		return (ch & 0x80) != 0;
+	#endif
+	}
+};
+
+}
+
+#endif//_YCL_WSTRING_H_

Added: trunk/TTProxy/YCL/include/YCL/WStringBuffer.h
===================================================================
--- trunk/TTProxy/YCL/include/YCL/WStringBuffer.h	                        (rev 0)
+++ trunk/TTProxy/YCL/include/YCL/WStringBuffer.h	2021-10-14 14:52:23 UTC (rev 9471)
@@ -0,0 +1,397 @@
+/*
+ * Copyright (C) 2021- TeraTerm Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* StringBuffer.h \x82\xF0\x8A\xEE\x82ɍ쐬 */
+
+#ifndef _YCL_WSTRINGBUFFER_H_
+#define _YCL_WSTRINGBUFFER_H_
+
+#pragma once
+
+#include <YCL/common.h>
+
+#include <YCL/WString.h>
+
+#include <malloc.h>
+
+namespace yebisuya {
+
+// \x89•ϒ\xB7\x82̕\xB6\x8E\x9A\x97\xF1\x82\xF0\x88\xB5\x82\xA4\x82\xBD\x82߂̃N\x83\x89\x83X\x81B
+class WStringBuffer {
+private:
+	// \x95\xB6\x8E\x9A\x97\xF1\x82\xF0\x8Ai\x94[\x82\xB7\x82\xE9\x83o\x83b\x83t\x83@\x81B
+	wchar_t* buffer;
+	// \x8C\xBB\x8DݗL\x8C\xF8\x82ȕ\xB6\x8E\x9A\x97\xF1\x82̒\xB7\x82\xB3\x81B
+	size_t validLength;
+	// \x83o\x83b\x83t\x83@\x82̑傫\x82\xB3\x81B
+	size_t bufferSize;
+	enum {
+		// \x83o\x83b\x83t\x83@\x82\xF0\x8DL\x82\xB0\x82\xE9\x8DۂɎg\x97p\x82\xB7\x82\xE9\x83T\x83C\x83Y\x81B
+		INIT_CAPACITY = 16,
+	};
+	// \x83o\x83b\x83t\x83@\x82\xF0\x8F\x89\x8A\x{227B0B7}\x82\xE9\x81B
+	// \x88\xF8\x90\x94:
+	//	source	\x8F\x89\x8A\x{257639A}\x97\xF1\x81B
+	//	length	\x8F\x89\x8A\x{257639A}\x97\xF1\x82̒\xB7\x82\xB3\x81B
+	//	capacity	\x83o\x83b\x83t\x83@\x82̏\x89\x8A\xFA\x83T\x83C\x83Y\x81B
+	void init(const wchar_t* source, size_t length, size_t capacity) {
+		if ((capacity != 0 || length != 0) && capacity < length + INIT_CAPACITY)
+			capacity = length + INIT_CAPACITY;
+		validLength = length;
+		bufferSize = capacity;
+		if (bufferSize == 0) {
+			buffer = NULL;
+		}else{
+			buffer = new wchar_t[bufferSize];
+		}
+		if (source != NULL) {
+			memcpy(buffer, source, validLength);
+		}
+		memset(buffer + validLength, '\0', bufferSize - validLength);
+	}
+public:
+	// \x83f\x83t\x83H\x83\x8B\x83g\x83R\x83\x93\x83X\x83g\x83\x89\x83N\x83^\x81B
+	WStringBuffer() {
+		init(NULL, 0, 0);
+	}
+	// \x83o\x83b\x83t\x83@\x82̏\x89\x8A\xFA\x83T\x83C\x83Y\x82\xF0\x8Ew\x92肷\x82\xE9\x83R\x83\x93\x83X\x83g\x83\x89\x83N\x83^\x81B
+	// \x88\xF8\x90\x94:
+	//	capacity \x83o\x83b\x83t\x83@\x82̏\x89\x8A\xFA\x83T\x83C\x83Y\x81B
+	WStringBuffer(size_t capacity) {
+		init(NULL, 0, capacity);
+	}
+	// \x83o\x83b\x83t\x83@\x82̏\x89\x8A\x{257639A}\x97\xF1\x82\xF0\x8Ew\x92肷\x82\xE9\x83R\x83\x93\x83X\x83g\x83\x89\x83N\x83^\x81B
+	// \x88\xF8\x90\x94:
+	//	source	\x8F\x89\x8A\x{257639A}\x97\xF1\x81B
+	WStringBuffer(const wchar_t* source) {
+		init(source, wcslen(source), 0);
+	}
+	// \x83R\x83s\x81[\x83R\x83\x93\x83X\x83g\x83\x89\x83N\x83^\x81B
+	// \x88\xF8\x90\x94:
+	//	source	\x8F\x89\x8A\x{257639A}\x97\xF1\x81B
+	WStringBuffer(const WStringBuffer& source) {
+		init(source.buffer, source.validLength, source.bufferSize);
+	}
+	// \x83f\x83X\x83g\x83\x89\x83N\x83^\x81B
+	~WStringBuffer() {
+		delete[] buffer;
+	}
+
+	// \x8C\xBB\x8DݗL\x8C\xF8\x82ȕ\xB6\x8E\x9A\x97\xF1\x82̒\xB7\x82\xB3\x82\xF0\x8E擾\x82\xB7\x82\xE9\x81B
+	// \x95Ԓl:
+	//	\x97L\x8C\xF8\x82ȕ\xB6\x8E\x9A\x97\xF1\x82̒\xB7\x82\xB3\x81B
+	size_t length()const {
+		return validLength;
+	}
+	// \x83o\x83b\x83t\x83@\x82̃T\x83C\x83Y\x82\xF0\x8E擾\x82\xB7\x82\xE9\x81B
+	// \x95Ԓl:
+	//	\x83o\x83b\x83t\x83@\x82̃T\x83C\x83Y\x81B
+	size_t capacity()const {
+		return bufferSize;
+	}
+	// \x83o\x83b\x83t\x83@\x82̃T\x83C\x83Y\x82\xF0\x8Ew\x92\xE8\x82̒\xB7\x82\xB3\x82\xAA\x8E\xFB\x82܂\xE9\x82悤\x82ɒ\xB2\x90߂\xB7\x82\xE9\x81B
+	// \x88\xF8\x90\x94:
+	//	newLength	\x92\xB2\x90߂\xB7\x82钷\x82\xB3\x81B
+	void ensureCapacity(size_t newLength) {
+		if (bufferSize < newLength) {
+			wchar_t* oldBuffer = buffer;
+			init(oldBuffer, validLength, newLength + INIT_CAPACITY);
+			delete[] oldBuffer;
+		}
+	}
+	// \x97L\x8C\xF8\x82ȕ\xB6\x8E\x9A\x97񒷂\xF0\x95ύX\x82\xB7\x82\xE9\x81B
+	// \x88\xF8\x90\x94:
+	//	newLength	\x90V\x82\xB5\x82\xA2\x95\xB6\x8E\x9A\x97񒷁B
+	void setLength(size_t newLength) {
+		if (validLength < newLength)
+			ensureCapacity(newLength);
+		validLength = newLength;
+	}
+	// \x8Ew\x92\xE8\x82̈ʒu\x82̕\xB6\x8E\x9A\x82\xF0\x8E擾\x82\xB7\x82\xE9\x81B
+	// \x88\xF8\x90\x94:
+	//	index	\x95\xB6\x8E\x9A\x82̈ʒu\x81B
+	// \x95Ԓl:
+	//	\x8Ew\x92\xE8\x82̈ʒu\x82̕\xB6\x8E\x9A\x81B
+	char charAt(size_t index)const {
+		return index < validLength ? buffer[index] : '\0';
+	}
+	// \x8Ew\x92\xE8\x82̈ʒu\x82̕\xB6\x8E\x9A\x82\xF0\x8E擾\x82\xB7\x82\xE9\x81B
+	// \x88\xF8\x90\x94:
+	//	index	\x95\xB6\x8E\x9A\x82̈ʒu\x81B
+	// \x95Ԓl:
+	//	\x8Ew\x92\xE8\x82̈ʒu\x82̕\xB6\x8E\x9A\x82̎Q\x8FƁB
+	wchar_t& charAt(size_t index) {
+		if (index >= validLength) {
+			ensureCapacity(validLength + 1);
+			index = validLength++;
+		}
+		return buffer[index];
+	}
+	// \x8Ew\x92\xE8\x82̈ʒu\x82̕\xB6\x8E\x9A\x82\xF0\x95ύX\x82\xB7\x82\xE9\x81B
+	// \x88\xF8\x90\x94:
+	//	index	\x95ύX\x82\xB7\x82镶\x8E\x9A\x82̈ʒu\x81B
+	//	chr	\x95ύX\x82\xB7\x82镶\x8E\x9A\x81B
+	void setCharAt(int index, char chr) {
+		charAt(index) = chr;
+	}
+	// \x95\xB6\x8E\x9A\x82\xF0\x92lj\xC1\x82\xB7\x82\xE9\x81B
+	// \x88\xF8\x90\x94:
+	//	chr	\x92lj\xC1\x82\xB7\x82镶\x8E\x9A\x81B
+	// \x95Ԓl:
+	//	\x92lj\xC1\x8C\x8B\x89ʁB
+	WStringBuffer& append(wchar_t chr) {
+		charAt(validLength) = chr;
+		return *this;
+	}
+	// \x95\xB6\x8E\x9A\x97\xF1\x82\xF0\x92lj\xC1\x82\xB7\x82\xE9\x81B
+	// \x88\xF8\x90\x94:
+	//	source	\x92lj\xC1\x82\xB7\x82镶\x8E\x9A\x97\xF1\x81B
+	// \x95Ԓl:
+	//	\x92lj\xC1\x8C\x8B\x89ʁB
+	WStringBuffer& append(const wchar_t* source) {
+		return append(source, wcslen(source));
+	}
+	// \x95\xB6\x8E\x9A\x97\xF1\x82\xF0\x92lj\xC1\x82\xB7\x82\xE9\x81B
+	// \x88\xF8\x90\x94:
+	//	source	\x92lj\xC1\x82\xB7\x82镶\x8E\x9A\x97\xF1\x81B
+	//	length	\x92lj\xC1\x82\xB7\x82镶\x8E\x9A\x97\xF1\x82̒\xB7\x82\xB3\x81B
+	// \x95Ԓl:
+	//	\x92lj\xC1\x8C\x8B\x89ʁB
+	WStringBuffer& append(const wchar_t* source, size_t length) {
+		size_t oldLength = validLength;
+		ensureCapacity(validLength + length);
+		memcpy(buffer + oldLength, source, length);
+		validLength += length;
+		return *this;
+	}
+	// \x8Ew\x92\xE8\x82̈ʒu\x82̕\xB6\x8E\x9A\x82\xF0\x8D폜\x82\xB7\x82\xE9\x81B
+	// \x88\xF8\x90\x94:
+	//	start	\x8D폜\x82\xB7\x82\xE9\x88ʒu\x81B
+	// \x95Ԓl:
+	//	\x8D폜\x8C\x8B\x89ʁB
+	WStringBuffer& remove(size_t index) {
+		return remove(index, index + 1);
+	}
+	// \x8Ew\x92\xE8\x82̈ʒu\x82̕\xB6\x8E\x9A\x97\xF1\x82\xF0\x8D폜\x82\xB7\x82\xE9\x81B
+	// \x88\xF8\x90\x94:
+	//	start	\x8D폜\x82\xB7\x82\xE9\x90擪\x88ʒu\x81B
+	//	end	\x8D폜\x82\xB7\x82\xE9\x8FI\x82\xED\x82\xE8\x82̈ʒu\x81B
+	// \x95Ԓl:
+	//	\x8D폜\x8C\x8B\x89ʁB
+	WStringBuffer& remove(size_t start, size_t end) {
+		if (start < end) {
+			if (end < validLength){
+				memcpy(buffer + start, buffer + end, validLength - end);
+				validLength -= end - start;
+			}else{
+				validLength = start;
+			}
+		}
+		return *this;
+	}
+	// \x8Ew\x92\xE8\x82̈ʒu\x82̕\xB6\x8E\x9A\x97\xF1\x82\xF0\x92u\x8A\xB7\x82\xB7\x82\xE9\x81B
+	// \x88\xF8\x90\x94:
+	//	start	\x92u\x8A\xB7\x82\xB7\x82\xE9\x90擪\x88ʒu\x81B
+	//	end	\x92u\x8A\xB7\x82\xB7\x82\xE9\x8FI\x82\xED\x82\xE8\x82̈ʒu\x81B
+	//	source	\x92u\x8A\xB7\x82\xB7\x82镶\x8E\x9A\x97\xF1\x81B
+	// \x95Ԓl:
+	//	\x92u\x8A\xB7\x8C\x8B\x89ʁB
+	WStringBuffer& replace(size_t start, size_t end, const char* source) {
+		if (end > validLength)
+			end = validLength;
+		if (start < end) {
+			size_t length = strlen(source);
+			size_t oldLength = validLength;
+			ensureCapacity(validLength += length - (end - start));
+			memcpy(buffer + start + length, buffer + end, oldLength - end);
+			memcpy(buffer + start, source, length);
+		}
+		return *this;
+	}
+	// \x8Ew\x92\xE8\x82̈ʒu\x82̕\xB6\x8E\x9A\x97\xF1\x82\xF0\x8E擾\x82\xB7\x82\xE9\x81B
+	// \x88\xF8\x90\x94:
+	//	start	\x8E擾\x82\xB7\x82镶\x8E\x9A\x97\xF1\x82̐擪\x88ʒu\x81B
+	// \x95Ԓl:
+	//	\x8Ew\x92\xE8\x82̈ʒu\x82̕\xB6\x8E\x9A\x97\xF1\x81B
+	WString substring(size_t index)const {
+		return WString(buffer + index, validLength - index);
+	}
+	// \x8Ew\x92\xE8\x82̈ʒu\x82̕\xB6\x8E\x9A\x97\xF1\x82\xF0\x8E擾\x82\xB7\x82\xE9\x81B
+	// \x88\xF8\x90\x94:
+	//	start	\x8E擾\x82\xB7\x82镶\x8E\x9A\x97\xF1\x82̐擪\x88ʒu\x81B
+	//	end	\x8E擾\x82\xB7\x82镶\x8E\x9A\x97\xF1\x82̏I\x82\xED\x82\xE8\x82̈ʒu\x81B
+	// \x95Ԓl:
+	//	\x8Ew\x92\xE8\x82̈ʒu\x82̕\xB6\x8E\x9A\x97\xF1\x81B
+	WString substring(size_t start, size_t end)const {
+		if (end > validLength)
+			end = validLength;
+		return WString(buffer + start, end - start);
+	}
+	// \x8Ew\x92\xE8\x82̈ʒu\x82ɕ\xB6\x8E\x9A\x82\xF0\x91}\x93\xFC\x82\xB7\x82\xE9\x81B
+	// \x88\xF8\x90\x94:
+	//	index	\x91}\x93\xFC\x82\xB7\x82\xE9\x88ʒu\x81B
+	//	source	\x91}\x93\xFC\x82\xB7\x82镶\x8E\x9A\x81B
+	// \x95Ԓl:
+	//	\x91}\x93\xFC\x8C\x8B\x89ʁB
+	WStringBuffer& insert(size_t index, char chr) {
+		return insert(index, &chr, 1);
+	}
+	// \x8Ew\x92\xE8\x82̈ʒu\x82ɕ\xB6\x8E\x9A\x97\xF1\x82\xF0\x91}\x93\xFC\x82\xB7\x82\xE9\x81B
+	// \x88\xF8\x90\x94:
+	//	index	\x91}\x93\xFC\x82\xB7\x82\xE9\x88ʒu\x81B
+	//	source	\x91}\x93\xFC\x82\xB7\x82镶\x8E\x9A\x97\xF1\x81B
+	// \x95Ԓl:
+	//	\x91}\x93\xFC\x8C\x8B\x89ʁB
+	WStringBuffer& insert(size_t index, const char* source) {
+		return insert(index, source, strlen(source));
+	}
+	// \x8Ew\x92\xE8\x82̈ʒu\x82ɕ\xB6\x8E\x9A\x97\xF1\x82\xF0\x91}\x93\xFC\x82\xB7\x82\xE9\x81B
+	// \x88\xF8\x90\x94:
+	//	index	\x91}\x93\xFC\x82\xB7\x82\xE9\x88ʒu\x81B
+	//	source	\x91}\x93\xFC\x82\xB7\x82镶\x8E\x9A\x97\xF1\x81B
+	//	length	\x95\xB6\x8E\x9A\x97\xF1\x82̒\xB7\x82\xB3\x81B
+	// \x95Ԓl:
+	//	\x91}\x93\xFC\x8C\x8B\x89ʁB
+	WStringBuffer& insert(size_t index, const char* source, size_t length) {
+		if (index >= validLength)
+			index = validLength;
+		size_t oldLength = validLength;
+		ensureCapacity(validLength + length);
+		char* temp = (char*) alloca(oldLength - index);
+		memcpy(temp, buffer + index, oldLength - index);
+		memcpy(buffer + index, source, length);
+		memcpy(buffer + index + length, temp, oldLength - index);
+		validLength += length;
+		return *this;
+	}
+#if 0
+	// \x95\xB6\x8E\x9A\x97\xF1\x82𔽓]\x82\xB7\x82\xE9\x81B
+	// \x95Ԓl:
+	//	\x94\xBD\x93]\x8C\x8B\x89ʁB
+	WStringBuffer& reverse() {
+		char* temporary = (char*) alloca(sizeof (char) * validLength);
+		char* dst = temporary + validLength;
+		wchar_t* src = buffer;
+		while (temporary < dst) {
+			if (String::isLeadByte(*src)) {
+				char pre = *src++;
+				*--dst = *src++;
+				*--dst = pre;
+			}else{
+				*--dst = *src++;
+			}
+		}
+		memcpy(buffer, temporary, validLength);
+		return *this;
+	}
+#endif
+	// \x95\xB6\x8E\x9A\x97\xF1\x82\xF0\x8E擾\x82\xB7\x82\xE9\x81B
+	// \x95Ԓl:
+	//	\x8C\xBB\x8Dݐݒ肳\x82\xEA\x82Ă\xA2\x82镶\x8E\x9A\x97\xF1\x81B
+	WString toString()const {
+		return WString(buffer, validLength);
+	}
+
+	// \x88ꕶ\x8E\x9A\x82\xBE\x82\xAF\x82̕\xB6\x8E\x9A\x97\xF1\x82ɕύX\x82\xB7\x82\xE9\x81B
+	// \x88\xF8\x90\x94:
+	//	\x95ύX\x82\xB7\x82\xE9\x88ꕶ\x8E\x9A\x81B
+	// \x95Ԓl:
+	//	\x95ύX\x8C\x8B\x89ʁB
+	WStringBuffer& set(char chr) {
+		ensureCapacity(1);
+		buffer[0] = chr;
+		validLength = 1;
+		return *this;
+	}
+	// \x8Ew\x92\xE8\x82̕\xB6\x8E\x9A\x97\xF1\x82ɕύX\x82\xB7\x82\xE9\x81B
+	// \x88\xF8\x90\x94:
+	//	source	\x95ύX\x82\xB7\x82镶\x8E\x9A\x97\xF1\x81B
+	// \x95Ԓl:
+	//	\x95ύX\x8C\x8B\x89ʁB
+	WStringBuffer& set(const char* source) {
+		size_t length = strlen(source);
+		ensureCapacity(validLength = length);
+		memcpy(buffer, source, length);
+		return *this;
+	}
+
+	// char*\x82ɕϊ\xB7\x82\xB7\x82\xE9\x83L\x83\x83\x83X\x83g\x89\x89\x8EZ\x8Eq\x81B
+	// \x83o\x83b\x83t\x83@\x82̃A\x83h\x83\x8C\x83X\x82\xF0\x8E擾\x82\xB7\x82\xE9\x81B
+	// \x95Ԓl:
+	//	\x83o\x83b\x83t\x83@\x82̃A\x83h\x83\x8C\x83X\x81B
+	operator wchar_t*() {
+		return buffer;
+	}
+	// String\x82ɕϊ\xB7\x82\xB7\x82\xE9\x83L\x83\x83\x83X\x83g\x89\x89\x8EZ\x8Eq\x81B
+	// \x95\xB6\x8E\x9A\x97\xF1\x82\xF0\x8E擾\x82\xB7\x82\xE9\x81B
+	// \x95Ԓl:
+	//	\x8C\xBB\x8Dݐݒ肳\x82\xEA\x82Ă\xA2\x82镶\x8E\x9A\x97\xF1\x81B
+	operator WString()const {
+		return toString();
+	}
+	// \x91\xE3\x93\xFC\x89\x89\x8EZ\x8Eq\x81B
+	// \x88ꕶ\x8E\x9A\x82\xBE\x82\xAF\x82̕\xB6\x8E\x9A\x97\xF1\x82ɕύX\x82\xB7\x82\xE9\x81B
+	// \x88\xF8\x90\x94:
+	//	ch	\x95ύX\x82\xB7\x82\xE9\x88ꕶ\x8E\x9A\x81B
+	// \x95Ԓl:
+	//	\x91\xE3\x93\xFC\x8C\x8B\x89ʁB
+	WStringBuffer& operator=(char ch) {
+		return set(ch);
+	}
+	// \x91\xE3\x93\xFC\x89\x89\x8EZ\x8Eq\x81B
+	// \x8Ew\x92\xE8\x82̕\xB6\x8E\x9A\x97\xF1\x82ɕύX\x82\xB7\x82\xE9\x81B
+	// \x88\xF8\x90\x94:
+	//	source	\x95ύX\x82\xB7\x82镶\x8E\x9A\x97\xF1\x81B
+	// \x95Ԓl:
+	//	\x91\xE3\x93\xFC\x8C\x8B\x89ʁB
+	WStringBuffer& operator=(const char* source) {
+		return set(source);
+	}
+	// \x98A\x8C\x8B\x91\xE3\x93\xFC\x89\x89\x8EZ\x8Eq\x81B
+	// \x95\xB6\x8E\x9A\x82\xF0\x92lj\xC1\x82\xB7\x82\xE9\x81B
+	// \x88\xF8\x90\x94:
+	//	ch	\x92lj\xC1\x82\xB7\x82镶\x8E\x9A\x81B
+	// \x95Ԓl:
+	//	\x91\xE3\x93\xFC\x8C\x8B\x89ʁB
+	WStringBuffer& operator+=(char ch) {
+		return append(ch);
+	}
+	// \x98A\x8C\x8B\x91\xE3\x93\xFC\x89\x89\x8EZ\x8Eq\x81B
+	// \x95\xB6\x8E\x9A\x97\xF1\x82\xF0\x92lj\xC1\x82\xB7\x82\xE9\x81B
+	// \x88\xF8\x90\x94:
+	//	source	\x92lj\xC1\x82\xB7\x82镶\x8E\x9A\x97\xF1\x81B
+	// \x95Ԓl:
+	//	\x91\xE3\x93\xFC\x8C\x8B\x89ʁB
+	WStringBuffer& operator+=(const wchar_t* source) {
+		return append(source);
+	}
+};
+
+}
+
+#endif//_YCL_WSTRINGBUFFER_H_

Modified: trunk/TTProxy/YCL/include/YCL/Window.h
===================================================================
--- trunk/TTProxy/YCL/include/YCL/Window.h	2021-10-14 14:52:13 UTC (rev 9470)
+++ trunk/TTProxy/YCL/include/YCL/Window.h	2021-10-14 14:52:23 UTC (rev 9471)
@@ -10,6 +10,7 @@
 #include <YCL/common.h>
 
 #include <YCL/String.h>
+#include <YCL/WString.h>
 
 namespace yebisuya {
 
@@ -37,9 +38,15 @@
 	int GetWindowTextLength()const {
 		return ::GetWindowTextLength(window);
 	}
+	int GetWindowTextLengthW()const {
+		return ::GetWindowTextLengthW(window);
+	}
 	int GetWindowText(char* buffer, int size)const {
 		return ::GetWindowText(window, buffer, size);
 	}
+	int GetWindowTextW(wchar_t* buffer, int size)const {
+		return ::GetWindowTextW(window, buffer, size);
+	}
 	String GetWindowText()const {
 		int length = GetWindowTextLength();
 		char* buffer = (char*) alloca(length + 1);
@@ -46,9 +53,18 @@
 		GetWindowText(buffer, length + 1);
 		return buffer;
 	}
+	WString GetWindowTextW()const {
+		int length = GetWindowTextLengthW();
+		wchar_t* buffer = (wchar_t*) alloca(sizeof(wchar_t) * (length + 1));
+		GetWindowTextW(buffer, length + 1);
+		return buffer;
+	}
 	bool SetWindowText(const char* text) {
 		return ::SetWindowText(window, text) != FALSE;
 	}
+	bool SetWindowTextW(const wchar_t* text) {
+		return ::SetWindowTextW(window, text) != FALSE;
+	}
 	LRESULT SendMessage(UINT message, WPARAM wparam = 0, LPARAM lparam = 0)const {
 		return ::SendMessage(window, message, wparam, lparam);
 	}

Deleted: trunk/TTProxy/YCL/include/YCL/wstring.h
===================================================================
--- trunk/TTProxy/YCL/include/YCL/wstring.h	2021-10-14 14:52:13 UTC (rev 9470)
+++ trunk/TTProxy/YCL/include/YCL/wstring.h	2021-10-14 14:52:23 UTC (rev 9471)
@@ -1,684 +0,0 @@
-/*
- * Copyright (C) 2021- TeraTerm Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef _YCL_WSTRING_H_
-#define _YCL_WSTRING_H_
-
-#pragma once
-
-#include <YCL/common.h>
-
-#include <string.h>
-#include <wchar.h>
-
-namespace yebisuya {
-
-// \x95\xB6\x8E\x9A\x97\xF1\x82̊Ǘ\x9D\x81E\x91\x80\x8D\xEC\x82\xF0\x8Ds\x82\xA4\x83N\x83\x89\x83X\x81B
-class WString {
-private:
-	// \x95\xB6\x8E\x9A\x97\xF1\x82\xF0\x8Ai\x94[\x82\xB7\x82\xE9\x83o\x83b\x83t\x83@\x81B
-	// \x95\xB6\x8E\x9A\x97\xF1\x82̑O\x82ɂ͎Q\x8FƃJ\x83E\x83\x93\x83^\x82\xF0\x8E\x9D\x82\xBF\x81A
-	// \x91\xE3\x93\xFC\x82\xE2\x94j\x8A\xFC\x82̍ۂɂ͂\xBB\x82\xB1\x82\xF0\x95ύX\x82\xB7\x82\xE9\x81B
-	const wchar_t* string;
-
-	// utilities
-	// \x95\xB6\x8E\x9A\x97\xF1\x82\xF0\x8Ai\x94[\x82\xB7\x82\xE9\x83o\x83b\x83t\x83@\x82\xF0\x8D쐬\x82\xB7\x82\xE9\x81B
-	// \x95\xB6\x8E\x9A\x97\xF1\x82ƎQ\x8FƃJ\x83E\x83\x93\x83^\x82̕\xAA\x82̗̈\xE6\x82\xF0\x8Am\x95ۂ\xB7\x82\xE9\x81B
-	// \x8EQ\x8FƃJ\x83E\x83\x93\x83^\x82\xCD0\x82ɂȂ\xC1\x82Ă\xA2\x82\xE9\x81B
-	// \x88\xF8\x90\x94:
-	//	length \x95\xB6\x8E\x9A\x97\xF1\x82̒\xB7\x82\xB3\x81B
-	// \x95Ԓl:
-	//	\x8D쐬\x82\xB5\x82\xBD\x83o\x83b\x83t\x83@\x82̕\xB6\x8E\x9A\x97񕔂̃A\x83h\x83\x8C\x83X\x81B
-	static wchar_t* createBuffer(size_t length) {
-		size_t* count = (size_t*) new unsigned char[sizeof (size_t) + sizeof (wchar_t) * (length + 1)];
-		*count = 0;
-		return (wchar_t*) (count + 1);
-	}
-	// \x95\xB6\x8E\x9A\x97\xF1\x82\xF0\x8Ai\x94[\x82\xB5\x82\xBD\x83o\x83b\x83t\x83@\x82\xF0\x8D쐬\x82\xB7\x82\xE9\x81B
-	// \x88\xF8\x90\x94:
-	//	source \x8Ai\x94[\x82\xB7\x82镶\x8E\x9A\x97\xF1\x81B
-	// \x95Ԓl:
-	//	\x8D쐬\x82\xB5\x82\xBD\x83o\x83b\x83t\x83@\x82̕\xB6\x8E\x9A\x97񕔂̃A\x83h\x83\x8C\x83X\x81B
-	static const wchar_t* create(const wchar_t* source) {
-		return source != NULL ? create(source, wcslen(source)) : NULL;
-	}
-	// \x95\xB6\x8E\x9A\x97\xF1\x82\xF0\x8Ai\x94[\x82\xB5\x82\xBD\x83o\x83b\x83t\x83@\x82\xF0\x8D쐬\x82\xB7\x82\xE9\x81B
-	// \x88\xF8\x90\x94:
-	//	source \x8Ai\x94[\x82\xB7\x82镶\x8E\x9A\x97\xF1\x81B
-	//	length \x95\xB6\x8E\x9A\x97\xF1\x82̒\xB7\x82\xB3\x81B
-	// \x95Ԓl:
-	//	\x8D쐬\x82\xB5\x82\xBD\x83o\x83b\x83t\x83@\x82̕\xB6\x8E\x9A\x97񕔂̃A\x83h\x83\x8C\x83X\x81B
-	static const wchar_t* create(const wchar_t* source, size_t length) {
-		if (source != NULL) {
-			wchar_t* buffer = createBuffer(length);
-			wmemcpy(buffer, source, length);
-			buffer[length] = '\0';
-			return buffer;
-		}
-		return NULL;
-	}
-	// \x93\xF1\x82‚̕\xB6\x8E\x9A\x97\xF1\x82\xF0\x98A\x8C\x8B\x82\xB5\x8Ai\x94[\x82\xB5\x82\xBD\x83o\x83b\x83t\x83@\x82\xF0\x8D쐬\x82\xB7\x82\xE9\x81B
-	// \x88\xF8\x90\x94:
-	//	str1 \x98A\x8C\x8B\x82\xB7\x82镶\x8E\x9A\x97\xF1(\x91O)\x81B
-	//	str2 \x98A\x8C\x8B\x82\xB7\x82镶\x8E\x9A\x97\xF1(\x8C\xE3)\x81B
-	// \x95Ԓl:
-	//	\x8D쐬\x82\xB5\x82\xBD\x83o\x83b\x83t\x83@\x82̕\xB6\x8E\x9A\x97񕔂̃A\x83h\x83\x8C\x83X\x81B
-	static const wchar_t* concat(const wchar_t* str1, const wchar_t* str2) {
-		size_t len1 = wcslen(str1);
-		size_t len2 = wcslen(str2);
-		wchar_t* buffer = createBuffer(len1 + len2);
-		wmemcpy(buffer, str1, len1);
-		wmemcpy(buffer + len1, str2, len2);
-		buffer[len1 + len2] = '\0';
-		return buffer;
-	}
-	// private methods
-	// \x8EQ\x8FƃJ\x83E\x83\x93\x83^\x82\xF0\x8C\xB8\x82炵\x81A0\x82ɂȂ\xC1\x82\xBD\x82\xE7\x83o\x83b\x83t\x83@\x82\xF0\x94j\x8A\xFC\x82\xB7\x82\xE9\x81B
-	void release() {
-		if (string != NULL) {
-			size_t* count = (size_t*) string - 1;
-			if (--*count == 0)
-				delete[] (unsigned char*) count;
-		}
-	}
-	// \x8EQ\x8FƃJ\x83E\x83\x93\x83^\x82𑝂₷\x81B
-	void add() {
-		if (string != NULL) {
-			size_t* count = (size_t*) string - 1;
-			++*count;
-		}
-	}
-	// \x95ʂ̃o\x83b\x83t\x83@\x82ƒu\x82\xAB\x8A\xB7\x82\xA6\x82\xE9\x81B
-	// \x8C\xB3\x82̃o\x83b\x83t\x83@\x82̎Q\x8FƃJ\x83E\x83\x93\x83^\x82\xF0\x8C\xB8\x82炵\x81A
-	// \x90V\x82\xB5\x82\xA2\x83o\x83b\x83t\x83@\x82̎Q\x8FƃJ\x83E\x83\x93\x83^\x82𑝂₷\x81B
-	// \x88\xF8\x90\x94:
-	//	source \x92u\x82\xAB\x8A\xB7\x82\xA6\x82\xE9\x90V\x82\xB5\x82\xA2\x83o\x83b\x83t\x83@\x81B
-	void set(const wchar_t* source) {
-		if (string != source) {
-			release();
-			string = source;
-			add();
-		}
-	}
-public:
-	// constructor
-	// \x83f\x83t\x83H\x83\x8B\x83g\x83R\x83\x93\x83X\x83g\x83\x89\x83N\x83^\x81B
-	// NULL\x82\xAA\x93\xFC\x82\xC1\x82Ă\xA2\x82\xE9\x82̂ŁA\x82\xB1\x82̂܂܂ŕ\xB6\x8E\x9A\x97񑀍삷\x82\xE9\x82ƃA\x83N\x83Z\x83X\x88ᔽ\x82ɂȂ\xE9\x82̂Œ\x8D\x88ӁB
-	WString():string(NULL) {
-	}
-	// \x8C\xB3\x82̕\xB6\x8E\x9A\x97\xF1\x82\xF0\x8Ew\x92肷\x82\xE9\x83R\x83\x93\x83X\x83g\x83\x89\x83N\x83^\x81B
-	// \x88\xF8\x90\x94:
-	//	source \x8C\xB3\x82̕\xB6\x8E\x9A\x97\xF1\x81B
-	WString(const wchar_t* source):string(NULL) {
-		set(create(source));
-	}
-	// \x8C\xB3\x82̕\xB6\x8E\x9A\x97\xF1\x82𒷂\xB3\x95t\x82\xAB\x82Ŏw\x92肷\x82\xE9\x83R\x83\x93\x83X\x83g\x83\x89\x83N\x83^\x81B
-	// \x88\xF8\x90\x94:
-	//	source \x8C\xB3\x82̕\xB6\x8E\x9A\x97\xF1\x81B
-	//	length \x95\xB6\x8E\x9A\x97\xF1\x82̒\xB7\x82\xB3\x81B
-	WString(const wchar_t* source, size_t length):string(NULL) {
-		set(create(source, length));
-	}
-	// \x83R\x83s\x81[\x83R\x83\x93\x83X\x83g\x83\x89\x83N\x83^\x81B
-	// \x88\xF8\x90\x94:
-	//	source \x8C\xB3\x82̕\xB6\x8E\x9A\x97\xF1\x81B
-	WString(const WString& source):string(NULL) {
-		set(source.string);
-	}
-	// \x93\xF1\x82‚̕\xB6\x8E\x9A\x97\xF1\x82\xF0\x98A\x8C\x8B\x82\xB7\x82\xE9\x83R\x83\x93\x83X\x83g\x83\x89\x83N\x83^\x81B
-	// \x88\xF8\x90\x94:
-	//	str1 \x91O\x82ɂȂ镶\x8E\x9A\x97\xF1\x81B
-	//	str2 \x8C\xE3\x82ɂȂ镶\x8E\x9A\x97\xF1\x81B
-	WString(const wchar_t* str1, const wchar_t* str2):string(NULL) {
-		set(concat(str1, str2));
-	}
-	// \x93\xF1\x82‚̕\xB6\x8E\x9A\x97\xF1\x82\xF0\x98A\x8C\x8B\x82\xB7\x82\xE9\x83R\x83\x93\x83X\x83g\x83\x89\x83N\x83^\x81B
-	// \x88\xF8\x90\x94:
-	//	str1 \x91O\x82ɂȂ镶\x8E\x9A\x97\xF1\x81B
-	//	str2 \x8C\xE3\x82ɂȂ镶\x8E\x9A\x97\xF1\x81B
-	WString(const WString& str1, const wchar_t* str2):string(NULL) {
-		set(*str2 != '\0' ? concat(str1.string, str2) : str1.string);
-	}
-	// destructor
-	// \x83f\x83X\x83g\x83\x89\x83N\x83^\x81B
-	// \x94h\x90\xB6\x82\xB7\x82邱\x82Ƃ͍l\x82\xA6\x82Ă\xA2\x82Ȃ\xA2\x82̂ʼn\xBC\x91z\x8A֐\x94\x82ɂ͂\xB5\x82Ȃ\xA2\x81B
-	~WString() {
-		release();
-	}
-	// public methods
-	// \x82\xB1\x82̕\xB6\x8E\x9A\x97\xF1\x82̌\xE3\x82Ɏw\x92\xE8\x82̕\xB6\x8E\x9A\x97\xF1\x82\xF0\x98A\x8C\x8B\x82\xB7\x82\xE9\x81B
-	// \x88\xF8\x90\x94:
-	//	source \x98A\x8C\x8B\x82\xB7\x82镶\x8E\x9A\x97\xF1\x81B
-	// \x95Ԓl:
-	//	\x98A\x8C\x8B\x82\xB3\x82ꂽ\x95\xB6\x8E\x9A\x97\xF1\x81B
-	WString concat(const wchar_t* source)const {
-		return WString(*this, source);
-	}
-	// \x95\xB6\x8E\x9A\x97\xF1\x82Ƃ̔\xE4\x8Ar\x82\xF0\x8Ds\x82\xA4\x81B
-	// NULL\x82Ƃ\xE0\x94\xE4\x8Ar\x82ł\xAB\x82\xE9\x81B
-	// \x88\xF8\x90\x94:
-	//	str \x94\xE4\x8Ar\x82\xB7\x82镶\x8E\x9A\x97\xF1\x81B
-	// \x95Ԓl:
-	//	\x93\x99\x82\xB5\x82\xAF\x82\xEA\x82\xCE0\x81Astr\x82̕\xFB\x82\xAA\x91傫\x82\xAF\x82\xEA\x82Ε\x89\x81A\x8F\xAC\x82\xB3\x82\xAF\x82\xEA\x82ΐ\xB3\x81B
-	int compareTo(const wchar_t* str)const {
-		if (str == NULL)
-			return string == NULL ? 0 : 1;
-		else if (string == NULL)
-			return -1;
-		return wcscmp(string, str);
-	}
-	// \x95\xB6\x8E\x9A\x97\xF1\x82Ƃ̔\xE4\x8Ar\x82\xF0\x91啶\x8E\x9A\x8F\xAC\x95\xB6\x8E\x9A\x82̋\xE6\x95ʂȂ\xB5\x82ōs\x82\xA4\x81B
-	// NULL\x82Ƃ\xE0\x94\xE4\x8Ar\x82ł\xAB\x82\xE9\x81B
-	// \x88\xF8\x90\x94:
-	//	str \x94\xE4\x8Ar\x82\xB7\x82镶\x8E\x9A\x97\xF1\x81B
-	// \x95Ԓl:
-	//	\x93\x99\x82\xB5\x82\xAF\x82\xEA\x82\xCE0\x81Astr\x82̕\xFB\x82\xAA\x91傫\x82\xAF\x82\xEA\x82Ε\x89\x81A\x8F\xAC\x82\xB3\x82\xAF\x82\xEA\x82ΐ\xB3\x81B
-	int compareToIgnoreCase(const wchar_t* str)const {
-		if (str == NULL)
-			return string == NULL ? 0 : 1;
-		else if (string == NULL)
-			return -1;
-		return _wcsicmp(string, str);
-	}
-	// \x95\xB6\x8E\x9A\x97\xF1\x82Ƃ̔\xE4\x8Ar\x82\xF0\x8Ds\x82\xA4\x81B
-	// NULL\x82Ƃ\xE0\x94\xE4\x8Ar\x82ł\xAB\x82\xE9\x81B
-	// \x88\xF8\x90\x94:
-	//	str \x94\xE4\x8Ar\x82\xB7\x82镶\x8E\x9A\x97\xF1\x81B
-	// \x95Ԓl:
-	//	\x93\x99\x82\xB5\x82\xAF\x82\xEA\x82ΐ^\x81B
-	bool equals(const wchar_t* str)const {
-		return compareTo(str) == 0;
-	}
-	// \x95\xB6\x8E\x9A\x97\xF1\x82Ƃ̔\xE4\x8Ar\x82\xF0\x91啶\x8E\x9A\x8F\xAC\x95\xB6\x8E\x9A\x82̋\xE6\x95ʂȂ\xB5\x82ōs\x82\xA4\x81B
-	// NULL\x82Ƃ\xE0\x94\xE4\x8Ar\x82ł\xAB\x82\xE9\x81B
-	// \x88\xF8\x90\x94:
-	//	str \x94\xE4\x8Ar\x82\xB7\x82镶\x8E\x9A\x97\xF1\x81B
-	// \x95Ԓl:
-	//	\x93\x99\x82\xB5\x82\xAF\x82\xEA\x82ΐ^\x81B
-	bool equalsIgnoreCase(const wchar_t* str)const {
-		return compareToIgnoreCase(str) == 0;
-	}
-	// \x8Ew\x92肳\x82ꂽ\x95\xB6\x8E\x9A\x97\xF1\x82Ŏn\x82܂\xC1\x82Ă\xA2\x82邩\x82ǂ\xA4\x82\xA9\x82𔻒肷\x82\xE9\x81B
-	// \x88\xF8\x90\x94:
-	//	str \x94\xE4\x8Ar\x82\xB7\x82镶\x8E\x9A\x97\xF1\x81B
-	// \x95Ԓl:
-	//	\x8Ew\x92肳\x82ꂽ\x95\xB6\x8E\x9A\x97\xF1\x82Ŏn\x82܂\xC1\x82Ă\xA2\x82\xEA\x82ΐ^\x81B
-	bool startsWith(const wchar_t* str)const {
-		return startsWith(str, 0);
-	}
-	// \x8Ew\x92\xE8\x82̈ʒu\x82\xA9\x82\xE7\x8Ew\x92肳\x82ꂽ\x95\xB6\x8E\x9A\x97\xF1\x82Ŏn\x82܂\xC1\x82Ă\xA2\x82邩\x82ǂ\xA4\x82\xA9\x82𔻒肷\x82\xE9\x81B
-	// \x88\xF8\x90\x94:
-	//	str \x94\xE4\x8Ar\x82\xB7\x82镶\x8E\x9A\x97\xF1\x81B
-	// \x95Ԓl:
-	//	\x8Ew\x92肳\x82ꂽ\x95\xB6\x8E\x9A\x97\xF1\x82Ŏn\x82܂\xC1\x82Ă\xA2\x82\xEA\x82ΐ^\x81B
-	bool startsWith(const wchar_t* str, int offset)const {
-		return wcsncmp(string, str, wcslen(str)) == 0;
-	}
-	// \x8Ew\x92肳\x82ꂽ\x95\xB6\x8E\x9A\x97\xF1\x82ŏI\x82\xED\x82\xC1\x82Ă\xA2\x82邩\x82ǂ\xA4\x82\xA9\x82𔻒肷\x82\xE9\x81B
-	// \x88\xF8\x90\x94:
-	//	str \x94\xE4\x8Ar\x82\xB7\x82镶\x8E\x9A\x97\xF1\x81B
-	// \x95Ԓl:
-	//	\x8Ew\x92肳\x82ꂽ\x95\xB6\x8E\x9A\x97\xF1\x82ŏI\x82\xED\x82\xC1\x82Ă\xA2\x82\xEA\x82ΐ^\x81B
-	//
-	bool endsWith(const wchar_t* str)const {
-		size_t str_length = wcslen(str);
-		size_t string_length = length();
-		if (string_length < str_length)
-			return false;
-		return wcscmp(string + string_length - str_length, str) == 0;
-	}
-	// \x8Ew\x92\xE8\x82̕\xB6\x8E\x9A\x82\xAA\x82ǂ̈ʒu\x82ɂ\xA0\x82邩\x82\xF0\x92T\x82\xB7\x81B
-	// \x88\xF8\x90\x94:
-	//	chr \x92T\x82\xB7\x95\xB6\x8E\x9A\x81B
-	// \x95Ԓl:
-	//	\x95\xB6\x8E\x9A\x82̌\xA9\x82‚\xA9\x82\xC1\x82\xBD\x83C\x83\x93\x83f\x83b\x83N\x83X\x81B\x8C\xA9\x82‚\xA9\x82\xE7\x82Ȃ\xAF\x82\xEA\x82\xCE-1\x81B
-	int indexOf(char chr)const {
-		return indexOf(chr, 0);
-	}
-	// \x8Ew\x92\xE8\x82̕\xB6\x8E\x9A\x82\xAA\x82ǂ̈ʒu\x82ɂ\xA0\x82邩\x82\xF0\x8Ew\x92\xE8\x82̈ʒu\x82\xA9\x82\xE7\x92T\x82\xB7\x81B
-	// \x88\xF8\x90\x94:
-	//	chr \x92T\x82\xB7\x95\xB6\x8E\x9A\x81B
-	//	from \x92T\x82\xB5\x8En\x82߂\xE9\x88ʒu\x81B
-	// \x95Ԓl:
-	//	\x95\xB6\x8E\x9A\x82̌\xA9\x82‚\xA9\x82\xC1\x82\xBD\x83C\x83\x93\x83f\x83b\x83N\x83X\x81B\x8C\xA9\x82‚\xA9\x82\xE7\x82Ȃ\xAF\x82\xEA\x82\xCE-1\x81B
-	int indexOf(wchar_t chr, size_t from)const {
-		if (from >= length())
-			return -1;
-		const wchar_t* found = wcschr(string + from, chr);
-		if (found == NULL)
-			return -1;
-		return found - string;
-	}
-	// \x8Ew\x92\xE8\x82̕\xB6\x8E\x9A\x97񂪂ǂ̈ʒu\x82ɂ\xA0\x82邩\x82\xF0\x92T\x82\xB7\x81B
-	// \x88\xF8\x90\x94:
-	//	str \x92T\x82\xB7\x95\xB6\x8E\x9A\x97\xF1\x81B
-	// \x95Ԓl:
-	//	\x95\xB6\x8E\x9A\x97\xF1\x82̌\xA9\x82‚\xA9\x82\xC1\x82\xBD\x83C\x83\x93\x83f\x83b\x83N\x83X\x81B\x8C\xA9\x82‚\xA9\x82\xE7\x82Ȃ\xAF\x82\xEA\x82\xCE-1\x81B
-	int indexOf(const wchar_t* str)const {
-		return indexOf(str, 0);
-	}
-	// \x8Ew\x92\xE8\x82̕\xB6\x8E\x9A\x97񂪂ǂ̈ʒu\x82ɂ\xA0\x82邩\x82\xF0\x8Ew\x92\xE8\x82̈ʒu\x82\xA9\x82\xE7\x92T\x82\xB7\x81B
-	// \x88\xF8\x90\x94:
-	//	str \x92T\x82\xB7\x95\xB6\x8E\x9A\x97\xF1\x81B
-	//	from \x92T\x82\xB5\x8En\x82߂\xE9\x88ʒu\x81B
-	// \x95Ԓl:
-	//	\x95\xB6\x8E\x9A\x97\xF1\x82̌\xA9\x82‚\xA9\x82\xC1\x82\xBD\x83C\x83\x93\x83f\x83b\x83N\x83X\x81B\x8C\xA9\x82‚\xA9\x82\xE7\x82Ȃ\xAF\x82\xEA\x82\xCE-1\x81B
-	//
-	int indexOf(const wchar_t* str, size_t from)const {
-		if (from >= length())
-			return -1;
-		const wchar_t* found = wcsstr(string + from, str);
-		if (found == NULL)
-			return -1;
-		return found - string;
-	}
-	// \x95\xB6\x8E\x9A\x97\xF1\x82̒\xB7\x82\xB3\x82\xF0\x95Ԃ\xB7\x81B
-	size_t length()const {
-		return wcslen(string);
-	}
-	// \x8Ew\x92\xE8\x82̕\xB6\x8E\x9A\x82\xAA\x8DŌ\xE3\x82Ɍ\xA9\x82‚\xA9\x82\xE9\x88ʒu\x82\xF0\x8E擾\x82\xB7\x82\xE9\x81B
-	// \x88\xF8\x90\x94:
-	//	chr \x92T\x82\xB7\x95\xB6\x8E\x9A\x81B
-	// \x95Ԓl:
-	//	\x95\xB6\x8E\x9A\x82̌\xA9\x82‚\xA9\x82\xC1\x82\xBD\x83C\x83\x93\x83f\x83b\x83N\x83X\x81B\x8C\xA9\x82‚\xA9\x82\xE7\x82Ȃ\xAF\x82\xEA\x82\xCE-1\x81B
-	int lastIndexOf(char chr)const {
-		return lastIndexOf(chr, (size_t) -1);
-	}
-	// \x8Ew\x92\xE8\x82̕\xB6\x8E\x9A\x82\xAA\x8Ew\x92\xE8\x82̈ʒu\x82\xE6\x82\xE8\x82\xE0\x91O\x82ōŌ\xE3\x82Ɍ\xA9\x82‚\xA9\x82\xE9\x88ʒu\x82\xF0\x8E擾\x82\xB7\x82\xE9\x81B
-	// \x88\xF8\x90\x94:
-	//	chr \x92T\x82\xB7\x95\xB6\x8E\x9A\x81B
-	//	from \x92T\x82\xB5\x8En\x82߂\xE9\x88ʒu\x81B
-	// \x95Ԓl:
-	//	\x95\xB6\x8E\x9A\x82̌\xA9\x82‚\xA9\x82\xC1\x82\xBD\x83C\x83\x93\x83f\x83b\x83N\x83X\x81B\x8C\xA9\x82‚\xA9\x82\xE7\x82Ȃ\xAF\x82\xEA\x82\xCE-1\x81B
-	int lastIndexOf(wchar_t chr, size_t from)const {
-		size_t len = length();
-		if (from > len - 1)
-			from = len - 1;
-		const wchar_t* s = string;
-		const wchar_t* end = string + from;
-		const wchar_t* found = NULL;
-		while (*s != '0' && s <= end) {
-			if (*s == chr)
-				found = s;
-			s++;
-		}
-		return found != NULL ? found - string : -1;
-	}
-	// \x8Ew\x92\xE8\x82̕\xB6\x8E\x9A\x97񂪍Ō\xE3\x82Ɍ\xA9\x82‚\xA9\x82\xE9\x88ʒu\x82\xF0\x8E擾\x82\xB7\x82\xE9\x81B
-	// \x88\xF8\x90\x94:
-	//	str \x92T\x82\xB7\x95\xB6\x8E\x9A\x97\xF1\x81B
-	// \x95Ԓl:
-	//	\x95\xB6\x8E\x9A\x97\xF1\x82̌\xA9\x82‚\xA9\x82\xC1\x82\xBD\x83C\x83\x93\x83f\x83b\x83N\x83X\x81B\x8C\xA9\x82‚\xA9\x82\xE7\x82Ȃ\xAF\x82\xEA\x82\xCE-1\x81B
-	int lastIndexOf(const wchar_t* str)const {
-		return lastIndexOf(str, (size_t) -1);
-	}
-	// \x8Ew\x92\xE8\x82̕\xB6\x8E\x9A\x97񂪎w\x92\xE8\x82̈ʒu\x82\xE6\x82\xE8\x82\xE0\x91O\x82ōŌ\xE3\x82Ɍ\xA9\x82‚\xA9\x82\xE9\x88ʒu\x82\xF0\x8E擾\x82\xB7\x82\xE9\x81B
-	// \x88\xF8\x90\x94:
-	//	str \x92T\x82\xB7\x95\xB6\x8E\x9A\x97\xF1\x81B
-	//	from \x92T\x82\xB5\x8En\x82߂\xE9\x88ʒu\x81B
-	// \x95Ԓl:
-	//	\x95\xB6\x8E\x9A\x97\xF1\x82̌\xA9\x82‚\xA9\x82\xC1\x82\xBD\x83C\x83\x93\x83f\x83b\x83N\x83X\x81B\x8C\xA9\x82‚\xA9\x82\xE7\x82Ȃ\xAF\x82\xEA\x82\xCE-1\x81B
-	int lastIndexOf(const wchar_t* str, size_t from)const {
-		size_t len = length();
-		size_t str_len = wcslen(str);
-		if (from > len - str_len)
-			from = len - str_len;
-		const wchar_t* s = string + from;
-		while (s >= string) {
-			if (wcsncmp(s, str, str_len) == 0)
-				return s - string;
-			s--;
-		}
-		return -1;
-	}
-	// \x95\xB6\x8E\x9A\x97\xF1\x82̈ꕔ\x82\xF0\x8E\xE6\x82\xE8\x8Fo\x82\xB7\x81B
-	// \x88\xF8\x90\x94:
-	//	start \x8E\xE6\x82\xE8\x8Fo\x82\xB7\x95\xB6\x8E\x9A\x97\xF1\x82̐擪\x82̈ʒu\x81B
-	// \x95Ԓl:
-	//	\x95\xB6\x8E\x9A\x97\xF1\x82̈ꕔ\x81B
-	WString substring(int start)const {
-		return WString(string + start);
-	}
-	// \x95\xB6\x8E\x9A\x97\xF1\x82̈ꕔ\x82\xF0\x8E\xE6\x82\xE8\x8Fo\x82\xB7\x81B
-	// \x88\xF8\x90\x94:
-	//	start \x8E\xE6\x82\xE8\x8Fo\x82\xB7\x95\xB6\x8E\x9A\x97\xF1\x82̐擪\x82̈ʒu\x81B
-	//	end \x8E\xE6\x82\xE8\x8Fo\x82\xB7\x95\xB6\x8E\x9A\x97\xF1\x82̌\xE3\x82̈ʒu\x81B
-	// \x95Ԓl:
-	//	\x95\xB6\x8E\x9A\x97\xF1\x82̈ꕔ\x81B
-	WString substring(int start, int end)const {
-		return WString(string + start, end - start);
-	}
-	// \x8Ew\x92\xE8\x82̈ʒu\x82ɂ\xA0\x82镶\x8E\x9A\x82\xF0\x8E\xE6\x82\xE8\x8Fo\x82\xB7\x81B
-	// \x88\xF8\x90\x94:
-	//	index \x8E\xE6\x82\xE8\x8Fo\x82\xB7\x95\xB6\x8E\x9A\x82̈ʒu\x81B
-	// \x95Ԓl:
-	//	\x8Ew\x92\xE8\x82̈ʒu\x82ɂ\xA0\x82镶\x8E\x9A\x81B
-	char charAt(size_t index)const {
-		return index < length() ? string[index] : '\0';
-	}
-	// \x8Ew\x92\xE8\x82̕\xB6\x8E\x9A\x82\xF0\x8Ew\x92\xE8\x82̕\xB6\x8E\x9A\x82ɒu\x82\xAB\x8A\xB7\x82\xA6\x82܂\xB7\x81B
-	// \x88\xF8\x90\x94:
-	//	oldChr \x8C\xB3\x82̕\xB6\x8E\x9A\x81B
-	//	newChr \x92u\x82\xAB\x8A\xB7\x82\xA6\x82镶\x8E\x9A\x81B
-	// \x95Ԓl:
-	//	\x92u\x8A\xB7\x8C\xE3\x82̕\xB6\x8E\x9A\x97\xF1\x81B
-	WString replace(char oldChr, char newChr)const {
-		WString result(string);
-		char* s = (char*) result.string;
-		while (*s != '\0'){
-			if (WString::isLeadByte(*s))
-				s++;
-			else if (*s == oldChr)
-				*s = newChr;
-			s++;
-		}
-		return result;
-	}
-	// \x95\xB6\x8E\x9A\x97񒆂̑啶\x8E\x9A\x82\xF0\x8F\xAC\x95\xB6\x8E\x9A\x82ɕϊ\xB7\x82\xB7\x82\xE9\x81B
-	// \x95Ԓl:
-	//	\x95ϊ\xB7\x8C\xE3\x82̕\xB6\x8E\x9A\x97\xF1\x81B
-	WString toLowerCase()const {
-		WString result(string);
-		char* s = (char*) result.string;
-		while (*s != '\0'){
-			if (WString::isLeadByte(*s))
-				s++;
-			else if ('A' <= *s && *s <= 'Z')
-				*s += 'a' - 'A';
-			s++;
-		}
-		return result;
-	}
-	// \x95\xB6\x8E\x9A\x97񒆂̏\xAC\x95\xB6\x8E\x9A\x82\xF0\x91啶\x8E\x9A\x82ɕϊ\xB7\x82\xB7\x82\xE9\x81B
-	// \x95Ԓl:
-	//	\x95ϊ\xB7\x8C\xE3\x82̕\xB6\x8E\x9A\x97\xF1\x81B
-	WString toUpperCase()const {
-		WString result(string);
-		char* s = (char*) result.string;
-		while (*s != '\0'){
-			if (WString::isLeadByte(*s))
-				s++;
-			else if ('a' <= *s && *s <= 'z')
-				*s += 'A' - 'a';
-			s++;
-		}
-		return result;
-	}
-	// \x95\xB6\x8E\x9A\x97\xF1\x82̑O\x8C\xE3\x82̋󔒕\xB6\x8E\x9A\x82\xF0\x8D폜\x82\xB7\x82\xE9\x81B
-	// \x95Ԓl:
-	//	\x8D폜\x8C\xE3\x82̕\xB6\x8E\x9A\x97\xF1\x81B
-	WString trim()const {
-		const wchar_t* s = string;
-		while (*s != '\0' && (unsigned char) *s <= ' ')
-			s++;
-		const wchar_t* start = s;
-		s = string + length();
-		while (s > start && (*s != '\0' && (unsigned char) *s <= ' '))
-			s--;
-		return WString(start, s - start);
-	}
-
-	// operators
-
-	// const char*\x82ւ̃L\x83\x83\x83X\x83g\x89\x89\x8EZ\x8Eq
-	// \x95Ԓl:
-	//	\x95\xB6\x8E\x9A\x97\xF1\x82ւ̃A\x83h\x83\x8C\x83X\x81B
-	operator const wchar_t*()const {
-		return string;
-	}
-	// char\x94z\x97\xF1\x82̂悤\x82Ɉ\xB5\x82\xA4\x82\xBD\x82߂\xCC[]\x89\x89\x8EZ\x8Eq\x81B
-	// \x88\xF8\x90\x94:
-	//	index \x8E擾\x82\xB7\x82镶\x8E\x9A\x82̃C\x83\x93\x83f\x83b\x83N\x83X\x81B
-	// \x95Ԓl:
-	//	\x8Ew\x92\xE8\x82̃C\x83\x93\x83f\x83b\x83N\x83X\x82ɂ\xA0\x82镶\x8E\x9A\x81B
-	char operator[](size_t index)const {
-		return charAt(index);
-	}
-	// \x95\xB6\x8E\x9A\x97\xF1\x82\xF0\x98A\x8C\x8B\x82\xB7\x82邽\x82߂\xCC+\x89\x89\x8EZ\x8Eq\x81B
-	// \x88\xF8\x90\x94:
-	//	source \x98A\x8C\x8B\x82\xB7\x82镶\x8E\x9A\x97\xF1\x81B
-	// \x95Ԓl:
-	//	\x98A\x8C\x8B\x82\xB5\x82\xBD\x95\xB6\x8E\x9A\x97\xF1\x81B
-	WString operator+(const wchar_t* source)const {
-		return WString(string, source);
-	}
-	// \x95\xB6\x8E\x9A\x97\xF1\x82\xF0\x98A\x8C\x8B\x82\xB7\x82邽\x82߂\xCC+\x89\x89\x8EZ\x8Eq\x81B
-	// \x88\xF8\x90\x94:
-	//	source \x98A\x8C\x8B\x82\xB7\x82镶\x8E\x9A\x97\xF1\x81B
-	// \x95Ԓl:
-	//	\x98A\x8C\x8B\x82\xB5\x82\xBD\x95\xB6\x8E\x9A\x97\xF1\x81B
-	WString operator+(const WString& source)const {
-		return *string != '\0' ? WString(string, source.string) : source;
-	}
-	// \x95\xB6\x8E\x9A\x97\xF1\x82\xF0\x98A\x8C\x8B\x82\xB7\x82邽\x82߂\xCC+\x89\x89\x8EZ\x8Eq\x81B
-	// \x88\xF8\x90\x94:
-	//	str1 \x98A\x8C\x8B\x82\xB7\x82镶\x8E\x9A\x97\xF1(\x91O)\x81B
-	//	str2 \x98A\x8C\x8B\x82\xB7\x82镶\x8E\x9A\x97\xF1(\x8C\xE3)\x81B
-	// \x95Ԓl:
-	//	\x98A\x8C\x8B\x82\xB5\x82\xBD\x95\xB6\x8E\x9A\x97\xF1\x81B
-	friend WString operator+(const wchar_t* str1, const WString& str2) {
-		return *str1 != '\0' ? WString(str1, str2.string) : str2;
-	}
-	// \x91\xE3\x93\xFC\x89\x89\x8EZ\x8Eq\x81B
-	// \x88\xF8\x90\x94:
-	//	source \x91\xE3\x93\xFC\x82\xB7\x82镶\x8E\x9A\x97\xF1\x81B
-	// \x95Ԓl:
-	//	\x91\xE3\x93\xFC\x8C\x8B\x89ʁB
-	WString& operator=(const wchar_t* source) {
-		set(create(source));
-		return *this;
-	}
-	// \x91\xE3\x93\xFC\x89\x89\x8EZ\x8Eq\x81B
-	// \x88\xF8\x90\x94:
-	//	source \x91\xE3\x93\xFC\x82\xB7\x82镶\x8E\x9A\x97\xF1\x81B
-	// \x95Ԓl:
-	//	\x91\xE3\x93\xFC\x8C\x8B\x89ʁB
-	WString& operator=(const WString& source) {
-		set(source.string);
-		return *this;
-	}
-	// \x98A\x8C\x8B\x82\xB5\x82\xBD\x8C\x8B\x89ʂ\xF0\x91\xE3\x93\xFC\x82\xB7\x82鉉\x8EZ\x8Eq\x81B
-	// \x88\xF8\x90\x94:
-	//	source \x98A\x8C\x8B\x82\xB7\x82镶\x8E\x9A\x97\xF1\x81B
-	// \x95Ԓl:
-	//	\x98A\x8C\x8B\x8C\x8B\x89ʁB
-	WString& operator+=(const wchar_t* source) {
-		if (*source != '\0')
-			set(concat(string, source));
-		return *this;
-	}
-	// \x94\xE4\x8Ar\x89\x89\x8EZ\x8Eq\x81B
-	// \x88\xF8\x90\x94:
-	//	str \x94\xE4\x8Ar\x91Ώۂ̕\xB6\x8E\x9A\x97\xF1\x81B
-	// \x95Ԓl:
-	//	str\x82̕\x{30AA4D9}\x82\xB5\x82\xAF\x82\xEA\x82ΐ^\x81B
-	bool operator==(const WString& str)const {
-		return compareTo(str.string) == 0;
-	}
-	// \x94\xE4\x8Ar\x89\x89\x8EZ\x8Eq\x81B
-	// \x88\xF8\x90\x94:
-	//	str \x94\xE4\x8Ar\x91Ώۂ̕\xB6\x8E\x9A\x97\xF1\x81B
-	// \x95Ԓl:
-	//	str\x82̕\x{30AA4D9}\x82\xB5\x82\xAF\x82\xEA\x82ΐ^\x81B
-	bool operator==(const wchar_t* str)const {
-		return compareTo(str) == 0;
-	}
-	// \x94\xE4\x8Ar\x89\x89\x8EZ\x8Eq\x81B
-	// \x88\xF8\x90\x94:
-	//	str1 \x94\xE4\x8Ar\x82\xB7\x82镶\x8E\x9A\x97\xF1\x81B
-	//	str2 \x94\xE4\x8Ar\x82\xB7\x82镶\x8E\x9A\x97\xF1\x81B
-	// \x95Ԓl:
-	//	str1\x82\xE6\x82\xE8str2\x82̕\x{30AA4D9}\x82\xB5\x82\xAF\x82\xEA\x82ΐ^\x81B
-	friend bool operator==(const wchar_t* str1, const WString& str2) {
-		return str2.compareTo(str1) == 0;
-	}
-	// \x94\xE4\x8Ar\x89\x89\x8EZ\x8Eq\x81B
-	// \x88\xF8\x90\x94:
-	//	str \x94\xE4\x8Ar\x91Ώۂ̕\xB6\x8E\x9A\x97\xF1\x81B
-	// \x95Ԓl:
-	//	str\x82̕\x{30AA4D9}\x82\xB5\x82\xAD\x82Ȃ\xAF\x82\xEA\x82ΐ^\x81B
-	bool operator!=(const WString& str)const {
-		return compareTo(str) != 0;
-	}
-	// \x94\xE4\x8Ar\x89\x89\x8EZ\x8Eq\x81B
-	// \x88\xF8\x90\x94:
-	//	str \x94\xE4\x8Ar\x91Ώۂ̕\xB6\x8E\x9A\x97\xF1\x81B
-	// \x95Ԓl:
-	//	str\x82̕\x{30AA4D9}\x82\xB5\x82\xAD\x82Ȃ\xAF\x82\xEA\x82ΐ^\x81B
-	bool operator!=(const wchar_t* str)const {
-		return compareTo(str) != 0;
-	}
-	// \x94\xE4\x8Ar\x89\x89\x8EZ\x8Eq\x81B
-	// \x88\xF8\x90\x94:
-	//	str1 \x94\xE4\x8Ar\x82\xB7\x82镶\x8E\x9A\x97\xF1\x81B
-	//	str2 \x94\xE4\x8Ar\x82\xB7\x82镶\x8E\x9A\x97\xF1\x81B
-	// \x95Ԓl:
-	//	str1\x82\xE6\x82\xE8str2\x82̕\x{30AA4D9}\x82\xB5\x82\xAD\x82Ȃ\xAF\x82\xEA\x82ΐ^\x81B
-	friend bool operator!=(const wchar_t* str1, const WString& str2) {
-		return str2.compareTo(str1) != 0;
-	}
-	// \x94\xE4\x8Ar\x89\x89\x8EZ\x8Eq\x81B
-	// \x88\xF8\x90\x94:
-	//	str \x94\xE4\x8Ar\x91Ώۂ̕\xB6\x8E\x9A\x97\xF1\x81B
-	// \x95Ԓl:
-	//	str\x82̕\xFB\x82\xAA\x91傫\x82\xAF\x82\xEA\x82ΐ^\x81B
-	bool operator<(const WString& str)const {
-		return compareTo(str) < 0;
-	}
-	// \x94\xE4\x8Ar\x89\x89\x8EZ\x8Eq\x81B
-	// \x88\xF8\x90\x94:
-	//	str \x94\xE4\x8Ar\x91Ώۂ̕\xB6\x8E\x9A\x97\xF1\x81B
-	// \x95Ԓl:
-	//	str\x82̕\xFB\x82\xAA\x91傫\x82\xAF\x82\xEA\x82ΐ^\x81B
-	bool operator<(const wchar_t* str)const {
-		return compareTo(str) < 0;
-	}
-	// \x94\xE4\x8Ar\x89\x89\x8EZ\x8Eq\x81B
-	// \x88\xF8\x90\x94:
-	//	str1 \x94\xE4\x8Ar\x82\xB7\x82镶\x8E\x9A\x97\xF1\x81B
-	//	str2 \x94\xE4\x8Ar\x82\xB7\x82镶\x8E\x9A\x97\xF1\x81B
-	// \x95Ԓl:
-	//	str1\x82\xE6\x82\xE8str2\x82̕\xFB\x82\xAA\x91傫\x82\xAF\x82\xEA\x82ΐ^\x81B
-	friend bool operator<(const wchar_t* str1, const WString& str2) {
-		return str2.compareTo(str1) > 0;
-	}
-	// \x94\xE4\x8Ar\x89\x89\x8EZ\x8Eq\x81B
-	// \x88\xF8\x90\x94:
-	//	str \x94\xE4\x8Ar\x91Ώۂ̕\xB6\x8E\x9A\x97\xF1\x81B
-	// \x95Ԓl:
-	//	str\x82̕\xFB\x82\xAA\x91傫\x82\xA2\x82\xA9\x93\x99\x82\xB5\x82\xAF\x82\xEA\x82ΐ^\x81B
-	bool operator<=(const WString& str)const {
-		return compareTo(str) <= 0;
-	}
-	// \x94\xE4\x8Ar\x89\x89\x8EZ\x8Eq\x81B
-	// \x88\xF8\x90\x94:
-	//	str \x94\xE4\x8Ar\x91Ώۂ̕\xB6\x8E\x9A\x97\xF1\x81B
-	// \x95Ԓl:
-	//	str\x82̕\xFB\x82\xAA\x91傫\x82\xA2\x82\xA9\x93\x99\x82\xB5\x82\xAF\x82\xEA\x82ΐ^\x81B
-	bool operator<=(const wchar_t* str)const {
-		return compareTo(str) <= 0;
-	}
-	// \x94\xE4\x8Ar\x89\x89\x8EZ\x8Eq\x81B
-	// \x88\xF8\x90\x94:
-	//	str1 \x94\xE4\x8Ar\x82\xB7\x82镶\x8E\x9A\x97\xF1\x81B
-	//	str2 \x94\xE4\x8Ar\x82\xB7\x82镶\x8E\x9A\x97\xF1\x81B
-	// \x95Ԓl:
-	//	str1\x82\xE6\x82\xE8str2\x82̕\xFB\x82\xAA\x91傫\x82\xA2\x82\xA9\x93\x99\x82\xB5\x82\xAF\x82\xEA\x82ΐ^\x81B
-	friend bool operator<=(const wchar_t* str1, const WString& str2) {
-		return str2.compareTo(str1) >= 0;
-	}
-	// \x94\xE4\x8Ar\x89\x89\x8EZ\x8Eq\x81B
-	// \x88\xF8\x90\x94:
-	//	str \x94\xE4\x8Ar\x91Ώۂ̕\xB6\x8E\x9A\x97\xF1\x81B
-	// \x95Ԓl:
-	//	str\x82̕\x{30AA3EC}\x82\xB3\x82\xAF\x82\xEA\x82ΐ^\x81B
-	bool operator>(const WString& str)const {
-		return compareTo(str) > 0;
-	}
-	// \x94\xE4\x8Ar\x89\x89\x8EZ\x8Eq\x81B
-	// \x88\xF8\x90\x94:
-	//	str \x94\xE4\x8Ar\x91Ώۂ̕\xB6\x8E\x9A\x97\xF1\x81B
-	// \x95Ԓl:
-	//	str\x82̕\x{30AA3EC}\x82\xB3\x82\xAF\x82\xEA\x82ΐ^\x81B
-	bool operator>(const wchar_t* str)const {
-		return compareTo(str) > 0;
-	}
-	// \x94\xE4\x8Ar\x89\x89\x8EZ\x8Eq\x81B
-	// \x88\xF8\x90\x94:
-	//	str1 \x94\xE4\x8Ar\x82\xB7\x82镶\x8E\x9A\x97\xF1\x81B
-	//	str2 \x94\xE4\x8Ar\x82\xB7\x82镶\x8E\x9A\x97\xF1\x81B
-	// \x95Ԓl:
-	//	str1\x82\xE6\x82\xE8str2\x82̕\x{30AA3EC}\x82\xB3\x82\xAF\x82\xEA\x82ΐ^\x81B
-	friend bool operator>(const wchar_t* str1, const WString& str2) {
-		return str2.compareTo(str1) < 0;
-	}
-	// \x94\xE4\x8Ar\x89\x89\x8EZ\x8Eq\x81B
-	// \x88\xF8\x90\x94:
-	//	str \x94\xE4\x8Ar\x91Ώۂ̕\xB6\x8E\x9A\x97\xF1\x81B
-	// \x95Ԓl:
-	//	str\x82̕\x{30AA3EC}\x82\xB3\x82\xA2\x82\xA9\x93\x99\x82\xB5\x82\xAF\x82\xEA\x82ΐ^\x81B
-	bool operator>=(const WString& str)const {
-		return compareTo(str) >= 0;
-	}
-	// \x94\xE4\x8Ar\x89\x89\x8EZ\x8Eq\x81B
-	// \x88\xF8\x90\x94:
-	//	str \x94\xE4\x8Ar\x91Ώۂ̕\xB6\x8E\x9A\x97\xF1\x81B
-	// \x95Ԓl:
-	//	str\x82̕\x{30AA3EC}\x82\xB3\x82\xA2\x82\xA9\x93\x99\x82\xB5\x82\xAF\x82\xEA\x82ΐ^\x81B
-	bool operator>=(const wchar_t* str)const {
-		return compareTo(str) >= 0;
-	}
-	// \x94\xE4\x8Ar\x89\x89\x8EZ\x8Eq\x81B
-	// \x88\xF8\x90\x94:
-	//	str1 \x94\xE4\x8Ar\x82\xB7\x82镶\x8E\x9A\x97\xF1\x81B
-	//	str2 \x94\xE4\x8Ar\x82\xB7\x82镶\x8E\x9A\x97\xF1\x81B
-	// \x95Ԓl:
-	//	str1\x82\xE6\x82\xE8str2\x82̕\x{30AA3EC}\x82\xB3\x82\xA2\x82\xA9\x93\x99\x82\xB5\x82\xAF\x82\xEA\x82ΐ^\x81B
-	friend bool operator>=(const wchar_t* str1, const WString& str2) {
-		return str2.compareTo(str1) <= 0;
-	}
-
-	// public utilities
-
-	// 2\x83o\x83C\x83g\x95\xB6\x8E\x9A\x82̍ŏ\x89\x82\xCC1\x83o\x83C\x83g\x82\xA9\x82ǂ\xA4\x82\xA9\x82𔻒肷\x82\xE9\x81B
-	// \x88\xF8\x90\x94:
-	//	\x94\xBB\x92肷\x82\xE9\x83o\x83C\x83g\x81B
-	// \x95Ԓl:
-	//	2\x83o\x83C\x83g\x95\xB6\x8E\x9A\x82̍ŏ\x89\x82\xCC1\x83o\x83C\x83g\x82ł\xA0\x82\xEA\x82ΐ^\x81B
-	static bool isLeadByte(char ch) {
-	#ifdef _INC_WINDOWS
-		return ::IsDBCSLeadByte(ch) != 0;
-	#else
-		return (ch & 0x80) != 0;
-	#endif
-	}
-};
-
-}
-
-#endif//_YCL_WSTRING_H_

Modified: trunk/teraterm/common/ttlib.h
===================================================================
--- trunk/teraterm/common/ttlib.h	2021-10-14 14:52:13 UTC (rev 9470)
+++ trunk/teraterm/common/ttlib.h	2021-10-14 14:52:23 UTC (rev 9471)
@@ -189,6 +189,8 @@
 BOOL IsTextW(const wchar_t *str, size_t len);
 wchar_t *NormalizeLineBreakCR(const wchar_t *src, size_t *len);
 wchar_t *NormalizeLineBreakCRLF(const wchar_t *src_);
+BOOL IsRelativePathA(const char *path);
+BOOL IsRelativePathW(const wchar_t *path);
 
 #ifdef __cplusplus
 }

Modified: trunk/teraterm/common/ttlib_static_cpp.cpp
===================================================================
--- trunk/teraterm/common/ttlib_static_cpp.cpp	2021-10-14 14:52:13 UTC (rev 9470)
+++ trunk/teraterm/common/ttlib_static_cpp.cpp	2021-10-14 14:52:23 UTC (rev 9471)
@@ -1106,7 +1106,7 @@
 			PWSTR pPath;
 			hr = pItem->GetDisplayName(SIGDN_FILESYSPATH, &pPath);
 			if (SUCCEEDED(hr)) {
-				*folder = wcsdup(pPath);
+				*folder = _wcsdup(pPath);
 				CoTaskMemFree(pPath);
 				result = TRUE;
 			}
@@ -1246,3 +1246,23 @@
 	}
 	wcsncat_s(FName,destlen,Temp,_TRUNCATE);
 }
+
+/**
+ *	path\x82\xAA\x91\x8A\x91΃p\x83X\x82\xA9\x82ǂ\xA4\x82\xA9\x82\xF0\x95Ԃ\xB7
+ *		TODO "\path\path" \x82\xCD \x91\x8A\x91΃p\x83X\x82ł͂Ȃ\xA2\x82̂ł͂Ȃ\xA2\x82\xA9?
+ */
+BOOL IsRelativePathW(const wchar_t *path)
+{
+	if (path[0] == '\\' || path[0] == '/' || path[0] != '\0' && path[1] == ':') {
+		return FALSE;
+	}
+	return TRUE;
+}
+
+BOOL IsRelativePathA(const char *path)
+{
+	if (path[0] == '\\' || path[0] == '/' || path[0] != '\0' && path[1] == ':') {
+		return FALSE;
+	}
+	return TRUE;
+}


ttssh2-commit メーリングリストの案内
Back to archive index