[Ttssh2-commit] [7810] 内部バッファUnicode化テストブランチ

Back to archive index
scmno****@osdn***** scmno****@osdn*****
2019年 6月 25日 (火) 23:05:37 JST


Revision: 7810
          https://osdn.net/projects/ttssh2/scm/svn/commits/7810
Author:   zmatsuo
Date:     2019-06-25 23:05:37 +0900 (Tue, 25 Jun 2019)
Log Message:
-----------
内部バッファUnicode化テストブランチ

Modified Paths:
--------------
    branches/unicode_buf/teraterm/common/tipwin.cpp
    branches/unicode_buf/teraterm/common/tipwin.h
    branches/unicode_buf/teraterm/common/ttlib.c
    branches/unicode_buf/teraterm/common/ttlib.h
    branches/unicode_buf/teraterm/teraterm/CMakeLists.txt
    branches/unicode_buf/teraterm/teraterm/buffer.c
    branches/unicode_buf/teraterm/teraterm/buffer.h
    branches/unicode_buf/teraterm/teraterm/ttermpro.v10.vcxproj
    branches/unicode_buf/teraterm/teraterm/ttermpro.v11.vcxproj
    branches/unicode_buf/teraterm/teraterm/ttermpro.v12.vcxproj
    branches/unicode_buf/teraterm/teraterm/ttermpro.v14.vcxproj
    branches/unicode_buf/teraterm/teraterm/ttermpro.v15.vcxproj
    branches/unicode_buf/teraterm/teraterm/ttermpro.v16.vcxproj
    branches/unicode_buf/teraterm/teraterm/ttermpro.v9.vcproj
    branches/unicode_buf/teraterm/teraterm/ttermpro.vcproj
    branches/unicode_buf/teraterm/teraterm/vtdisp.c
    branches/unicode_buf/teraterm/teraterm/vtdisp.h
    branches/unicode_buf/teraterm/teraterm/vtterm.c
    branches/unicode_buf/teraterm/teraterm/vtwin.cpp
    branches/unicode_buf/teraterm/ttpcmn/ttcmn.c

Added Paths:
-----------
    branches/unicode_buf/teraterm/teraterm/unicode/
    branches/unicode_buf/teraterm/teraterm/unicode/get_combine_table.md
    branches/unicode_buf/teraterm/teraterm/unicode/get_combine_table.pl
    branches/unicode_buf/teraterm/teraterm/unicode/get_f_w_a.md
    branches/unicode_buf/teraterm/teraterm/unicode/get_f_w_a.pl
    branches/unicode_buf/teraterm/teraterm/unicode.cpp
    branches/unicode_buf/teraterm/teraterm/unicode.h
    branches/unicode_buf/teraterm/teraterm/unicode_asian_width.tbl
    branches/unicode_buf/teraterm/teraterm/unicode_combine.tbl
    branches/unicode_buf/teraterm/teraterm/unicode_test.h

-------------- next part --------------
Modified: branches/unicode_buf/teraterm/common/tipwin.cpp
===================================================================
--- branches/unicode_buf/teraterm/common/tipwin.cpp	2019-06-25 13:58:11 UTC (rev 7809)
+++ branches/unicode_buf/teraterm/common/tipwin.cpp	2019-06-25 14:05:37 UTC (rev 7810)
@@ -55,15 +55,24 @@
  */
 /* based on windows/sizetip.c from PuTTY 0.60 */
 
+#define UNICODE
+#define _UNICODE
+
 #include <windows.h>
 #include <stdio.h>
 #include <tchar.h>
 #include <assert.h>
+#include <crtdbg.h>
 
 #include "ttlib.h"		// for GetMessageboxFont()
 
 #include "tipwin.h"
 
+#if defined(_DEBUG) && !defined(_CRTDBG_MAP_ALLOC)
+#define malloc(l) _malloc_dbg((l), _NORMAL_BLOCK, __FILE__, __LINE__)
+#define free(p)   _free_dbg((p), _NORMAL_BLOCK)
+#endif
+
 #define	FRAME_WIDTH	6
 
 static ATOM tip_class = 0;
@@ -246,7 +255,7 @@
 	GetMessageboxFont(&logfont);
 	logfont.lfWidth = MulDiv(logfont.lfWidth, uDpi, 96);
 	logfont.lfHeight = MulDiv(logfont.lfHeight, uDpi, 96);
-	pTipWin->tip_font = CreateFontIndirect(&logfont);
+	pTipWin->tip_font = CreateFontIndirectA(&logfont);
 	CalcStrRect(pTipWin);
 	pTipWin->hParentWnd = src;
 	create_tipwin(pTipWin, hInst, cx, cy);
@@ -257,18 +266,30 @@
 	return pTipWin;
 }
 
-void TipWinSetPos(int x, int y)
+void TipWinSetTextW(TipWin *tWin, const wchar_t *text)
 {
+	if (tWin != NULL) {
+		HWND tip_wnd = tWin->tip_wnd;
+		SetWindowTextW(tip_wnd, text);
+	}
 }
 
-void TipWinSetText(TipWin *tWin, TCHAR *text)
+void TipWinSetTextA(TipWin *tWin, const char *text)
 {
 	if (tWin != NULL) {
 		HWND tip_wnd = tWin->tip_wnd;
-		SetWindowText(tip_wnd, text);
+		SetWindowTextA(tip_wnd, text);
 	}
 }
 
+void TipWinSetPos(TipWin *tWin, int x, int y)
+{
+	if (tWin != NULL) {
+		HWND tip_wnd = tWin->tip_wnd;
+		SetWindowPos(tip_wnd, 0, x, y, 0, 0, SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE);
+	}
+}
+
 void TipWinDestroy(TipWin *tWin)
 {
 	if (tWin != NULL) {

Modified: branches/unicode_buf/teraterm/common/tipwin.h
===================================================================
--- branches/unicode_buf/teraterm/common/tipwin.h	2019-06-25 13:58:11 UTC (rev 7809)
+++ branches/unicode_buf/teraterm/common/tipwin.h	2019-06-25 14:05:37 UTC (rev 7810)
@@ -1,3 +1,30 @@
+/*
+ * Copyright (C) 2018-2019 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.
+ */
 
 #include <windows.h>
 #include <tchar.h>
@@ -9,9 +36,18 @@
 typedef struct tagTipWinData TipWin;
 
 TipWin *TipWinCreate(HWND src, int cx, int cy, const TCHAR *str);
-void TipWinSetText(TipWin *tWin, TCHAR *text);
+void TipWinSetTextW(TipWin *tWin, const wchar_t *text);
+void TipWinSetTextA(TipWin *tWin, const char *text);
+void TipWinSetPos(TipWin *tWin, int x, int y);
 void TipWinDestroy(TipWin *tWin);
 
+#if defined(UNICODE)
+#define TipWinSetText(p1, p2)	TipWinSetTextW(p1, p2)
+#else
+#define TipWinSetText(p1, p2)	TipWinSetTextA(p1, p2)
+#endif
+
+
 #ifdef __cplusplus
 }
 #endif

Modified: branches/unicode_buf/teraterm/common/ttlib.c
===================================================================
--- branches/unicode_buf/teraterm/common/ttlib.c	2019-06-25 13:58:11 UTC (rev 7809)
+++ branches/unicode_buf/teraterm/common/ttlib.c	2019-06-25 14:05:37 UTC (rev 7810)
@@ -44,6 +44,8 @@
 #include "tttypes.h"
 #include "compat_win.h"
 
+#include "../teraterm/unicode_test.h"
+
 /* OS version with GetVersionEx(*1)
 
                 dwMajorVersion   dwMinorVersion    dwPlatformId
@@ -1086,7 +1088,7 @@
 	OutputDebugStringA(tmp);
 }
 
-#if defined(UNICODE)
+#if UNICODE_API // defined(UNICODE)
 void OutputDebugPrintfW(const wchar_t *fmt, ...)
 {
 	wchar_t tmp[1024];

Modified: branches/unicode_buf/teraterm/common/ttlib.h
===================================================================
--- branches/unicode_buf/teraterm/common/ttlib.h	2019-06-25 13:58:11 UTC (rev 7809)
+++ branches/unicode_buf/teraterm/common/ttlib.h	2019-06-25 14:05:37 UTC (rev 7810)
@@ -85,6 +85,7 @@
 int get_lang_font(PCHAR key, HWND dlg, PLOGFONT logfont, HFONT *font, const char *iniFile);
 DllExport BOOL doSelectFolder(HWND hWnd, char *path, int pathlen, const char *def, const char *msg);
 DllExport void OutputDebugPrintf(const char *fmt, ...);
+DllExport void OutputDebugPrintfW(const wchar_t *fmt, ...);
 DllExport DWORD get_OPENFILENAME_SIZEA();
 DllExport DWORD get_OPENFILENAME_SIZEW();
 DllExport BOOL IsWindows95();

Modified: branches/unicode_buf/teraterm/teraterm/CMakeLists.txt
===================================================================
--- branches/unicode_buf/teraterm/teraterm/CMakeLists.txt	2019-06-25 13:58:11 UTC (rev 7809)
+++ branches/unicode_buf/teraterm/teraterm/CMakeLists.txt	2019-06-25 14:05:37 UTC (rev 7810)
@@ -140,6 +140,11 @@
   #
   ${COMMON_SRC}
   ${TTDLG_SRC}
+  #
+  unicode.h
+  unicode.cpp
+  unicode_asian_width.tbl
+  unicode_combine.tbl
   )
 
 include_directories(

Modified: branches/unicode_buf/teraterm/teraterm/buffer.c
===================================================================
--- branches/unicode_buf/teraterm/teraterm/buffer.c	2019-06-25 13:58:11 UTC (rev 7809)
+++ branches/unicode_buf/teraterm/teraterm/buffer.c	2019-06-25 14:05:37 UTC (rev 7810)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 1994-1998 T. Teranishi
- * (C) 2004-2017 TeraTerm Project
+ * (C) 2004-2019 TeraTerm Project
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -28,11 +28,17 @@
  */
 
 /* TERATERM.EXE, scroll buffer routines */
+#undef UNICODE
+#undef _UNICODE
 
 #include "teraterm.h"
 #include "tttypes.h"
 #include <string.h>
 #include <stdio.h>
+#include <windows.h>
+#include <crtdbg.h>
+#include <mbstring.h>
+#include <assert.h>
 
 #include "ttwinman.h"
 #include "teraprn.h"
@@ -40,9 +46,38 @@
 #include "clipboar.h"
 #include "telnet.h"
 #include "ttplug.h" /* TTPLUG */
+#include "codeconv.h"
+#include "unicode.h"
 
 #include "buffer.h"
 
+#ifdef _DEBUG
+#define malloc(l)		_malloc_dbg((l), _NORMAL_BLOCK, __FILE__, __LINE__)
+#define	realloc(p, l)	_realloc_dbg((p), (l),  _NORMAL_BLOCK, __FILE__, __LINE__)
+#define free(p)			_free_dbg((p), _NORMAL_BLOCK)
+#endif
+
+#include "unicode_test.h"
+
+#if UNICODE_INTERNAL_BUFF
+
+typedef unsigned long char32_t;		// C++11
+
+// \x83o\x83b\x83t\x83@\x93\xE0\x82̔\xBC\x8Ap1\x95\xB6\x8E\x9A\x95\xAA\x82̏\xEE\x95\xF1
+typedef struct {
+	char32_t u32;
+	char32_t u32_last;
+	char WidthProperty;		// 'W' or 'H' or 'A'
+	char CombinationCharCount16;
+	char CombinationCharSize16;
+	char CombinationCharCount32;
+	char CombinationCharSize32;
+	wchar_t *pCombinationChars16;
+	char32_t *pCombinationChars32;
+	wchar_t	wc2[2];
+} buff_char_t;
+#endif
+
 // URL\x82\xF0\x8B\xAD\x92\xB2\x82\xB7\x82\xE9\x81i\x90΍莁\x83p\x83b\x83` 2005/4/2\x81j
 #define URL_EMPHASIS 1
 
@@ -80,6 +115,10 @@
 static PCHAR AttrLine2;
 static PCHAR AttrLineFG;
 static PCHAR AttrLineBG;
+#if UNICODE_INTERNAL_BUFF
+static buff_char_t *CodeBuffW;
+static buff_char_t *CodeLineW;
+#endif
 static LONG LinePtr;
 static LONG BufferSize;
 static int NumOfLinesInBuff;
@@ -94,10 +133,96 @@
 
 static TCharAttr CurCharAttr;
 
-HANDLE SaveBuff = NULL;
-int SaveBuffX;
-int SaveBuffY;
+static char *SaveBuff = NULL;
+static int SaveBuffX;
+static int SaveBuffY;
 
+#if UNICODE_INTERNAL_BUFF
+static void BuffSetChar(buff_char_t *buff, char32_t u32, char property)
+{
+	size_t wstr_len;
+	buff_char_t *p = buff;
+	if (p->pCombinationChars16 != NULL) {
+		free(p->pCombinationChars16);
+		p->pCombinationChars16 = NULL;
+	}
+	p->CombinationCharCount16 = 0;
+	p->CombinationCharSize16 = 0;
+	if (p->pCombinationChars32 != NULL) {
+		free(p->pCombinationChars32);
+		p->pCombinationChars32 = NULL;
+	}
+	p->CombinationCharCount32 = 0;
+	p->CombinationCharSize32 = 0;
+	p->WidthProperty = property;
+	p->u32 = u32;
+	p->u32_last = u32;
+	wstr_len = UTF32ToUTF16(u32, &p->wc2[0], 2);
+	switch (wstr_len) {
+	case 0:
+	default:
+		p->wc2[0] = 0;
+		p->wc2[1] = 0;
+		break;
+	case 1:
+		p->wc2[1] = 0;
+		break;
+	case 2:
+		break;
+	}
+}
+
+static void BuffAddChar(buff_char_t *buff, char32_t u32, char property)
+{
+	buff_char_t *p = buff;
+	assert(p->u32 != 0);
+	// \x8C\xE3\x82ɑ\xB1\x82\xAD\x95\xB6\x8E\x9A\x97̈\xE6\x82\xF0\x8Ag\x91傷\x82\xE9
+	if (p->CombinationCharSize16 < p->CombinationCharCount16 + 2) {
+		size_t new_size = p->CombinationCharSize16;
+		new_size = new_size == 0 ? 5 : new_size * 2;
+		p->pCombinationChars16 = realloc(p->pCombinationChars16, sizeof(wchar_t) * new_size);
+		p->CombinationCharSize16 = (char)new_size;
+	}
+	if (p->CombinationCharSize32 < p->CombinationCharCount32 + 2) {
+		size_t new_size = p->CombinationCharSize32;
+		new_size = new_size == 0 ? 5 : new_size * 2;
+		p->pCombinationChars32 = realloc(p->pCombinationChars32, sizeof(char32_t) * new_size);
+		p->CombinationCharSize32 = (char)new_size;
+	}
+
+	// UTF-32
+	p->u32_last = u32;
+	p->pCombinationChars32[p->CombinationCharCount32] = u32;
+	p->CombinationCharCount32++;
+
+	// UTF-16
+	{
+		wchar_t *u16 = &p->pCombinationChars16[p->CombinationCharCount16];
+		size_t wlen = UTF32ToUTF16(u32, u16, 2);
+		p->CombinationCharCount16 += (char)wlen;
+	}
+}
+
+static void memcpyW(buff_char_t *dest, const buff_char_t *src, size_t count)
+{
+	memcpy(dest, src, count * sizeof(buff_char_t));
+}
+
+static void memsetW(buff_char_t *dest, wchar_t ch, size_t count)
+{
+	size_t i;
+	for (i=0; i<count; i++) {
+		BuffSetChar(dest, ch, 'H');
+		dest++;
+	}
+}
+
+static void memmoveW(buff_char_t *dest, const buff_char_t *src, size_t count)
+{
+	memmove(dest, src, count * sizeof(buff_char_t));
+}
+#endif
+
 LONG GetLinePtr(int Line)
 {
 	LONG Ptr;
@@ -135,6 +260,10 @@
 	PCHAR CodeDest, AttrDest, AttrDest2, AttrDestFG, AttrDestBG;
 	LONG SrcPtr, DestPtr;
 	WORD LockOld;
+#if UNICODE_INTERNAL_BUFF
+	buff_char_t *CodeDestW;
+	buff_char_t *CodeWNew;
+#endif
 
 	if (Nx > BuffXMax) {
 		Nx = BuffXMax;
@@ -157,6 +286,9 @@
 	HAttr2New = NULL;
 	HAttrFGNew = NULL;
 	HAttrBGNew = NULL;
+#if UNICODE_INTERNAL_BUFF
+	CodeWNew = NULL;
+#endif
 
 	if ((HCodeNew=GlobalAlloc(GMEM_MOVEABLE, NewSize)) == NULL || (CodeDest=GlobalLock(HCodeNew)) == NULL) {
 		goto allocate_error;
@@ -173,8 +305,16 @@
 	if ((HAttrBGNew=GlobalAlloc(GMEM_MOVEABLE, NewSize)) == NULL || (AttrDestBG=GlobalLock(HAttrBGNew)) == NULL) {
 		goto allocate_error;
 	}
+#if UNICODE_INTERNAL_BUFF
+	CodeWNew = malloc(NewSize * sizeof(buff_char_t));
+	CodeDestW = CodeWNew;
+#endif
 
 	memset(&CodeDest[0], 0x20, NewSize);
+#if UNICODE_INTERNAL_BUFF
+	memset(&CodeDestW[0], 0, NewSize * sizeof(buff_char_t));
+	memsetW(&CodeDestW[0], 0x20, NewSize);
+#endif
 	memset(&AttrDest[0], AttrDefault, NewSize);
 	memset(&AttrDest2[0], AttrDefault, NewSize);
 	memset(&AttrDestFG[0], AttrDefaultFG, NewSize);
@@ -199,6 +339,9 @@
 		DestPtr = 0;
 		for (i = 1 ; i <= NyCopy ; i++) {
 			memcpy(&CodeDest[DestPtr],&CodeBuff[SrcPtr],NxCopy);
+#if UNICODE_INTERNAL_BUFF
+			memcpyW(&CodeDestW[DestPtr],&CodeBuffW[SrcPtr],NxCopy);
+#endif
 			memcpy(&AttrDest[DestPtr],&AttrBuff[SrcPtr],NxCopy);
 			memcpy(&AttrDest2[DestPtr],&AttrBuff2[SrcPtr],NxCopy);
 			memcpy(&AttrDestFG[DestPtr],&AttrBuffFG[SrcPtr],NxCopy);
@@ -240,6 +383,9 @@
 	HAttrBuff2 = HAttr2New;
 	HAttrBuffFG = HAttrFGNew;
 	HAttrBuffBG = HAttrBGNew;
+#if UNICODE_INTERNAL_BUFF
+	CodeBuffW = CodeWNew;
+#endif
 	BufferSize = NewSize;
 	NumOfLinesInBuff = Ny;
 	BuffStartAbs = 0;
@@ -262,6 +408,9 @@
 		AttrBuffFG = (PCHAR)GlobalLock(HAttrBuffFG);
 		AttrBuffBG = (PCHAR)GlobalLock(HAttrBuffBG);
 		CodeLine = CodeBuff;
+#if UNICODE_INTERNAL_BUFF
+		CodeLineW = CodeBuffW;
+#endif
 		AttrLine = AttrBuff;
 		AttrLine2 = AttrBuff2;
 		AttrLineFG = AttrBuffFG;
@@ -285,6 +434,9 @@
 	if (AttrDestFG) GlobalUnlock(HAttrFGNew);
 	if (AttrDestBG) GlobalUnlock(HAttrBGNew);
 	if (HCodeNew)   GlobalFree(HCodeNew);
+#if UNICODE_INTERNAL_BUFF
+	if (CodeWNew)   free(CodeWNew);
+#endif
 	if (HAttrNew)   GlobalFree(HAttrNew);
 	if (HAttr2New)  GlobalFree(HAttr2New);
 	if (HAttrFGNew) GlobalFree(HAttrFGNew);
@@ -332,7 +484,7 @@
 	StatusLine = 0;
 }
 
-void NewLine(int Line)
+static void NewLine(int Line)
 {
 	LinePtr = GetLinePtr(Line);
 	CodeLine = &CodeBuff[LinePtr];
@@ -340,6 +492,9 @@
 	AttrLine2 = &AttrBuff2[LinePtr];
 	AttrLineFG = &AttrBuffFG[LinePtr];
 	AttrLineBG = &AttrBuffBG[LinePtr];
+#if UNICODE_INTERNAL_BUFF
+	CodeLineW = &CodeBuffW[LinePtr];
+#endif
 }
 
 void LockBuffer()
@@ -390,6 +545,12 @@
 		GlobalFree(HCodeBuff);
 		HCodeBuff = NULL;
 	}
+#if UNICODE_INTERNAL_BUFF
+	if (CodeBuffW != NULL) {
+		free(CodeBuffW);
+		CodeBuffW = NULL;
+	}
+#endif
 	if (HAttrBuff!=NULL) {
 		GlobalFree(HAttrBuff);
 		HAttrBuff = NULL;
@@ -496,11 +657,17 @@
 		SrcPtr = GetLinePtr(PageStart+NumOfLines-1);
 		for (i=NumOfLines-1; i>=Bottom+1; i--) {
 			memcpy(&(CodeBuff[DestPtr]),&(CodeBuff[SrcPtr]),NumOfColumns);
+#if UNICODE_INTERNAL_BUFF
+			memcpyW(&(CodeBuffW[DestPtr]),&(CodeBuffW[SrcPtr]),NumOfColumns);
+#endif
 			memcpy(&(AttrBuff[DestPtr]),&(AttrBuff[SrcPtr]),NumOfColumns);
 			memcpy(&(AttrBuff2[DestPtr]),&(AttrBuff2[SrcPtr]),NumOfColumns);
 			memcpy(&(AttrBuffFG[DestPtr]),&(AttrBuffFG[SrcPtr]),NumOfColumns);
 			memcpy(&(AttrBuffBG[DestPtr]),&(AttrBuffBG[SrcPtr]),NumOfColumns);
 			memset(&(CodeBuff[SrcPtr]),0x20,NumOfColumns);
+#if UNICODE_INTERNAL_BUFF
+			memsetW(&(CodeBuffW[SrcPtr]),0x20,NumOfColumns);
+#endif
 			memset(&(AttrBuff[SrcPtr]),AttrDefault,NumOfColumns);
 			memset(&(AttrBuff2[SrcPtr]),CurCharAttr.Attr2 & Attr2ColorMask, NumOfColumns);
 			memset(&(AttrBuffFG[SrcPtr]),CurCharAttr.Fore,NumOfColumns);
@@ -512,6 +679,9 @@
 	}
 	for (i = 1 ; i <= n ; i++) {
 		memset(&CodeBuff[DestPtr],0x20,NumOfColumns);
+#if UNICODE_INTERNAL_BUFF
+		memsetW(&CodeBuffW[DestPtr],0x20,NumOfColumns);
+#endif
 		memset(&AttrBuff[DestPtr],AttrDefault,NumOfColumns);
 		memset(&AttrBuff2[DestPtr],CurCharAttr.Attr2 & Attr2ColorMask, NumOfColumns);
 		memset(&AttrBuffFG[DestPtr],CurCharAttr.Fore,NumOfColumns);
@@ -558,6 +728,9 @@
 	AttrLine2 = &AttrBuff2[LinePtr];
 	AttrLineFG = &AttrBuffFG[LinePtr];
 	AttrLineBG = &AttrBuffBG[LinePtr];
+#if UNICODE_INTERNAL_BUFF
+	CodeLineW = &CodeBuffW[LinePtr];
+#endif
 }
 
 void PrevLine()
@@ -568,6 +741,9 @@
 	AttrLine2 = &AttrBuff2[LinePtr];
 	AttrLineFG = &AttrBuffFG[LinePtr];
 	AttrLineBG = &AttrBuffBG[LinePtr];
+#if UNICODE_INTERNAL_BUFF
+	CodeLineW = &CodeBuffW[LinePtr];
+#endif
 }
 
 void EraseKanji(int LR)
@@ -604,17 +780,29 @@
 		pos = ptr + CursorLeftM-1;
 		if (CursorLeftM>0 && (AttrBuff[pos] & AttrKanji)) {
 			CodeBuff[pos] = 0x20;
+#if UNICODE_INTERNAL_BUFF
+			BuffSetChar(&CodeBuffW[pos], 0x20, 'H');
+#endif
 			AttrBuff[pos] &= ~AttrKanji;
 			pos++;
 			CodeBuff[pos] = 0x20;
+#if UNICODE_INTERNAL_BUFF
+			BuffSetChar(&CodeBuffW[pos], 0x20, 'H');
+#endif
 			AttrBuff[pos] &= ~AttrKanji;
 		}
 		pos = ptr + CursorRightM;
 		if (CursorRightM < NumOfColumns-1 && (AttrBuff[pos] & AttrKanji)) {
 			CodeBuff[pos] = 0x20;
+#if UNICODE_INTERNAL_BUFF
+			BuffSetChar(&CodeBuffW[pos], 0x20, 'H');
+#endif
 			AttrBuff[pos] &= ~AttrKanji;
 			pos++;
 			CodeBuff[pos] = 0x20;
+#if UNICODE_INTERNAL_BUFF
+			BuffSetChar(&CodeBuffW[pos], 0x20, 'H');
+#endif
 			AttrBuff[pos] &= ~AttrKanji;
 		}
 		ptr = NextLinePtr(ptr);
@@ -638,6 +826,9 @@
 
 	if (CursorRightM < NumOfColumns-1 && (AttrLine[CursorRightM] & AttrKanji)) {
 		CodeLine[CursorRightM+1] = 0x20;
+#if UNICODE_INTERNAL_BUFF
+		BuffSetChar(&CodeLineW[CursorRightM + 1], 0x20, 'H');
+#endif
 		AttrLine[CursorRightM+1] &= ~AttrKanji;
 		extr = 1;
 	}
@@ -649,6 +840,9 @@
 
 	if (MoveLen > 0) {
 		memmove(&(CodeLine[CursorX+Count]), &(CodeLine[CursorX]), MoveLen);
+#if UNICODE_INTERNAL_BUFF
+		memmoveW(&(CodeLineW[CursorX+Count]), &(CodeLineW[CursorX]), MoveLen);
+#endif
 		memmove(&(AttrLine[CursorX+Count]), &(AttrLine[CursorX]), MoveLen);
 		memmove(&(AttrLine2[CursorX+Count]), &(AttrLine2[CursorX]), MoveLen);
 		memmove(&(AttrLineFG[CursorX+Count]), &(AttrLineFG[CursorX]), MoveLen);
@@ -655,6 +849,9 @@
 		memmove(&(AttrLineBG[CursorX+Count]), &(AttrLineBG[CursorX]), MoveLen);
 	}
 	memset(&(CodeLine[CursorX]), 0x20, Count);
+#if UNICODE_INTERNAL_BUFF
+	memsetW(&(CodeLineW[CursorX]), 0x20, Count);
+#endif
 	memset(&(AttrLine[CursorX]), AttrDefault, Count);
 	memset(&(AttrLine2[CursorX]), CurCharAttr.Attr2 & Attr2ColorMask, Count);
 	memset(&(AttrLineFG[CursorX]), CurCharAttr.Fore, Count);
@@ -663,6 +860,9 @@
 	if ((AttrLine[CursorRightM] & AttrKanji) != 0) {
 		/* then delete it */
 		CodeLine[CursorRightM] = 0x20;
+#if UNICODE_INTERNAL_BUFF
+		BuffSetChar(&CodeLineW[CursorRightM], 0x20, 'H');
+#endif
 		AttrLine[CursorRightM] &= ~AttrKanji;
 	}
 	BuffUpdateRect(CursorX, CursorY, CursorRightM+extr, CursorY);
@@ -687,6 +887,9 @@
 	}
 	for (i = CursorY ; i <= YEnd ; i++) {
 		memset(&(CodeBuff[TmpPtr+offset]),0x20,NumOfColumns-offset);
+#if UNICODE_INTERNAL_BUFF
+		memsetW(&(CodeBuffW[TmpPtr+offset]),0x20,NumOfColumns-offset);
+#endif
 		memset(&(AttrBuff[TmpPtr+offset]),AttrDefault,NumOfColumns-offset);
 		memset(&(AttrBuff2[TmpPtr+offset]),CurCharAttr.Attr2 & Attr2ColorMask, NumOfColumns-offset);
 		memset(&(AttrBuffFG[TmpPtr+offset]),CurCharAttr.Fore,NumOfColumns-offset);
@@ -722,6 +925,9 @@
 			offset = CursorX+1;
 		}
 		memset(&(CodeBuff[TmpPtr]),0x20,offset);
+#if UNICODE_INTERNAL_BUFF
+		memsetW(&(CodeBuffW[TmpPtr]),0x20,offset);
+#endif
 		memset(&(AttrBuff[TmpPtr]),AttrDefault,offset);
 		memset(&(AttrBuff2[TmpPtr]),CurCharAttr.Attr2 & Attr2ColorMask, offset);
 		memset(&(AttrBuffFG[TmpPtr]),CurCharAttr.Fore,offset);
@@ -756,6 +962,9 @@
 	linelen = CursorRightM - CursorLeftM + 1;
 	for (i= YEnd-Count ; i>=CursorY ; i--) {
 		memcpy(&(CodeBuff[DestPtr]), &(CodeBuff[SrcPtr]), linelen);
+#if UNICODE_INTERNAL_BUFF
+		memcpyW(&(CodeBuffW[DestPtr]), &(CodeBuffW[SrcPtr]), linelen);
+#endif
 		memcpy(&(AttrBuff[DestPtr]), &(AttrBuff[SrcPtr]), linelen);
 		memcpy(&(AttrBuff2[DestPtr]), &(AttrBuff2[SrcPtr]), linelen);
 		memcpy(&(AttrBuffFG[DestPtr]), &(AttrBuffFG[SrcPtr]), linelen);
@@ -765,6 +974,9 @@
 	}
 	for (i = 1 ; i <= Count ; i++) {
 		memset(&(CodeBuff[DestPtr]), 0x20, linelen);
+#if UNICODE_INTERNAL_BUFF
+		memsetW(&(CodeBuffW[DestPtr]), 0x20, linelen);
+#endif
 		memset(&(AttrBuff[DestPtr]), AttrDefault, linelen);
 		memset(&(AttrBuff2[DestPtr]), CurCharAttr.Attr2 & Attr2ColorMask, linelen);
 		memset(&(AttrBuffFG[DestPtr]), CurCharAttr.Fore, linelen);
@@ -794,6 +1006,9 @@
 
 	NewLine(PageStart+CursorY);
 	memset(&(CodeLine[XStart]),0x20,Count);
+#if UNICODE_INTERNAL_BUFF
+	memsetW(&(CodeLineW[XStart]),0x20,Count);
+#endif
 	memset(&(AttrLine[XStart]),AttrDefault,Count);
 	memset(&(AttrLine2[XStart]),CurCharAttr.Attr2 & Attr2ColorMask, Count);
 	memset(&(AttrLineFG[XStart]),CurCharAttr.Fore,Count);
@@ -835,6 +1050,9 @@
 	linelen = CursorRightM - CursorLeftM + 1;
 	for (i=CursorY ; i<= YEnd-Count ; i++) {
 		memcpy(&(CodeBuff[DestPtr]), &(CodeBuff[SrcPtr]), linelen);
+#if UNICODE_INTERNAL_BUFF
+		memcpyW(&(CodeBuffW[DestPtr]), &(CodeBuffW[SrcPtr]), linelen);
+#endif
 		memcpy(&(AttrBuff[DestPtr]), &(AttrBuff[SrcPtr]), linelen);
 		memcpy(&(AttrBuff2[DestPtr]), &(AttrBuff2[SrcPtr]), linelen);
 		memcpy(&(AttrBuffFG[DestPtr]), &(AttrBuffFG[SrcPtr]), linelen);
@@ -844,6 +1062,9 @@
 	}
 	for (i = YEnd+1-Count ; i<=YEnd ; i++) {
 		memset(&(CodeBuff[DestPtr]), 0x20, linelen);
+#if UNICODE_INTERNAL_BUFF
+		memsetW(&(CodeBuffW[DestPtr]), 0x20, linelen);
+#endif
 		memset(&(AttrBuff[DestPtr]), AttrDefault, linelen);
 		memset(&(AttrBuff2[DestPtr]), CurCharAttr.Attr2 & Attr2ColorMask,  linelen);
 		memset(&(AttrBuffFG[DestPtr]), CurCharAttr.Fore, linelen);
@@ -875,6 +1096,9 @@
 
 	if (CursorRightM < NumOfColumns-1 && (AttrLine[CursorRightM] & AttrKanji)) {
 		CodeLine[CursorRightM] = 0x20;
+#if UNICODE_INTERNAL_BUFF
+		BuffSetChar(&CodeLineW[CursorRightM], 0x20, 'H');
+#endif
 		AttrLine[CursorRightM] &= ~AttrKanji;
 		CodeLine[CursorRightM+1] = 0x20;
 		AttrLine[CursorRightM+1] &= ~AttrKanji;
@@ -888,6 +1112,9 @@
 
 	if (MoveLen > 0) {
 		memmove(&(CodeLine[CursorX]), &(CodeLine[CursorX+Count]), MoveLen);
+#if UNICODE_INTERNAL_BUFF
+		memmoveW(&(CodeLineW[CursorX]), &(CodeLineW[CursorX+Count]), MoveLen);
+#endif
 		memmove(&(AttrLine[CursorX]), &(AttrLine[CursorX+Count]), MoveLen);
 		memmove(&(AttrLine2[CursorX]), &(AttrLine2[CursorX+Count]), MoveLen);
 		memmove(&(AttrLineFG[CursorX]), &(AttrLineFG[CursorX+Count]), MoveLen);
@@ -894,6 +1121,9 @@
 		memmove(&(AttrLineBG[CursorX]), &(AttrLineBG[CursorX+Count]), MoveLen);
 	}
 	memset(&(CodeLine[CursorX + MoveLen]), 0x20, Count);
+#if UNICODE_INTERNAL_BUFF
+	memsetW(&(CodeLineW[CursorX + MoveLen]), 0x20, Count);
+#endif
 	memset(&(AttrLine[CursorX + MoveLen]), AttrDefault, Count);
 	memset(&(AttrLine2[CursorX + MoveLen]), CurCharAttr.Attr2 & Attr2ColorMask, Count);
 	memset(&(AttrLineFG[CursorX + MoveLen]), CurCharAttr.Fore, Count);
@@ -917,6 +1147,9 @@
 		Count = NumOfColumns-CursorX;
 	}
 	memset(&(CodeLine[CursorX]),0x20,Count);
+#if UNICODE_INTERNAL_BUFF
+	memsetW(&(CodeLineW[CursorX]),0x20,Count);
+#endif
 	memset(&(AttrLine[CursorX]),AttrDefault,Count);
 	memset(&(AttrLine2[CursorX]),CurCharAttr.Attr2 & Attr2ColorMask, Count);
 	memset(&(AttrLineFG[CursorX]),CurCharAttr.Fore,Count);
@@ -935,6 +1168,9 @@
 	TmpPtr = GetLinePtr(PageStart);
 	for (i = 0 ; i <= NumOfLines-1-StatusLine ; i++) {
 		memset(&(CodeBuff[TmpPtr]),'E',NumOfColumns);
+#if UNICODE_INTERNAL_BUFF
+		memsetW(&(CodeBuffW[TmpPtr]),'E',NumOfColumns);
+#endif
 		memset(&(AttrBuff[TmpPtr]),AttrDefault,NumOfColumns);
 		memset(&(AttrBuff2[TmpPtr]),AttrDefault,NumOfColumns);
 		memset(&(AttrBuffFG[TmpPtr]),AttrDefaultFG,NumOfColumns);
@@ -974,6 +1210,9 @@
 			}
 			Ptr = GetLinePtr(PageStart+Y);
 			memset(&(CodeBuff[Ptr+CursorX]),'q',C);
+#if UNICODE_INTERNAL_BUFF
+			memsetW(&(CodeBuffW[Ptr+CursorX]),'q',C);
+#endif
 			memset(&(AttrBuff[Ptr+CursorX]),Attr.Attr,C);
 			memset(&(AttrBuff2[Ptr+CursorX]),Attr.Attr2,C);
 			memset(&(AttrBuffFG[Ptr+CursorX]),Attr.Fore,C);
@@ -1002,6 +1241,9 @@
 			}
 			for (i=1; i<=C; i++) {
 				CodeBuff[Ptr+X] = 'x';
+#if UNICODE_INTERNAL_BUFF
+				BuffSetChar(&CodeBuffW[Ptr+X], 0x20, 'H');
+#endif
 				AttrBuff[Ptr+X] = Attr.Attr;
 				AttrBuff2[Ptr+X] = Attr.Attr2;
 				AttrBuffFG[Ptr+X] = Attr.Fore;
@@ -1037,6 +1279,9 @@
 		if ((XStart>0) &&
 		    ((AttrBuff[Ptr+XStart-1] & AttrKanji) != 0)) {
 			CodeBuff[Ptr+XStart-1] = 0x20;
+#if UNICODE_INTERNAL_BUFF
+			BuffSetChar(&CodeBuffW[Ptr+XStart-1], 0x20, 'H');
+#endif
 			AttrBuff[Ptr+XStart-1] = CurCharAttr.Attr;
 			AttrBuff2[Ptr+XStart-1] = CurCharAttr.Attr2;
 			AttrBuffFG[Ptr+XStart-1] = CurCharAttr.Fore;
@@ -1045,6 +1290,9 @@
 		if ((XStart+C<NumOfColumns) &&
 		    ((AttrBuff[Ptr+XStart+C-1] & AttrKanji) != 0)) {
 			CodeBuff[Ptr+XStart+C] = 0x20;
+#if UNICODE_INTERNAL_BUFF
+			BuffSetChar(&CodeBuffW[Ptr+XStart+C], 0x20, 'H');
+#endif
 			AttrBuff[Ptr+XStart+C] = CurCharAttr.Attr;
 			AttrBuff2[Ptr+XStart+C] = CurCharAttr.Attr2;
 			AttrBuffFG[Ptr+XStart+C] = CurCharAttr.Fore;
@@ -1051,6 +1299,9 @@
 			AttrBuffBG[Ptr+XStart+C] = CurCharAttr.Back;
 		}
 		memset(&(CodeBuff[Ptr+XStart]),0x20,C);
+#if UNICODE_INTERNAL_BUFF
+		memsetW(&(CodeBuffW[Ptr+XStart]),0x20,C);
+#endif
 		memset(&(AttrBuff[Ptr+XStart]),AttrDefault,C);
 		memset(&(AttrBuff2[Ptr+XStart]),CurCharAttr.Attr2 & Attr2ColorMask, C);
 		memset(&(AttrBuffFG[Ptr+XStart]),CurCharAttr.Fore,C);
@@ -1083,13 +1334,22 @@
 		if ((XStart>0) &&
 		    ((AttrBuff[Ptr+XStart-1] & AttrKanji) != 0)) {
 			CodeBuff[Ptr+XStart-1] = 0x20;
+#if UNICODE_INTERNAL_BUFF
+			BuffSetChar(&CodeLineW[Ptr + XStart - 1], 0x20, 'H');
+#endif
 			AttrBuff[Ptr+XStart-1] ^= AttrKanji;
 		}
 		if ((XStart+Cols<NumOfColumns) &&
 		    ((AttrBuff[Ptr+XStart+Cols-1] & AttrKanji) != 0)) {
 			CodeBuff[Ptr+XStart+Cols] = 0x20;
+#if UNICODE_INTERNAL_BUFF
+			BuffSetChar(&CodeLineW[Ptr + XStart + Cols], 0x20, 'H');
+#endif
 		}
 		memset(&(CodeBuff[Ptr+XStart]), ch, Cols);
+#if UNICODE_INTERNAL_BUFF
+		BuffSetChar(&CodeLineW[Ptr + XStart], 0x20, 'H');
+#endif
 		memset(&(AttrBuff[Ptr+XStart]), CurCharAttr.Attr, Cols);
 		memset(&(AttrBuff2[Ptr+XStart]), CurCharAttr.Attr2, Cols);
 		memset(&(AttrBuffFG[Ptr+XStart]), CurCharAttr.Fore, Cols);
@@ -1145,6 +1405,9 @@
 		DPtr = GetLinePtr(PageStart+DstY);
 		for (i=0; i<L; i++) {
 			memcpy(&(CodeBuff[DPtr+DstX]), &(CodeBuff[SPtr+SrcXStart]), C);
+#if UNICODE_INTERNAL_BUFF
+			memcpyW(&(CodeBuffW[DPtr+DstX]), &(CodeBuffW[SPtr+SrcXStart]), C);
+#endif
 			memcpy(&(AttrBuff[DPtr+DstX]), &(AttrBuff[SPtr+SrcXStart]), C);
 			memcpy(&(AttrBuff2[DPtr+DstX]), &(AttrBuff2[SPtr+SrcXStart]), C);
 			memcpy(&(AttrBuffFG[DPtr+DstX]), &(AttrBuffFG[SPtr+SrcXStart]), C);
@@ -1158,6 +1421,9 @@
 		DPtr = GetLinePtr(PageStart+DstY+L-1);
 		for (i=L; i>0; i--) {
 			memcpy(&(CodeBuff[DPtr+DstX]), &(CodeBuff[SPtr+SrcXStart]), C);
+#if UNICODE_INTERNAL_BUFF
+			memcpyW(&(CodeBuffW[DPtr+DstX]), &(CodeBuffW[SPtr+SrcXStart]), C);
+#endif
 			memcpy(&(AttrBuff[DPtr+DstX]), &(AttrBuff[SPtr+SrcXStart]), C);
 			memcpy(&(AttrBuff2[DPtr+DstX]), &(AttrBuff2[SPtr+SrcXStart]), C);
 			memcpy(&(AttrBuffFG[DPtr+DstX]), &(AttrBuffFG[SPtr+SrcXStart]), C);
@@ -1171,6 +1437,9 @@
 		DPtr = GetLinePtr(PageStart+DstY);
 		for (i=0; i<L; i++) {
 			memmove(&(CodeBuff[DPtr+DstX]), &(CodeBuff[SPtr+SrcXStart]), C);
+#if UNICODE_INTERNAL_BUFF
+			memmoveW(&(CodeBuffW[DPtr+DstX]), &(CodeBuffW[SPtr+SrcXStart]), C);
+#endif
 			memmove(&(AttrBuff[DPtr+DstX]), &(AttrBuff[SPtr+SrcXStart]), C);
 			memmove(&(AttrBuff2[DPtr+DstX]), &(AttrBuff2[SPtr+SrcXStart]), C);
 			memmove(&(AttrBuffFG[DPtr+DstX]), &(AttrBuffFG[SPtr+SrcXStart]), C);
@@ -1386,7 +1655,7 @@
 	BuffUpdateRect(0, YStart, NumOfColumns-1, YEnd);
 }
 
-int LeftHalfOfDBCS(LONG Line, int CharPtr)
+static int LeftHalfOfDBCS(LONG Line, int CharPtr)
 // If CharPtr is on the right half of a DBCS character,
 // return pointer to the left half
 //   Line: points to a line in CodeBuff
@@ -1400,7 +1669,7 @@
 	return CharPtr;
 }
 
-int MoveCharPtr(LONG Line, int *x, int dx)
+static int MoveCharPtr(LONG Line, int *x, int dx)
 // move character pointer x by dx character unit
 //   in the line specified by Line
 //   Line: points to a line in CodeBuff
@@ -2002,6 +2271,242 @@
 	}
 }
 
+/**
+ *	\x83\x86\x83j\x83R\x81[\x83h\x83L\x83\x83\x83\x89\x83N\x83^\x82\xF01\x95\xB6\x8E\x9A\x83o\x83b\x83t\x83@\x82֓\xFC\x97͂\xB7\x82\xE9
+ *	@param[in]	uc		unicode character
+ *	@param[in]	Attr	attributes
+ *	@param[in]	Insert	Insert flag
+ */
+#if UNICODE_INTERNAL_BUFF
+char BuffPutUnicode(unsigned int uc, TCharAttr Attr, BOOL Insert)
+{
+//	int XStart, LineEnd, MoveLen;
+//	int extr = 0;
+//	unsigned int w = uc;
+	int ret;
+//	wchar_t wchar = (wchar_t)uc;
+	BYTE b1, b2;
+	unsigned int u32 = uc;
+	char retval = 'h';
+	BOOL half_width = TRUE;
+
+	if (uc < 0x80) {
+		b1 = (BYTE)uc;
+		b2 = 0;
+		ret = 1;
+	} else {
+		char mbchar[2];
+		ret = UTF32ToCP932(uc, mbchar, 2);
+		if (ret == 0) {
+			b1 = '?';
+			b2 = 0;
+			ret = 1;
+		} else if (ret == 1) {
+			b1 = mbchar[0];
+			b2 = 0;
+		} else {	// ret == 2
+			b1 = mbchar[0];
+			b2 = mbchar[1];
+			ret = 2;
+		}
+	}
+
+#if 0
+	OutputDebugPrintf("BuffPutUnicode(%06x(%02x,%02x)\n",
+					  uc, b1, b2);
+#endif
+
+	if (ts.EnableContinuedLineCopy && CursorX == 0 && (AttrLine[0] & AttrLineContinued)) {
+		Attr.Attr |= AttrLineContinued;
+	}
+
+	if (Insert) {
+		assert(FALSE);
+#if 0
+		if (CursorX > CursorRightM)
+			LineEnd = NumOfColumns - 1;
+		else
+			LineEnd = CursorRightM;
+
+		if (LineEnd < NumOfColumns - 1 && (AttrLine[LineEnd] & AttrKanji)) {
+			CodeLine[LineEnd] = 0x20;
+			CodeLineW[LineEnd].wc = 0x20;
+			CodeLineW[LineEnd].u32 = 0x20;
+			AttrLine[LineEnd] &= ~AttrKanji;
+			CodeLine[LineEnd+1] = 0x20;
+			AttrLine[LineEnd+1] &= ~AttrKanji;
+			extr = 1;
+		}
+
+		MoveLen = LineEnd - CursorX - 1;
+		if (MoveLen > 0) {
+			memmove(&CodeLine[CursorX+2], &CodeLine[CursorX], MoveLen);
+			memmove(&CodeLineW[CursorX+2], &CodeLineW[CursorX], MoveLen * sizeof(wchar_t));
+			memmove(&AttrLine[CursorX+2], &AttrLine[CursorX], MoveLen);
+			memmove(&AttrLine2[CursorX+2], &AttrLine2[CursorX], MoveLen);
+			memmove(&AttrLineFG[CursorX+2], &AttrLineFG[CursorX], MoveLen);
+			memmove(&AttrLineBG[CursorX+2], &AttrLineBG[CursorX], MoveLen);
+		}
+
+		if (HIBYTE(w) == 0) {
+			int a = 0;
+		}
+		CodeLine[CursorX] = HIBYTE(w);
+		CodeLineW[CursorX].wc = u16_high;
+		CodeLineW[CursorX].u32 = u32;
+		AttrLine[CursorX] = Attr.Attr;
+		AttrLine2[CursorX] = Attr.Attr2;
+		AttrLineFG[CursorX] = Attr.Fore;
+		AttrLineBG[CursorX] = Attr.Back;
+		if (CursorX < LineEnd) {
+			CodeLine[CursorX+1] = LOBYTE(w);
+			CodeLineW[CursorX + 1].wc = u16_low;
+			CodeLineW[CursorX + 1].u32 = 0;
+			//			CodeLineW[CursorX+1] = 0;
+			AttrLine[CursorX+1] = Attr.Attr;
+			AttrLine2[CursorX+1] = Attr.Attr2;
+			AttrLineFG[CursorX+1] = Attr.Fore;
+			AttrLineBG[CursorX+1] = Attr.Back;
+		}
+		/* begin - ishizaki */
+		markURL(CursorX);
+		markURL(CursorX+1);
+		/* end - ishizaki */
+
+		/* last char in current line is kanji first? */
+		if ((AttrLine[LineEnd] & AttrKanji) != 0) {
+			/* then delete it */
+			CodeLine[LineEnd] = 0x20;
+			BuffSetChar(&CodeLineW[LineEnd], 0x20, 'H');
+			AttrLine[LineEnd] = CurCharAttr.Attr;
+			AttrLine2[LineEnd] = CurCharAttr.Attr2;
+			AttrLineFG[LineEnd] = CurCharAttr.Fore;
+			AttrLineBG[LineEnd] = CurCharAttr.Back;
+		}
+
+		if (StrChangeCount==0) {
+			XStart = CursorX;
+		}
+		else {
+			XStart = StrChangeStart;
+		}
+		StrChangeCount = 0;
+		BuffUpdateRect(XStart, CursorY, LineEnd+extr, CursorY);
+#endif
+	} else {
+		buff_char_t *p;
+
+		if (UnicodeIsVariationSelector(u32)) {
+			retval = 'V';
+		} else if (UnicodeIsCombiningCharacter(u32)) {
+			retval = '0';
+		} else if (u32 == 0x200d) {
+			retval = '0';
+		} else {
+			retval = UnicodeGetWidthProperty(u32);
+			half_width = (retval == 'H') ? TRUE : FALSE;
+		}
+
+		// \x91O\x82̕\xB6\x8E\x9A
+		p = NULL;	// NULL\x82̂Ƃ\xAB\x81A\x91O\x82̕\xB6\x8E\x9A\x82͂Ȃ\xA2
+		if (CursorX >= 1 && CodeLineW[CursorX - 1].u32 != 0) {
+			p = &CodeLineW[CursorX - 1];
+		} else if (CursorX >= 2 && CodeLineW[CursorX - 2].u32 != 0) {
+			p = &CodeLineW[CursorX - 2];
+		}
+		if (p != NULL && p->u32_last == 0x200d) {
+			retval = '0';
+		}
+
+		if (retval == 'V' || retval == '0') {
+			// \x91O\x82̕\xB6\x8E\x9A\x82ɂ\xAD\x82\xC1\x82‚\xAF\x82\xE9
+			// VariationSelector or
+			// CombiningCharacter or
+			// ZERO WIDTH JOINER(ZWJ)
+
+			if (p != NULL) {
+				// \x91O\x82̕\xB6\x8E\x9A\x82ɂ\xAD\x82\xC1\x82‚\xAF\x82\xE9
+				BuffAddChar(p, uc, retval);
+				AttrLine[CursorX] = Attr.Attr; // | AttrKanji; /* DBCS first byte */
+				AttrLine2[CursorX] = Attr.Attr2;
+				AttrLineFG[CursorX] = Attr.Fore;
+				AttrLineBG[CursorX] = Attr.Back;
+			} else {
+				// \x91O\x82\xAA\x82Ȃ\xA2\x82̂ɂ\xAD\x82\xC1\x82‚\xAD\x95\xB6\x8E\x9A\x82\xAA\x8Fo\x82Ă\xAB\x82\xBD\x82Ƃ\xAB
+				// \x82Ƃ肠\x82\xA6\x82\xB8\x83X\x83y\x81[\x83X\x82ɂ\xAD\x82\xC1\x82‚\xAF\x82\xE9
+				p = &CodeLineW[CursorX];
+				BuffSetChar(p, ' ', 'H');
+				BuffAddChar(p, uc, retval);
+				AttrLine[CursorX] = Attr.Attr;
+				AttrLine2[CursorX] = Attr.Attr2;
+				AttrLineFG[CursorX] = Attr.Fore;
+				AttrLineBG[CursorX] = Attr.Back;
+			}
+		} else {
+			// \x90V\x82\xB5\x82\xA2\x95\xB6\x8E\x9A\x92lj\xC1
+			CodeLine[CursorX] = b1;
+			BuffSetChar(&CodeLineW[CursorX], u32, retval);
+			AttrLine[CursorX] = Attr.Attr; // | AttrKanji; /* DBCS first byte */
+			AttrLine2[CursorX] = Attr.Attr2;
+			AttrLineFG[CursorX] = Attr.Fore;
+			AttrLineBG[CursorX] = Attr.Back;
+
+			if (!half_width) {
+				// \x91S\x8Ap\x82̎\x9E\x82͎\x9F\x82̕\xB6\x8E\x9A\x83R\x81[\x83h\x82\xC90\x82\xF0\x93\xFC\x82\xEA\x82\xE9
+				if (CursorX < NumOfColumns-1) {
+					BuffSetChar(&CodeLineW[CursorX+1], 0, 'H');
+					CodeLine[CursorX+1] = b2;
+					AttrLine[CursorX+1] = Attr.Attr;
+					AttrLine2[CursorX+1] = Attr.Attr2;
+					AttrLineFG[CursorX+1] = Attr.Fore;
+					AttrLineBG[CursorX+1] = Attr.Back;
+				}
+			}
+		}
+
+		/* begin - ishizaki */
+//		markURL(CursorX);
+//		markURL(CursorX+1);
+		/* end - ishizaki */
+
+		if (StrChangeCount==0) {
+			StrChangeStart = CursorX;
+		}
+		if (retval == '0' || retval == 'V') {
+			if (StrChangeCount == 0) {
+				StrChangeCount = 1;
+			}
+		} else if (retval == 'H') {
+			// \x94\xBC\x8Ap
+			StrChangeCount = StrChangeCount + 1;
+		} else if (retval == 'A') {
+			// \x93\xC1\x90\xAB\x92lA(\x9EB\x96\x86)\x82\xF0\x8E\x9D\x82•\xB6\x8E\x9A\x82́A\x91S\x8Ap\x82̕\xB6\x8E\x9A (fullwidth) \x82Ƃ\xB5\x82Ĉ\xB5\x82\xA4\x81B
+			StrChangeCount = StrChangeCount + 2;
+		} else {
+			// \x91S\x8Ap ('F' or 'W')
+			StrChangeCount = StrChangeCount + 2;
+		}
+#if 0
+		{
+			char ba[128];
+			memcpy(ba, &CodeLine[0], _countof(ba)-1);
+			ba[127] = 0;
+			OutputDebugPrintf("A '%s'\n", ba);
+			wchar_t bb[128];
+			memcpy(bb, &CodeLineW[0], _countof(bb)-1);
+			bb[127] = 0;
+			OutputDebugPrintfW(L"W '%s'\n", bb);
+		}
+#endif
+	}
+
+#if 0
+	OutputDebugPrintf("BuffPutUnicode leave\n");
+#endif
+	return retval;
+}
+#endif
+
 BOOL CheckSelect(int x, int y)
 //  subroutine called by BuffUpdateRect
 {
@@ -2024,6 +2529,143 @@
 	}
 }
 
+#if UNICODE_INTERNAL_BUFF
+/*
+ *	DrawX,Y			Clint\x97̈\xE6\x95`\x89\xE6\x88ʒu(pixel)
+ *	SY				\x83X\x83N\x83\x8A\x81[\x83\x93\x8F\xE3\x82̈ʒu(Charactor)
+ *					PageStart + YStart \x82Ȃ\xC7
+ *	IStart,IEnd		\x83X\x83N\x83\x8A\x81[\x83\x93\x8F\xE3\x82̈ʒu(Charactor)
+ */
+static void BuffDrawLineI(int DrawX, int DrawY, int SY, int IStart, int IEnd)
+{
+	int X = DrawX;
+	int Y = DrawY;
+	const LONG TmpPtr = GetLinePtr(SY);
+	int istart = IStart;
+	char bufA[TermWidthMax];
+	wchar_t bufW[TermWidthMax];
+	char bufWW[TermWidthMax];
+	int lenW = 0;
+	int lenA = 0;
+	TCharAttr CurAttr;
+	BOOL ConbinationCharInclude = FALSE;
+
+	int count = 0;		// index;
+	while (istart + count <= IEnd) {
+		buff_char_t *b;
+		TCharAttr TempAttr;
+		BOOL DrawFlag = FALSE;
+		BOOL Conbination = FALSE;
+
+		// \x83A\x83g\x83\x8A\x83r\x83\x85\x81[\x83g\x8E擾
+		TempAttr.Attr = AttrBuff[TmpPtr+istart+count] & ~ AttrKanji;
+		TempAttr.Attr2 = AttrBuff2[TmpPtr+istart+count];
+		TempAttr.Fore = AttrBuffFG[TmpPtr+istart+count];
+		TempAttr.Back = AttrBuffBG[TmpPtr+istart+count];
+
+		bufA[lenA] = CodeBuff[TmpPtr + istart + count];
+		lenA++;
+
+		b = &CodeBuffW[TmpPtr + istart + count];
+		if (b->u32 != 0) {
+			if (b->u32 < 0x10000) {
+				bufW[lenW] = b->wc2[0];
+				bufWW[lenW] = b->WidthProperty;
+				lenW++;
+			} else {
+				bufW[lenW] = b->wc2[0];
+				bufWW[lenW] = b->WidthProperty;
+				lenW++;
+				bufW[lenW] = b->wc2[1];
+				bufWW[lenW] = '0';
+				lenW++;
+				Conbination = TRUE;
+				DrawFlag = TRUE;
+			}
+			if ((b->WidthProperty == 'W' || b->WidthProperty == 'H') &&
+				b->CombinationCharCount16 != 0)
+			{
+				int i;
+				for (i = 0 ; i < (int)b->CombinationCharCount16; i++) {
+					bufW[lenW+i] = b->pCombinationChars16[i];
+					bufWW[lenW + i] = '0';
+				}
+				lenW += b->CombinationCharCount16;
+				Conbination = TRUE;
+				DrawFlag = TRUE;
+			}
+		}
+
+		if (count == 0) {
+			// \x8Dŏ\x89\x82\xCC1\x95\xB6\x8E\x9A\x96\xDA
+			CurAttr = TempAttr;
+		}
+
+		if (DrawFlag) {
+			;
+		} else if (istart + count == IEnd) {
+			// \x8DŌ\xE3\x82܂ŃX\x83L\x83\x83\x83\x93\x82\xB5\x82\xBD
+			DrawFlag = TRUE;
+		} else if (b->u32 != 0) {
+			// \x8E\x9F\x82̕\xB6\x8E\x9A\x82ŃA\x83g\x83\x8A\x83r\x83\x85\x81[\x83g\x82\xAA\x95ω\xBB\x82\xB7\x82\xE9?
+			if (count > 0 && TCharAttrCmp(CurAttr, TempAttr) != 0) {
+				// \x83A\x83g\x83\x8A\x83r\x83\x85\x81[\x83g\x82\xAA\x95ω\xBB\x82\xB5\x82\xBD
+				DrawFlag = TRUE;
+				lenA--;
+				lenW--;
+			} else if ((b->WidthProperty == 'W' || b->WidthProperty == 'H' )
+					   && b->CombinationCharCount16 != 0)
+			{
+				// \x83A\x83g\x83\x8A\x83r\x83\x85\x81[\x83g(unicode\x8F\xF3\x91\xD4)\x82\xAA\x95ω\xBB\x82\xB5\x82\xBD
+				DrawFlag = TRUE;
+				lenA--;
+				lenW--;
+			} else {
+				if (Conbination == FALSE) {
+					if (ConbinationCharInclude) {
+						// not \x8C\x8B\x8D\x87\x95\xB6\x8E\x9A && \x8C\x8B\x8D\x87\x95\xB6\x8E\x9A\x97\xF1?
+						DrawFlag = TRUE;
+						lenA--;
+						lenW--;
+					}
+				}
+				else {
+					ConbinationCharInclude = TRUE;
+				}
+			}
+		}
+
+		if (DrawFlag) {
+			// \x95`\x89悷\x82\xE9
+			bufA[lenA] = 0;
+			bufW[lenW] = 0;
+			bufWW[lenW] = 0;
+
+#if 0
+			OutputDebugPrintf("A[%d] '%s'\n", lenA, bufA);
+			OutputDebugPrintfW(L"W[%d] '%s'\n", lenW, bufW);
+#endif
+
+			DispSetupDC(CurAttr, FALSE);
+#if UNICODE_INTERNAL_BUFF && UNICODE_DISPLAY
+			DispStrW(bufW, bufWW, lenW, Y, &X);
+#else
+			DispStr(bufA, lenA, Y, &X);
+#endif
+
+			lenA = 0;
+			lenW = 0;
+			DrawFlag = FALSE;
+			istart += (count+1);
+			count = 0;
+			ConbinationCharInclude = FALSE;
+		} else {
+			count++;
+		}
+	}
+}
+#endif
+
 void BuffUpdateRect
   (int XStart, int YStart, int XEnd, int YEnd)
 // Display text in a rectangular region in the screen
@@ -2036,8 +2678,18 @@
 	int IStart, IEnd;
 	int X, Y;
 	LONG TmpPtr;
-	TCharAttr CurAttr, TempAttr;
-	BOOL CurSel, TempSel, Caret;
+	TCharAttr TempAttr;
+#if !UNICODE_INTERNAL_BUFF
+	TCharAttr CurAttr;
+	BOOL CurSel;
+#endif
+	BOOL TempSel, Caret;
+#if UNICODE_INTERNAL_BUFF
+//	char bufA[256];
+//	wchar_t bufW[256];
+//	int lenW = 0;
+//	int lenA = 0;
+#endif
 
 	if (XStart >= WinOrgX+WinWidth) {
 		return;
@@ -2065,6 +2717,13 @@
 		YEnd = WinOrgY+WinHeight-1;
 	}
 
+#if 0
+	OutputDebugPrintf("BuffUpdateRect (%d,%d)-(%d,%d) [%d,%d]\n",
+					  XStart, YStart,
+					  XEnd, YEnd,
+					  XEnd - XStart + 1, YEnd - YStart + 1);
+#endif
+
 	TempAttr = DefCharAttr;
 	TempSel = FALSE;
 
@@ -2086,6 +2745,7 @@
 		X = (IStart-WinOrgX)*FontWidth;
 
 		i = IStart;
+#if !UNICODE_INTERNAL_BUFF
 		do {
 			CurAttr.Attr = AttrBuff[TmpPtr+i] & ~ AttrKanji;
 			CurAttr.Attr2 = AttrBuff2[TmpPtr+i];
@@ -2113,6 +2773,11 @@
 			i = i+count;
 		}
 		while (i<=IEnd);
+#else
+		{
+			BuffDrawLineI(X, Y, j, IStart, IEnd);
+		}
+#endif
 		Y = Y + FontHeight;
 		TmpPtr = NextLinePtr(TmpPtr);
 	}
@@ -2125,7 +2790,9 @@
 // Display not-yet-displayed string
 {
 	int X, Y;
+#if !UNICODE_INTERNAL_BUFF
 	TCharAttr TempAttr;
+#endif
 	int pos, len;
 
 	if (StrChangeCount==0) {
@@ -2138,6 +2805,7 @@
 		return;
 	}
 
+#if !UNICODE_INTERNAL_BUFF
 	TempAttr.Attr = AttrLine[StrChangeStart];
 	TempAttr.Attr2 = AttrLine2[StrChangeStart];
 	TempAttr.Fore = AttrLineFG[StrChangeStart];
@@ -2172,7 +2840,9 @@
 		DispSetupDC(TempAttr, FALSE);
 		DispStr(&CodeLine[StrChangeStart],StrChangeCount,Y, &X);
 	}
-
+#else
+	BuffDrawLineI(X, Y, PageStart+CursorY, StrChangeStart, StrChangeStart + StrChangeCount - 1);
+#endif
 	StrChangeCount = 0;
 }
 
@@ -2261,6 +2931,9 @@
 		for (i = CursorBottom-1 ; i >= CursorTop ; i--) {
 			SrcPtr = PrevLinePtr(DestPtr);
 			memcpy(&(CodeBuff[DestPtr]), &(CodeBuff[SrcPtr]), linelen);
+#if UNICODE_INTERNAL_BUFF
+			memcpyW(&(CodeBuffW[DestPtr]), &(CodeBuffW[SrcPtr]), linelen);
+#endif
 			memcpy(&(AttrBuff[DestPtr]), &(AttrBuff[SrcPtr]), linelen);
 			memcpy(&(AttrBuff2[DestPtr]), &(AttrBuff2[SrcPtr]), linelen);
 			memcpy(&(AttrBuffFG[DestPtr]), &(AttrBuffFG[SrcPtr]), linelen);
@@ -2268,6 +2941,9 @@
 			DestPtr = SrcPtr;
 		}
 		memset(&(CodeBuff[SrcPtr]), 0x20, linelen);
+#if UNICODE_INTERNAL_BUFF
+		memsetW(&(CodeBuffW[SrcPtr]), 0x20, linelen);
+#endif
 		memset(&(AttrBuff[SrcPtr]), AttrDefault, linelen);
 		memset(&(AttrBuff2[SrcPtr]), CurCharAttr.Attr2 & Attr2ColorMask, linelen);
 		memset(&(AttrBuffFG[SrcPtr]), CurCharAttr.Fore, linelen);
@@ -2332,6 +3008,9 @@
 			SrcPtr = GetLinePtr(PageStart+CursorTop+n) + (LONG)CursorLeftM;
 			for (i = CursorTop+n ; i<=CursorBottom ; i++) {
 				memmove(&(CodeBuff[DestPtr]), &(CodeBuff[SrcPtr]), linelen);
+#if UNICODE_INTERNAL_BUFF
+				memmoveW(&(CodeBuffW[DestPtr]), &(CodeBuffW[SrcPtr]), linelen);
+#endif
 				memmove(&(AttrBuff[DestPtr]), &(AttrBuff[SrcPtr]), linelen);
 				memmove(&(AttrBuff2[DestPtr]), &(AttrBuff2[SrcPtr]), linelen);
 				memmove(&(AttrBuffFG[DestPtr]), &(AttrBuffFG[SrcPtr]), linelen);
@@ -2345,6 +3024,9 @@
 		}
 		for (i = CursorBottom+1-n ; i<=CursorBottom; i++) {
 			memset(&(CodeBuff[DestPtr]), 0x20, linelen);
+#if UNICODE_INTERNAL_BUFF
+			memsetW(&(CodeBuffW[DestPtr]), 0x20, linelen);
+#endif
 			memset(&(AttrBuff[DestPtr]), AttrDefault, linelen);
 			memset(&(AttrBuff2[DestPtr]), CurCharAttr.Attr2 & Attr2ColorMask, linelen);
 			memset(&(AttrBuffFG[DestPtr]), CurCharAttr.Fore, linelen);
@@ -2393,6 +3075,9 @@
 			SrcPtr = GetLinePtr(PageStart+CursorTop+n) + CursorLeftM;
 			for (i = CursorTop+n ; i<=CursorBottom ; i++) {
 				memmove(&(CodeBuff[DestPtr]), &(CodeBuff[SrcPtr]), linelen);
+#if UNICODE_INTERNAL_BUFF
+				memmoveW(&(CodeBuffW[DestPtr]), &(CodeBuffW[SrcPtr]), linelen);
+#endif
 				memmove(&(AttrBuff[DestPtr]), &(AttrBuff[SrcPtr]), linelen);
 				memmove(&(AttrBuff2[DestPtr]), &(AttrBuff2[SrcPtr]), linelen);
 				memmove(&(AttrBuffFG[DestPtr]), &(AttrBuffFG[SrcPtr]), linelen);
@@ -2406,6 +3091,9 @@
 		}
 		for (i = CursorBottom+1-n ; i<=CursorBottom; i++) {
 			memset(&(CodeBuff[DestPtr]), 0x20, linelen);
+#if UNICODE_INTERNAL_BUFF
+			memsetW(&(CodeBuffW[DestPtr]), 0x20, linelen);
+#endif
 			memset(&(AttrBuff[DestPtr]), AttrDefault, linelen);
 			memset(&(AttrBuff2[DestPtr]), CurCharAttr.Attr2 & Attr2ColorMask, linelen);
 			memset(&(AttrBuffFG[DestPtr]), CurCharAttr.Fore, linelen);
@@ -2445,6 +3133,9 @@
 		SrcPtr = GetLinePtr(PageStart+CursorBottom-n) + CursorLeftM;
 		for (i=CursorBottom-n ; i>=CursorTop ; i--) {
 			memmove(&(CodeBuff[DestPtr]), &(CodeBuff[SrcPtr]), linelen);
+#if UNICODE_INTERNAL_BUFF
+			memmoveW(&(CodeBuffW[DestPtr]), &(CodeBuffW[SrcPtr]), linelen);
+#endif
 			memmove(&(AttrBuff[DestPtr]), &(AttrBuff[SrcPtr]), linelen);
 			memmove(&(AttrBuff2[DestPtr]), &(AttrBuff2[SrcPtr]), linelen);
 			memmove(&(AttrBuffFG[DestPtr]), &(AttrBuffFG[SrcPtr]), linelen);
@@ -2458,6 +3149,9 @@
 	}
 	for (i = CursorTop+n-1; i>=CursorTop; i--) {
 		memset(&(CodeBuff[DestPtr]), 0x20, linelen);
+#if UNICODE_INTERNAL_BUFF
+		memsetW(&(CodeBuffW[DestPtr]), 0x20, linelen);
+#endif
 		memset(&(AttrBuff[DestPtr]), AttrDefault, linelen);
 		memset(&(AttrBuff2[DestPtr]), CurCharAttr.Attr2 & Attr2ColorMask, linelen);
 		memset(&(AttrBuffFG[DestPtr]), CurCharAttr.Fore, linelen);
@@ -2505,7 +3199,7 @@
 
 // called by BuffDblClk
 //   check if a character is the word delimiter
-BOOL IsDelimiter(LONG Line, int CharPtr)
+static BOOL IsDelimiter(LONG Line, int CharPtr)
 {
 	if ((AttrBuff[Line+CharPtr] & AttrKanji) !=0) {
 		return (ts.DelimDBCS!=0);
@@ -3473,6 +4167,9 @@
 
 	NewLine(0);
 	memset(&CodeBuff[0],0x20,BufferSize);
+#if UNICODE_INTERNAL_BUFF
+	memsetW(&CodeBuffW[0],0x20,BufferSize);
+#endif
 	memset(&AttrBuff[0],AttrDefault,BufferSize);
 	memset(&AttrBuff2[0],CurCharAttr.Attr2 & Attr2ColorMask, BufferSize);
 	memset(&AttrBuffFG[0],CurCharAttr.Fore,BufferSize);
@@ -3697,93 +4394,119 @@
 void BuffSaveScreen()
 {
 	PCHAR CodeDest, AttrDest, AttrDest2, AttrDestFG, AttrDestBG;
+#if UNICODE_INTERNAL_BUFF
+	buff_char_t *CodeDestW;
+#endif
 	LONG ScrSize;
+	size_t AllocSize;
 	LONG SrcPtr, DestPtr;
 	int i;
 
 	if (SaveBuff == NULL) {
-		ScrSize = NumOfColumns * NumOfLines;
-		if ((SaveBuff=GlobalAlloc(GMEM_MOVEABLE, ScrSize * 5)) != NULL) {
-			if ((CodeDest=GlobalLock(SaveBuff)) != NULL) {
-				AttrDest = CodeDest + ScrSize;
-				AttrDest2 = AttrDest + ScrSize;
-				AttrDestFG = AttrDest2 + ScrSize;
-				AttrDestBG = AttrDestFG + ScrSize;
+		ScrSize = NumOfColumns * NumOfLines;	// 1\x89\xE6\x96ʕ\xAA\x82̃o\x83b\x83t\x83@\x82̕ۑ\xB6\x90\x94
+#if UNICODE_INTERNAL_BUFF
+		// \x91S\x89\xE6\x96ʕ\xAA\x82̃o\x83C\x83g\x90\x94
+		AllocSize = ScrSize * (5+sizeof(buff_char_t));
+#else
+		AllocSize = ScrSize * 5;
+#endif
+		SaveBuff = malloc(AllocSize);
+		if (SaveBuff != NULL) {
+			CodeDest = SaveBuff;
+			AttrDest = CodeDest + ScrSize;
+			AttrDest2 = AttrDest + ScrSize;
+			AttrDestFG = AttrDest2 + ScrSize;
+			AttrDestBG = AttrDestFG + ScrSize;
+#if UNICODE_INTERNAL_BUFF
+			CodeDestW = (buff_char_t *)(AttrDestBG + ScrSize);
+#endif
 
-				SaveBuffX = NumOfColumns;
-				SaveBuffY = NumOfLines;
+			SaveBuffX = NumOfColumns;
+			SaveBuffY = NumOfLines;
 
-				SrcPtr = GetLinePtr(PageStart);
-				DestPtr = 0;
+			SrcPtr = GetLinePtr(PageStart);
+			DestPtr = 0;
 
-				for (i=0; i<NumOfLines; i++) {
-					memcpy(&CodeDest[DestPtr], &CodeBuff[SrcPtr], NumOfColumns);
-					memcpy(&AttrDest[DestPtr], &AttrBuff[SrcPtr], NumOfColumns);
-					memcpy(&AttrDest2[DestPtr], &AttrBuff2[SrcPtr], NumOfColumns);
-					memcpy(&AttrDestFG[DestPtr], &AttrBuffFG[SrcPtr], NumOfColumns);
-					memcpy(&AttrDestBG[DestPtr], &AttrBuffBG[SrcPtr], NumOfColumns);
-					SrcPtr = NextLinePtr(SrcPtr);
-					DestPtr += NumOfColumns;
-				}
+			for (i=0; i<NumOfLines; i++) {
+				memcpy(&CodeDest[DestPtr], &CodeBuff[SrcPtr], NumOfColumns);
+#if UNICODE_INTERNAL_BUFF
+				memcpyW(&CodeDestW[DestPtr], &CodeBuffW[SrcPtr], NumOfColumns);
+#endif
+				memcpy(&AttrDest[DestPtr], &AttrBuff[SrcPtr], NumOfColumns);
+				memcpy(&AttrDest2[DestPtr], &AttrBuff2[SrcPtr], NumOfColumns);
+				memcpy(&AttrDestFG[DestPtr], &AttrBuffFG[SrcPtr], NumOfColumns);
+				memcpy(&AttrDestBG[DestPtr], &AttrBuffBG[SrcPtr], NumOfColumns);
+				SrcPtr = NextLinePtr(SrcPtr);
+				DestPtr += NumOfColumns;
 			}
-			else {
-				GlobalFree(SaveBuff);
-				SaveBuff = NULL;
-			}
 		}
 	}
-	return;
+	_CrtCheckMemory();
 }
 
 void BuffRestoreScreen()
 {
 	PCHAR CodeSrc, AttrSrc, AttrSrc2, AttrSrcFG, AttrSrcBG;
+#if UNICODE_INTERNAL_BUFF
+	buff_char_t *CodeSrcW;
+#endif
 	LONG ScrSize;
 	LONG SrcPtr, DestPtr;
 	int i, CopyX, CopyY;
 
+	_CrtCheckMemory();
 	if (SaveBuff != NULL) {
-		if ((CodeSrc=GlobalLock(SaveBuff)) != NULL) {
-			ScrSize = SaveBuffX * SaveBuffY;
+		CodeSrc = SaveBuff;
+		ScrSize = SaveBuffX * SaveBuffY;
 
-			AttrSrc = CodeSrc + ScrSize;
-			AttrSrc2 = AttrSrc + ScrSize;
-			AttrSrcFG = AttrSrc2 + ScrSize;
-			AttrSrcBG = AttrSrcFG + ScrSize;
+		AttrSrc = CodeSrc + ScrSize;
+		AttrSrc2 = AttrSrc + ScrSize;
+		AttrSrcFG = AttrSrc2 + ScrSize;
+		AttrSrcBG = AttrSrcFG + ScrSize;
+#if UNICODE_INTERNAL_BUFF
+		CodeSrcW = (buff_char_t*)(AttrSrcBG + ScrSize);
+#endif
 
-			CopyX = (SaveBuffX > NumOfColumns) ? NumOfColumns : SaveBuffX;
-			CopyY = (SaveBuffY > NumOfLines) ? NumOfLines : SaveBuffY;
+		CopyX = (SaveBuffX > NumOfColumns) ? NumOfColumns : SaveBuffX;
+		CopyY = (SaveBuffY > NumOfLines) ? NumOfLines : SaveBuffY;
 
-			SrcPtr = 0;
-			DestPtr = GetLinePtr(PageStart);
+		SrcPtr = 0;
+		DestPtr = GetLinePtr(PageStart);
 
-			for (i=0; i<CopyY; i++) {
-				memcpy(&CodeBuff[DestPtr], &CodeSrc[SrcPtr], CopyX);
-				memcpy(&AttrBuff[DestPtr], &AttrSrc[SrcPtr], CopyX);
-				memcpy(&AttrBuff2[DestPtr], &AttrSrc2[SrcPtr], CopyX);
-				memcpy(&AttrBuffFG[DestPtr], &AttrSrcFG[SrcPtr], CopyX);
-				memcpy(&AttrBuffBG[DestPtr], &AttrSrcBG[SrcPtr], CopyX);
-				if (AttrBuff[DestPtr+CopyX-1] & AttrKanji) {
-					CodeBuff[DestPtr+CopyX-1] = ' ';
-					AttrBuff[DestPtr+CopyX-1] ^= AttrKanji;
-				}
-				SrcPtr += SaveBuffX;
-				DestPtr = NextLinePtr(DestPtr);
+		for (i=0; i<CopyY; i++) {
+			memcpy(&CodeBuff[DestPtr], &CodeSrc[SrcPtr], CopyX);
+#if UNICODE_INTERNAL_BUFF
+			memcpyW(&CodeBuffW[DestPtr], &CodeSrcW[SrcPtr], CopyX);
+#endif
+			memcpy(&AttrBuff[DestPtr], &AttrSrc[SrcPtr], CopyX);
+			memcpy(&AttrBuff2[DestPtr], &AttrSrc2[SrcPtr], CopyX);
+			memcpy(&AttrBuffFG[DestPtr], &AttrSrcFG[SrcPtr], CopyX);
+			memcpy(&AttrBuffBG[DestPtr], &AttrSrcBG[SrcPtr], CopyX);
+			if (AttrBuff[DestPtr+CopyX-1] & AttrKanji) {
+				CodeBuff[DestPtr+CopyX-1] = ' ';
+#if UNICODE_INTERNAL_BUFF
+				BuffSetChar(&CodeBuffW[DestPtr+CopyX-1], 0x20, 'H');
+#endif
+				AttrBuff[DestPtr+CopyX-1] ^= AttrKanji;
 			}
-			BuffUpdateRect(WinOrgX,WinOrgY,WinOrgX+WinWidth-1,WinOrgY+WinHeight-1);
+			SrcPtr += SaveBuffX;
+			DestPtr = NextLinePtr(DestPtr);
 		}
+		BuffUpdateRect(WinOrgX,WinOrgY,WinOrgX+WinWidth-1,WinOrgY+WinHeight-1);
 
-		GlobalFree(SaveBuff);
+		free(SaveBuff);
 		SaveBuff = NULL;
 	}
-	return;
+	_CrtCheckMemory();
 }
 
-void BuffDiscardSavedScreen() {
+void BuffDiscardSavedScreen()
+{
 	if (SaveBuff != NULL) {
-		GlobalFree(SaveBuff);
+		free(SaveBuff);
 		SaveBuff = NULL;
 	}
+	_CrtCheckMemory();
 }
 
 void BuffSelectedEraseCurToEnd()
@@ -3809,6 +4532,9 @@
 		for (j = TmpPtr + offset; j < TmpPtr + NumOfColumns - offset; j++) {
 			if (!(AttrBuff2[j] & Attr2Protect)) {
 				CodeBuff[j] = 0x20;
+#if UNICODE_INTERNAL_BUFF
+				BuffSetChar(&CodeBuffW[j], 0x20, 'H');
+#endif
 				AttrBuff[j] &= AttrSgrMask;
 			}
 		}
@@ -3847,6 +4573,9 @@
 		for (j = TmpPtr; j < TmpPtr + offset; j++) {
 			if (!(AttrBuff2[j] & Attr2Protect)) {
 				CodeBuff[j] = 0x20;
+#if UNICODE_INTERNAL_BUFF
+				BuffSetChar(&CodeBuffW[j], 0x20, 'H');
+#endif
 				AttrBuff[j] &= AttrSgrMask;
 			}
 		}
@@ -3887,6 +4616,9 @@
 		    ((AttrBuff[Ptr+XStart-1] & AttrKanji) != 0) &&
 		    ((AttrBuff2[Ptr+XStart-1] & Attr2Protect) == 0)) {
 			CodeBuff[Ptr+XStart-1] = 0x20;
+#if UNICODE_INTERNAL_BUFF
+			BuffSetChar(&CodeBuffW[Ptr+XStart-1], 0x20, 'H');
+#endif
 			AttrBuff[Ptr+XStart-1] &= AttrSgrMask;
 		}
 		if ((XStart+C<NumOfColumns) &&
@@ -3893,11 +4625,17 @@
 		    ((AttrBuff[Ptr+XStart+C-1] & AttrKanji) != 0) &&
 		    ((AttrBuff2[Ptr+XStart+C-1] & Attr2Protect) == 0)) {
 			CodeBuff[Ptr+XStart+C] = 0x20;
+#if UNICODE_INTERNAL_BUFF
+			BuffSetChar(&CodeBuffW[Ptr+XStart+C], 0x20, 'H');
+#endif
 			AttrBuff[Ptr+XStart+C] &= AttrSgrMask;
 		}
 		for (j=Ptr+XStart; j<Ptr+XStart+C; j++) {
 			if (!(AttrBuff2[j] & Attr2Protect)) {
 				CodeBuff[j] = 0x20;
+#if UNICODE_INTERNAL_BUFF
+				BuffSetChar(&CodeBuffW[j], 0x20, 'H');
+#endif
 				AttrBuff[j] &= AttrSgrMask;
 			}
 		}
@@ -3959,22 +4697,37 @@
 
 		if (AttrBuff[LPtr+CursorRightM] & AttrKanji) {
 			CodeBuff[LPtr+CursorRightM] = 0x20;
+#if UNICODE_INTERNAL_BUFF
+			BuffSetChar(&CodeBuffW[LPtr+CursorRightM], 0x20, 'H');
+#endif
 			AttrBuff[LPtr+CursorRightM] &= ~AttrKanji;
 			if (CursorRightM < NumOfColumns-1) {
 				CodeBuff[LPtr+CursorRightM+1] = 0x20;
+#if UNICODE_INTERNAL_BUFF
+				BuffSetChar(&CodeBuffW[LPtr+CursorRightM+1], 0x20, 'H');
+#endif
 			}
 		}
 
 		if (AttrBuff[Ptr+count-1] & AttrKanji) {
 			CodeBuff[Ptr+count] = 0x20;
+#if UNICODE_INTERNAL_BUFF
+			BuffSetChar(&CodeBuffW[Ptr+count], 0x20, 'H');
+#endif
 		}
 
 		if (CursorLeftM > 0 && AttrBuff[Ptr-1] & AttrKanji) {
 			CodeBuff[Ptr-1] = 0x20;
+#if UNICODE_INTERNAL_BUFF
+			BuffSetChar(&CodeBuffW[Ptr-1], 0x20, 'H');
+#endif
 			AttrBuff[Ptr-1] &= ~AttrKanji;
 		}
 
 		memmove(&(CodeBuff[Ptr]),   &(CodeBuff[Ptr+count]),   MoveLen);
+#if UNICODE_INTERNAL_BUFF
+		memmoveW(&(CodeBuffW[Ptr]),   &(CodeBuffW[Ptr+count]),   MoveLen);
+#endif
 		memmove(&(AttrBuff[Ptr]),   &(AttrBuff[Ptr+count]),   MoveLen);
 		memmove(&(AttrBuff2[Ptr]),  &(AttrBuff2[Ptr+count]),  MoveLen);
 		memmove(&(AttrBuffFG[Ptr]), &(AttrBuffFG[Ptr+count]), MoveLen);
@@ -3981,6 +4734,9 @@
 		memmove(&(AttrBuffBG[Ptr]), &(AttrBuffBG[Ptr+count]), MoveLen);
 
 		memset(&(CodeBuff[Ptr+MoveLen]),   0x20,             count);
+#if UNICODE_INTERNAL_BUFF
+		memsetW(&(CodeBuffW[Ptr+MoveLen]),   0x20,             count);
+#endif
 		memset(&(AttrBuff[Ptr+MoveLen]),   AttrDefault,      count);
 		memset(&(AttrBuff2[Ptr+MoveLen]),  CurCharAttr.Attr2 & Attr2ColorMask, count);
 		memset(&(AttrBuffFG[Ptr+MoveLen]), CurCharAttr.Fore, count);
@@ -4006,15 +4762,27 @@
 
 		if (CursorRightM < NumOfColumns-1 && AttrBuff[LPtr+CursorRightM] & AttrKanji) {
 			CodeBuff[LPtr+CursorRightM+1] = 0x20;
+#if UNICODE_INTERNAL_BUFF
+			BuffSetChar(&CodeBuffW[LPtr+CursorRightM+1], 0x20, 'H');
+#endif
 		}
 
 		if (CursorLeftM > 0 && AttrBuff[Ptr-1] & AttrKanji) {
 			CodeBuff[Ptr-1] = 0x20;
+#if UNICODE_INTERNAL_BUFF
+			BuffSetChar(&CodeBuffW[Ptr-1], 0x20, 'H');
+#endif
 			AttrBuff[Ptr-1] &= ~AttrKanji;
 			CodeBuff[Ptr] = 0x20;
+#if UNICODE_INTERNAL_BUFF
+			BuffSetChar(&CodeBuffW[Ptr], 0x20, 'H');
+#endif
 		}
 
 		memmove(&(CodeBuff[Ptr+count]),   &(CodeBuff[Ptr]),   MoveLen);
+#if UNICODE_INTERNAL_BUFF
+		memmoveW(&(CodeBuffW[Ptr+count]),   &(CodeBuffW[Ptr]),   MoveLen);
+#endif
 		memmove(&(AttrBuff[Ptr+count]),   &(AttrBuff[Ptr]),   MoveLen);
 		memmove(&(AttrBuff2[Ptr+count]),  &(AttrBuff2[Ptr]),  MoveLen);
 		memmove(&(AttrBuffFG[Ptr+count]), &(AttrBuffFG[Ptr]), MoveLen);
@@ -4021,6 +4789,9 @@
 		memmove(&(AttrBuffBG[Ptr+count]), &(AttrBuffBG[Ptr]), MoveLen);
 
 		memset(&(CodeBuff[Ptr]),   0x20,             count);
+#if UNICODE_INTERNAL_BUFF
+		memsetW(&(CodeBuffW[Ptr]),   0x20,             count);
+#endif
 		memset(&(AttrBuff[Ptr]),   AttrDefault,      count);
 		memset(&(AttrBuff2[Ptr]),  CurCharAttr.Attr2 & Attr2ColorMask, count);
 		memset(&(AttrBuffFG[Ptr]), CurCharAttr.Fore, count);
@@ -4028,6 +4799,9 @@
 
 		if (AttrBuff[LPtr+CursorRightM] & AttrKanji) {
 			CodeBuff[LPtr+CursorRightM] = 0x20;
+#if UNICODE_INTERNAL_BUFF
+			BuffSetChar(&CodeBuffW[LPtr+CursorRightM], 0x20, 'H');
+#endif
 			AttrBuff[LPtr+CursorRightM] &= ~AttrKanji;
 		}
 
@@ -4096,3 +4870,97 @@
 
 	return Result;
 }
+
+/* \x83f\x83o\x83O\x97p */
+void BuffCheckMouse(int Xw, int Yw, wchar_t *buf, size_t buf_size)
+{
+	int X, Y;
+	int ScreenY;
+	LONG TmpPtr;
+	BOOL Right;
+	unsigned char c;
+	char cs[4];
+#if UNICODE_INTERNAL_BUFF
+	char32_t u32;
+	wchar_t wcs[4];
+#endif
+
+	DispConvWinToScreen(Xw, Yw, &X, &ScreenY, &Right);
+	Y = PageStart + ScreenY;
+
+	if (X < 0)
+		X = 0;
+	else if (X > NumOfColumns)
+		X = NumOfColumns;
+	if (Y < 0)
+		Y = 0;
+	else if (Y >= BuffEnd)
+		Y = BuffEnd - 1;
+
+	TmpPtr = GetLinePtr(Y);
+	LockBuffer();
+
+	c = (unsigned char)CodeBuff[TmpPtr+X];
+	if (c < 0x20) {
+		cs[0] = '.';
+		cs[1] = 0;
+	} else if (!_ismbblead(c)) {
+		cs[0] = c;
+		cs[1] = 0;
+	} else {
+		cs[0] = c;
+		cs[1] = CodeBuff[TmpPtr+X+1];
+		cs[2] = 0;
+	}
+
+#if UNICODE_INTERNAL_BUFF
+	{
+		const wchar_t wc1 = CodeBuffW[TmpPtr+X].wc2[0];
+		const wchar_t wc2 = CodeBuffW[TmpPtr+X+1].wc2[1];
+		u32 = CodeBuffW[TmpPtr+X].u32;
+		if (u32 < 0x20) {
+			wcs[0] = '.';
+			wcs[1] = 0;
+			wcs[2] = 0;
+		} else if (u32 < 0x10000) {
+			wcs[0] = wc1;
+			wcs[1] = 0;
+			wcs[2] = 0;
+		} else {
+			// \x83T\x83\x8D\x83Q\x81[\x83g\x83y\x83A
+			wcs[0] = wc1;
+			wcs[1] = wc2;
+			wcs[2] = 0;
+		}
+	}
+#endif
+
+	swprintf_s(buf, buf_size,
+			   L"ch(%d,%d(%d)) px(%d,%d)\n"
+			   L"attr      0x%02x\n"
+			   L"attr2     0x%02x\n"
+			   L"attrFore  0x%02x\n"
+			   L"attrBack  0x%02x\n"
+			   L"CodeLine  0x%02x('%S')"
+#if UNICODE_INTERNAL_BUFF
+			   L"\n"
+			   L"CodeLineW 0+%06x('%s')"
+#endif
+			   ,
+			   X, ScreenY, Y,
+			   Xw, Yw,
+			   AttrBuff[TmpPtr+X],
+			   AttrBuff2[TmpPtr+X],
+			   AttrBuffFG[TmpPtr+X],
+			   AttrBuffBG[TmpPtr+X],
+			   c, cs
+#if UNICODE_INTERNAL_BUFF
+			   , u32, wcs
+#endif
+		);
+#if 0
+	OutputDebugPrintfW(buf);
+#endif
+
+	UnlockBuffer();
+}

Modified: branches/unicode_buf/teraterm/teraterm/buffer.h
===================================================================
--- branches/unicode_buf/teraterm/teraterm/buffer.h	2019-06-25 13:58:11 UTC (rev 7809)
+++ branches/unicode_buf/teraterm/teraterm/buffer.h	2019-06-25 14:05:37 UTC (rev 7810)
@@ -63,6 +63,7 @@
 void BuffDumpCurrentLine(BYTE TERM);
 void BuffPutChar(BYTE b, TCharAttr Attr, BOOL Insert);
 void BuffPutKanji(WORD w, TCharAttr Attr, BOOL Insert);
+char BuffPutUnicode(unsigned int uc, TCharAttr Attr, BOOL Insert);
 void BuffUpdateRect(int XStart, int YStart, int XEnd, int YEnd);
 void UpdateStr();
 void UpdateStrUnicode(void);
@@ -108,6 +109,7 @@
 int BuffGetCurrentLineData(char *buf, int bufsize);
 int BuffGetAnyLineData(int offset_y, char *buf, int bufsize);
 BOOL BuffCheckMouseOnURL(int Xw, int Yw);
+void BuffCheckMouse(int Xw, int Yw, wchar_t *buf, size_t buf_size);
 
 extern int StatusLine;
 extern int CursorTop, CursorBottom, CursorLeftM, CursorRightM;

Modified: branches/unicode_buf/teraterm/teraterm/ttermpro.v10.vcxproj
===================================================================
--- branches/unicode_buf/teraterm/teraterm/ttermpro.v10.vcxproj	2019-06-25 13:58:11 UTC (rev 7809)
+++ branches/unicode_buf/teraterm/teraterm/ttermpro.v10.vcxproj	2019-06-25 14:05:37 UTC (rev 7810)
@@ -181,6 +181,7 @@
     <ClCompile Include="vtwin.cpp" />
     <ClCompile Include="winjump.c" />
     <ClCompile Include="WSAAsyncGetAddrInfo.c" />
+    <ClCompile Include="unicode.cpp" />
     <ClInclude Include="..\ttpdlg\dlg_res.h" />
     <ClCompile Include="../ttpdlg/ttdlg.c" />
     <ClInclude Include="../ttpdlg/ttdlg.h" />
@@ -241,6 +242,7 @@
     <ClInclude Include="vtdisp.h" />
     <ClInclude Include="vtterm.h" />
     <ClInclude Include="vtwin.h" />
+    <ClInclude Include="unicode.h" />
   </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="..\svnrev\svnrev.v10.vcxproj">

Modified: branches/unicode_buf/teraterm/teraterm/ttermpro.v11.vcxproj
===================================================================
--- branches/unicode_buf/teraterm/teraterm/ttermpro.v11.vcxproj	2019-06-25 13:58:11 UTC (rev 7809)
+++ branches/unicode_buf/teraterm/teraterm/ttermpro.v11.vcxproj	2019-06-25 14:05:37 UTC (rev 7810)
@@ -178,6 +178,7 @@
     <ClCompile Include="vtwin.cpp" />
     <ClCompile Include="winjump.c" />
     <ClCompile Include="WSAAsyncGetAddrInfo.c" />
+    <ClCompile Include="unicode.cpp" />
     <ClInclude Include="..\ttpdlg\dlg_res.h" />
     <ClCompile Include="../ttpdlg/ttdlg.c" />
     <ClInclude Include="../ttpdlg/ttdlg.h" />
@@ -238,6 +239,7 @@
     <ClInclude Include="vtdisp.h" />
     <ClInclude Include="vtterm.h" />
     <ClInclude Include="vtwin.h" />
+    <ClInclude Include="unicode.h" />
   </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="..\svnrev\svnrev.v11.vcxproj">

Modified: branches/unicode_buf/teraterm/teraterm/ttermpro.v12.vcxproj
===================================================================
--- branches/unicode_buf/teraterm/teraterm/ttermpro.v12.vcxproj	2019-06-25 13:58:11 UTC (rev 7809)
+++ branches/unicode_buf/teraterm/teraterm/ttermpro.v12.vcxproj	2019-06-25 14:05:37 UTC (rev 7810)
@@ -178,6 +178,7 @@
     <ClCompile Include="vtwin.cpp" />
     <ClCompile Include="winjump.c" />
     <ClCompile Include="WSAAsyncGetAddrInfo.c" />
+    <ClCompile Include="unicode.cpp" />
     <ClInclude Include="..\ttpdlg\dlg_res.h" />
     <ClCompile Include="../ttpdlg/ttdlg.c" />
     <ClInclude Include="../ttpdlg/ttdlg.h" />
@@ -238,6 +239,7 @@
     <ClInclude Include="vtdisp.h" />
     <ClInclude Include="vtterm.h" />
     <ClInclude Include="vtwin.h" />
+    <ClInclude Include="unicode.h" />
   </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="..\svnrev\svnrev.v12.vcxproj">

Modified: branches/unicode_buf/teraterm/teraterm/ttermpro.v14.vcxproj
===================================================================
--- branches/unicode_buf/teraterm/teraterm/ttermpro.v14.vcxproj	2019-06-25 13:58:11 UTC (rev 7809)
+++ branches/unicode_buf/teraterm/teraterm/ttermpro.v14.vcxproj	2019-06-25 14:05:37 UTC (rev 7810)
@@ -180,6 +180,7 @@
     <ClCompile Include="vtwin.cpp" />
     <ClCompile Include="winjump.c" />
     <ClCompile Include="WSAAsyncGetAddrInfo.c" />
+    <ClCompile Include="unicode.cpp" />
     <ClInclude Include="..\ttpdlg\dlg_res.h" />
     <ClCompile Include="../ttpdlg/ttdlg.c" />
     <ClInclude Include="../ttpdlg/ttdlg.h" />
@@ -240,6 +241,7 @@
     <ClInclude Include="vtdisp.h" />
     <ClInclude Include="vtterm.h" />
     <ClInclude Include="vtwin.h" />
+    <ClInclude Include="unicode.h" />
   </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="..\svnrev\svnrev.v14.vcxproj">

Modified: branches/unicode_buf/teraterm/teraterm/ttermpro.v15.vcxproj
===================================================================
--- branches/unicode_buf/teraterm/teraterm/ttermpro.v15.vcxproj	2019-06-25 13:58:11 UTC (rev 7809)
+++ branches/unicode_buf/teraterm/teraterm/ttermpro.v15.vcxproj	2019-06-25 14:05:37 UTC (rev 7810)
@@ -183,6 +183,7 @@
     <ClCompile Include="vtwin.cpp" />
     <ClCompile Include="winjump.c" />
     <ClCompile Include="WSAAsyncGetAddrInfo.c" />
+    <ClCompile Include="unicode.cpp" />
     <ClInclude Include="../ttpdlg/dlg_res.h" />
     <ClCompile Include="../ttpdlg/ttdlg.c" />
     <ClInclude Include="../ttpdlg/ttdlg.h" />
@@ -243,6 +244,7 @@
     <ClInclude Include="vtdisp.h" />
     <ClInclude Include="vtterm.h" />
     <ClInclude Include="vtwin.h" />
+    <ClInclude Include="unicode.h" />
   </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="..\svnrev\svnrev.v15.vcxproj">

Modified: branches/unicode_buf/teraterm/teraterm/ttermpro.v16.vcxproj
===================================================================
--- branches/unicode_buf/teraterm/teraterm/ttermpro.v16.vcxproj	2019-06-25 13:58:11 UTC (rev 7809)
+++ branches/unicode_buf/teraterm/teraterm/ttermpro.v16.vcxproj	2019-06-25 14:05:37 UTC (rev 7810)
@@ -183,6 +183,7 @@
     <ClCompile Include="vtwin.cpp" />
     <ClCompile Include="winjump.c" />
     <ClCompile Include="WSAAsyncGetAddrInfo.c" />
+    <ClCompile Include="unicode.cpp" />
     <ClInclude Include="../ttpdlg/dlg_res.h" />
     <ClCompile Include="../ttpdlg/ttdlg.c" />
     <ClInclude Include="../ttpdlg/ttdlg.h" />
@@ -243,6 +244,7 @@
     <ClInclude Include="vtdisp.h" />
     <ClInclude Include="vtterm.h" />
     <ClInclude Include="vtwin.h" />
+    <ClInclude Include="unicode.h" />
   </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="..\svnrev\svnrev.v16.vcxproj">
@@ -277,4 +279,4 @@
       <UserProperties RESOURCE_FILE="ttermpro.rc" />
     </VisualStudio>
   </ProjectExtensions>
-</Project>
\ No newline at end of file
+</Project>

Modified: branches/unicode_buf/teraterm/teraterm/ttermpro.v9.vcproj
===================================================================
--- branches/unicode_buf/teraterm/teraterm/ttermpro.v9.vcproj	2019-06-25 13:58:11 UTC (rev 7809)
+++ branches/unicode_buf/teraterm/teraterm/ttermpro.v9.vcproj	2019-06-25 14:05:37 UTC (rev 7810)
@@ -605,6 +605,14 @@
 				RelativePath=".\ttdialog.h"
 				>
 			</File>
+			<File
+				RelativePath="unicode.h"
+				>
+			</File>
+			<File
+				RelativePath="unicode.cpp"
+				>
+			</File>
 		</Filter>
 	</Files>
 	<Globals>

Modified: branches/unicode_buf/teraterm/teraterm/ttermpro.vcproj
===================================================================
--- branches/unicode_buf/teraterm/teraterm/ttermpro.vcproj	2019-06-25 13:58:11 UTC (rev 7809)
+++ branches/unicode_buf/teraterm/teraterm/ttermpro.vcproj	2019-06-25 14:05:37 UTC (rev 7810)
@@ -606,6 +606,14 @@
 				RelativePath=".\ttdialog.h"
 				>
 			</File>
+			<File
+				RelativePath="unicode.h"
+				>
+			</File>
+			<File
+				RelativePath="unicode.cpp"
+				>
+			</File>
 		</Filter>
 	</Files>
 	<Globals>

Added: branches/unicode_buf/teraterm/teraterm/unicode/get_combine_table.md
===================================================================
--- branches/unicode_buf/teraterm/teraterm/unicode/get_combine_table.md	                        (rev 0)
+++ branches/unicode_buf/teraterm/teraterm/unicode/get_combine_table.md	2019-06-25 14:05:37 UTC (rev 7810)
@@ -0,0 +1,21 @@
+
+# combining charactors
+
+- 結合文字
+- 濁点など、前のもじとくっつける
+  https://en.m.wikipedia.org/wiki/Combining_character
+
+# テーブルの作り方
+
+- あらかじめ NamesList.txt をダウンロードしておく
+- 次のように実行する
+  - `perl get_combine_table.pl > unicode_combine.tbl`
+
+## original data
+
+https://unicode.org/Public/UNIDATA/NamesList.txt
+
+    The Unicode Standard 12.1.0
+    Unicode 12.1.0 final names list.
+
+

Added: branches/unicode_buf/teraterm/teraterm/unicode/get_combine_table.pl
===================================================================
--- branches/unicode_buf/teraterm/teraterm/unicode/get_combine_table.pl	                        (rev 0)
+++ branches/unicode_buf/teraterm/teraterm/unicode/get_combine_table.pl	2019-06-25 14:05:37 UTC (rev 7810)
@@ -0,0 +1,32 @@
+#!/usr/bin/perl
+use utf8;
+
+open(FILE, "NamesList.txt") || die "Cannot open width file.";
+$ostart = 0;
+$oend = 0;
+while($a = <FILE>) {
+	if ($a =~ /^([0-9A-F]+)\s+(.*)$/) {
+		$start = hex $1;
+		$name = $2;
+		if ($name =~ /COMBINING/ || $name =~ /EMOJI MODIFIER/) {
+			if ($ostart == 0) {
+				$ostart = $start;
+				$oend = $start;
+				$comment = $name;
+			} else {
+				if ($oend + 1 == $start) {
+					$oend = $start;
+				}
+			}
+		} else {
+			if ($ostart != 0) {
+				printf("{ 0x%06x, 0x%06x },		// '%s'\n", $ostart, $oend, $comment);
+				$ostart = 0;
+			}
+		}
+	}
+}
+if ($ostart != 0) {
+	printf("{ 0x%06x, 0x%06x },\n", $ostart, $oend);
+}
+

Added: branches/unicode_buf/teraterm/teraterm/unicode/get_f_w_a.md
===================================================================
--- branches/unicode_buf/teraterm/teraterm/unicode/get_f_w_a.md	                        (rev 0)
+++ branches/unicode_buf/teraterm/teraterm/unicode/get_f_w_a.md	2019-06-25 14:05:37 UTC (rev 7810)
@@ -0,0 +1,21 @@
+
+# unicodeの全角半角
+
+- unicode.orgにある East Asian Width に基づいて決める
+
+# テーブルの作り方
+
+- あらかじめ EastAsianWidth.txt をダウンロードしておく
+- 次のように実行
+  - `perl get_f_w_a.pl > unicode_asian_width.tbl`
+
+## East Asian Width について
+
+https://ja.wikipedia.org/wiki/%E6%9D%B1%E3%82%A2%E3%82%B8%E3%82%A2%E3%81%AE%E6%96%87%E5%AD%97%E5%B9%85
+
+## original data
+
+http://www.unicode.org/Public/UCD/latest/ucd/EastAsianWidth.txt
+
+    EastAsianWidth-12.1.0.txt
+    Date: 2019-03-31, 22:01:58 GMT [KW, LI]

Added: branches/unicode_buf/teraterm/teraterm/unicode/get_f_w_a.pl
===================================================================
--- branches/unicode_buf/teraterm/teraterm/unicode/get_f_w_a.pl	                        (rev 0)
+++ branches/unicode_buf/teraterm/teraterm/unicode/get_f_w_a.pl	2019-06-25 14:05:37 UTC (rev 7810)
@@ -0,0 +1,41 @@
+#!/usr/bin/perl
+use utf8;
+
+open(FILE, "EastAsianWidth.txt") || die "Cannot open width file.";
+$ostart = -1;
+while($a = <FILE>) {
+	if ($a =~ /^([0-9A-F]+)\.\.([0-9A-F]+);([A-Za-z]+)/) {
+		$start = hex $1;
+		$end = hex $2;
+		$type = $3;
+	}
+	elsif ($a =~ /^([0-9A-F]+);([A-Za-z]+)/) {
+		$start = hex $1;
+		$end = hex $1;
+		$type = $2;
+	} else {
+		next;
+	}
+
+#	printf("-{ 0x%06x, 0x%06x, $type },\n", $start, $end);
+
+	if ($otype eq $type
+		#&& $oend+1 == $start	# 未定義部を飛ばしてつなげる
+		)
+	{
+		# 1つ前とつなげる
+		$oend = $end;
+	} elsif ($ostart == -1) {
+		$ostart = $start;
+		$oend = $end;
+		$otype = $type;
+	} else {
+		if (($otype eq "W") || ($otype eq "F") || ($otype eq "A")) {
+			printf("{ 0x%06x, 0x%06x, '$otype' },\n", $ostart, $oend);
+		}
+		$ostart = $start;
+		$oend = $end;
+		$otype = $type;
+	}
+}
+printf("{ 0x%06x, 0x%06x, '$type' },\n", $ostart, $oend);

Added: branches/unicode_buf/teraterm/teraterm/unicode.cpp
===================================================================
--- branches/unicode_buf/teraterm/teraterm/unicode.cpp	                        (rev 0)
+++ branches/unicode_buf/teraterm/teraterm/unicode.cpp	2019-06-25 14:05:37 UTC (rev 7810)
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#pragma warning(push, 0)
+#include <stdlib.h>
+#include <stdio.h>
+#pragma warning(pop)
+
+#include "unicode.h"
+
+/**
+ *	East_Asian_Width \x8EQ\x8Dl\x93\xC1\x90\xAB \x8E擾
+ *
+ *	@retval	'F'		Fullwidth \x91S\x8Ap
+ *	@retval	'W'		Wide \x8DL
+ *	@retval	'A'		Ambiguous \x9EB\x96\x86
+ *	@retval	'H'		\x94\xBC\x8Ap\x88\xB5\x82\xA2 (H(Halfwidth \x94\xBC\x8Ap) or Na(Narrow \x8B\xB7) or N(Neutral \x92\x86\x97\xA7))
+ */
+char UnicodeGetWidthProperty(unsigned long u32)
+{
+	typedef struct {
+		unsigned long code_from;
+		unsigned long code_to;
+		char property;
+	} east_asian_width_map_t;
+	const static east_asian_width_map_t east_asian_width_map[] = {
+#include "unicode_asian_width.tbl"
+	};
+	const east_asian_width_map_t *table = east_asian_width_map;
+	const size_t table_size = _countof(east_asian_width_map);
+
+	if (u32 < east_asian_width_map[0].code_from) {
+		return 'H';
+	}
+	if (east_asian_width_map[table_size-1].code_to < u32) {
+		return 'H';
+	}
+
+	size_t low = 0;
+	size_t high = table_size - 1;
+	while (low < high) {
+		size_t mid = (low + high) / 2;
+		if (table[mid].code_from <= u32 && u32 <= table[mid].code_to) {
+			return table[mid].property;
+		} else if (table[mid].code_to < u32) {
+			low = mid + 1;
+		} else {
+			high = mid;
+		}
+	}
+	// \x83e\x81[\x83u\x83\x8B\x82͈̔͊O
+	return 'H';
+}
+
+/*
+ * \x8C\x8B\x8D\x87\x95\xB6\x8E\x9A\x82\xA9\x8C\x9F\x8D\xB8\x82\xB7\x82\xE9
+ *		EMOJI MODIFIER \x82\xE0\x8C\x8B\x8D\x87\x95\xB6\x8E\x9A\x82Ƃ\xB5\x82Ĉ\xB5\x82\xA4
+ *
+ *	@retval	0		\x8C\x8B\x8D\x87\x95\xB6\x8E\x9A\x82ł͂Ȃ\xA2
+ *	@retval	1		\x8C\x8B\x8D\x87\x95\xB6\x8E\x9A\x82ł\xA0\x82\xE9
+ */
+int UnicodeIsCombiningCharacter(unsigned long u32)
+{
+	typedef struct {
+		unsigned long code_from;
+		unsigned long code_to;
+	} CombiningCharacterList_t;
+	const static CombiningCharacterList_t CombiningCharacterList[] = {
+#include "unicode_combine.tbl"
+	};
+	const CombiningCharacterList_t *table = CombiningCharacterList;
+	const size_t table_size = _countof(CombiningCharacterList);
+	if (u32 < CombiningCharacterList[0].code_from) {
+		return 0;
+	}
+	if (u32 > CombiningCharacterList[table_size-1].code_to) {
+		return 0;
+	}
+	size_t low = 0;
+	size_t high = table_size - 1;
+	while (low <= high) {
+		size_t mid = (low + high) / 2;
+		if (table[mid].code_from <= u32 && u32 <= table[mid].code_to) {
+			return 1;
+		} else if (table[mid].code_to < u32) {
+			low = mid + 1;
+		} else {
+			high = mid - 1;
+		}
+	}
+	// \x83e\x81[\x83u\x83\x8B\x82͈̔͊O
+	return 0;
+}
+
+/**
+ *	\x88ّ̎\x9A\x83Z\x83\x8C\x83N\x83^\x82\xA9\x83`\x83F\x83b\x83N\x82\xB7\x82\xE9
+ *
+ *	@retval	0		\x88ّ̎\x9A\x83Z\x83\x8C\x83N\x83^\x82ł͂Ȃ\xA2
+ *	@retval	1		\x88ّ̎\x9A\x83Z\x83\x8C\x83N\x83^\x82ł\xA0\x82\xE9
+ */
+int UnicodeIsVariationSelector(unsigned long u32)
+{
+	if ((0x00180b <= u32 && u32 <= 0x00180d) ||	// FVS (Mongolian Free Variation Selector)
+		(0x00fe00 <= u32 && u32 <= 0x00fe0f) ||	// SVS VS1\x81`VS16
+		(0x0e0100 <= u32 && u32 <= 0x0e01ef))	// IVS VS17\x81`VS256
+	{
+		return 1;
+	}
+	return 0;
+}
+
+
+#if 0
+int main(int, char *[])
+{
+	static const unsigned long codes[] = {
+#if 0
+		0, 1, 0x7f,
+		0x80,
+		0x0e00ff,
+		0x0e0100,
+		0x10fffd,
+#endif
+		0x10fffe,
+	};
+
+	for (size_t i = 0; i < _countof(codes); i++) {
+		unsigned long code = codes[i];
+		printf("U+%06lx %c\n", code, UnicodeGetWidthProperty(code));
+	}
+	return 0;
+}
+#endif

Added: branches/unicode_buf/teraterm/teraterm/unicode.h
===================================================================
--- branches/unicode_buf/teraterm/teraterm/unicode.h	                        (rev 0)
+++ branches/unicode_buf/teraterm/teraterm/unicode.h	2019-06-25 14:05:37 UTC (rev 7810)
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+char UnicodeGetWidthProperty(unsigned long u32);
+int UnicodeIsCombiningCharacter(unsigned long u32);
+int UnicodeIsVariationSelector(unsigned long u32);
+
+#ifdef __cplusplus
+}
+#endif

Added: branches/unicode_buf/teraterm/teraterm/unicode_asian_width.tbl
===================================================================
--- branches/unicode_buf/teraterm/teraterm/unicode_asian_width.tbl	                        (rev 0)
+++ branches/unicode_buf/teraterm/teraterm/unicode_asian_width.tbl	2019-06-25 14:05:37 UTC (rev 7810)
@@ -0,0 +1,256 @@
+{ 0x0000a1, 0x0000a1, 'A' },
+{ 0x0000a4, 0x0000a4, 'A' },
+{ 0x0000a7, 0x0000a8, 'A' },
+{ 0x0000aa, 0x0000aa, 'A' },
+{ 0x0000ad, 0x0000ae, 'A' },
+{ 0x0000b0, 0x0000b4, 'A' },
+{ 0x0000b6, 0x0000ba, 'A' },
+{ 0x0000bc, 0x0000bf, 'A' },
+{ 0x0000c6, 0x0000c6, 'A' },
+{ 0x0000d0, 0x0000d0, 'A' },
+{ 0x0000d7, 0x0000d8, 'A' },
+{ 0x0000de, 0x0000e1, 'A' },
+{ 0x0000e6, 0x0000e6, 'A' },
+{ 0x0000e8, 0x0000ea, 'A' },
+{ 0x0000ec, 0x0000ed, 'A' },
+{ 0x0000f0, 0x0000f0, 'A' },
+{ 0x0000f2, 0x0000f3, 'A' },
+{ 0x0000f7, 0x0000fa, 'A' },
+{ 0x0000fc, 0x0000fc, 'A' },
+{ 0x0000fe, 0x0000fe, 'A' },
+{ 0x000101, 0x000101, 'A' },
+{ 0x000111, 0x000111, 'A' },
+{ 0x000113, 0x000113, 'A' },
+{ 0x00011b, 0x00011b, 'A' },
+{ 0x000126, 0x000127, 'A' },
+{ 0x00012b, 0x00012b, 'A' },
+{ 0x000131, 0x000133, 'A' },
+{ 0x000138, 0x000138, 'A' },
+{ 0x00013f, 0x000142, 'A' },
+{ 0x000144, 0x000144, 'A' },
+{ 0x000148, 0x00014b, 'A' },
+{ 0x00014d, 0x00014d, 'A' },
+{ 0x000152, 0x000153, 'A' },
+{ 0x000166, 0x000167, 'A' },
+{ 0x00016b, 0x00016b, 'A' },
+{ 0x0001ce, 0x0001ce, 'A' },
+{ 0x0001d0, 0x0001d0, 'A' },
+{ 0x0001d2, 0x0001d2, 'A' },
+{ 0x0001d4, 0x0001d4, 'A' },
+{ 0x0001d6, 0x0001d6, 'A' },
+{ 0x0001d8, 0x0001d8, 'A' },
+{ 0x0001da, 0x0001da, 'A' },
+{ 0x0001dc, 0x0001dc, 'A' },
+{ 0x000251, 0x000251, 'A' },
+{ 0x000261, 0x000261, 'A' },
+{ 0x0002c4, 0x0002c4, 'A' },
+{ 0x0002c7, 0x0002c7, 'A' },
+{ 0x0002c9, 0x0002cb, 'A' },
+{ 0x0002cd, 0x0002cd, 'A' },
+{ 0x0002d0, 0x0002d0, 'A' },
+{ 0x0002d8, 0x0002db, 'A' },
+{ 0x0002dd, 0x0002dd, 'A' },
+{ 0x0002df, 0x0002df, 'A' },
+{ 0x000300, 0x00036f, 'A' },
+{ 0x000391, 0x0003a9, 'A' },
+{ 0x0003b1, 0x0003c1, 'A' },
+{ 0x0003c3, 0x0003c9, 'A' },
+{ 0x000401, 0x000401, 'A' },
+{ 0x000410, 0x00044f, 'A' },
+{ 0x000451, 0x000451, 'A' },
+{ 0x001100, 0x00115f, 'W' },
+{ 0x002010, 0x002010, 'A' },
+{ 0x002013, 0x002016, 'A' },
+{ 0x002018, 0x002019, 'A' },
+{ 0x00201c, 0x00201d, 'A' },
+{ 0x002020, 0x002022, 'A' },
+{ 0x002024, 0x002027, 'A' },
+{ 0x002030, 0x002030, 'A' },
+{ 0x002032, 0x002033, 'A' },
+{ 0x002035, 0x002035, 'A' },
+{ 0x00203b, 0x00203b, 'A' },
+{ 0x00203e, 0x00203e, 'A' },
+{ 0x002074, 0x002074, 'A' },
+{ 0x00207f, 0x00207f, 'A' },
+{ 0x002081, 0x002084, 'A' },
+{ 0x0020ac, 0x0020ac, 'A' },
+{ 0x002103, 0x002103, 'A' },
+{ 0x002105, 0x002105, 'A' },
+{ 0x002109, 0x002109, 'A' },
+{ 0x002113, 0x002113, 'A' },
+{ 0x002116, 0x002116, 'A' },
+{ 0x002121, 0x002122, 'A' },
+{ 0x002126, 0x002126, 'A' },
+{ 0x00212b, 0x00212b, 'A' },
+{ 0x002153, 0x002154, 'A' },
+{ 0x00215b, 0x00215e, 'A' },
+{ 0x002160, 0x00216b, 'A' },
+{ 0x002170, 0x002179, 'A' },
+{ 0x002189, 0x002189, 'A' },
+{ 0x002190, 0x002199, 'A' },
+{ 0x0021b8, 0x0021b9, 'A' },
+{ 0x0021d2, 0x0021d2, 'A' },
+{ 0x0021d4, 0x0021d4, 'A' },
+{ 0x0021e7, 0x0021e7, 'A' },
+{ 0x002200, 0x002200, 'A' },
+{ 0x002202, 0x002203, 'A' },
+{ 0x002207, 0x002208, 'A' },
+{ 0x00220b, 0x00220b, 'A' },
+{ 0x00220f, 0x00220f, 'A' },
+{ 0x002211, 0x002211, 'A' },
+{ 0x002215, 0x002215, 'A' },
+{ 0x00221a, 0x00221a, 'A' },
+{ 0x00221d, 0x002220, 'A' },
+{ 0x002223, 0x002223, 'A' },
+{ 0x002225, 0x002225, 'A' },
+{ 0x002227, 0x00222c, 'A' },
+{ 0x00222e, 0x00222e, 'A' },
+{ 0x002234, 0x002237, 'A' },
+{ 0x00223c, 0x00223d, 'A' },
+{ 0x002248, 0x002248, 'A' },
+{ 0x00224c, 0x00224c, 'A' },
+{ 0x002252, 0x002252, 'A' },
+{ 0x002260, 0x002261, 'A' },
+{ 0x002264, 0x002267, 'A' },
+{ 0x00226a, 0x00226b, 'A' },
+{ 0x00226e, 0x00226f, 'A' },
+{ 0x002282, 0x002283, 'A' },
+{ 0x002286, 0x002287, 'A' },
+{ 0x002295, 0x002295, 'A' },
+{ 0x002299, 0x002299, 'A' },
+{ 0x0022a5, 0x0022a5, 'A' },
+{ 0x0022bf, 0x0022bf, 'A' },
+{ 0x002312, 0x002312, 'A' },
+{ 0x00231a, 0x00231b, 'W' },
+{ 0x002329, 0x00232a, 'W' },
+{ 0x0023e9, 0x0023ec, 'W' },
+{ 0x0023f0, 0x0023f0, 'W' },
+{ 0x0023f3, 0x0023f3, 'W' },
+{ 0x002460, 0x0024e9, 'A' },
+{ 0x0024eb, 0x00254b, 'A' },
+{ 0x002550, 0x002573, 'A' },
+{ 0x002580, 0x00258f, 'A' },
+{ 0x002592, 0x002595, 'A' },
+{ 0x0025a0, 0x0025a1, 'A' },
+{ 0x0025a3, 0x0025a9, 'A' },
+{ 0x0025b2, 0x0025b3, 'A' },
+{ 0x0025b6, 0x0025b7, 'A' },
+{ 0x0025bc, 0x0025bd, 'A' },
+{ 0x0025c0, 0x0025c1, 'A' },
+{ 0x0025c6, 0x0025c8, 'A' },
+{ 0x0025cb, 0x0025cb, 'A' },
+{ 0x0025ce, 0x0025d1, 'A' },
+{ 0x0025e2, 0x0025e5, 'A' },
+{ 0x0025ef, 0x0025ef, 'A' },
+{ 0x0025fd, 0x0025fe, 'W' },
+{ 0x002605, 0x002606, 'A' },
+{ 0x002609, 0x002609, 'A' },
+{ 0x00260e, 0x00260f, 'A' },
+{ 0x002614, 0x002615, 'W' },
+{ 0x00261c, 0x00261c, 'A' },
+{ 0x00261e, 0x00261e, 'A' },
+{ 0x002640, 0x002640, 'A' },
+{ 0x002642, 0x002642, 'A' },
+{ 0x002648, 0x002653, 'W' },
+{ 0x002660, 0x002661, 'A' },
+{ 0x002663, 0x002665, 'A' },
+{ 0x002667, 0x00266a, 'A' },
+{ 0x00266c, 0x00266d, 'A' },
+{ 0x00266f, 0x00266f, 'A' },
+{ 0x00267f, 0x00267f, 'W' },
+{ 0x002693, 0x002693, 'W' },
+{ 0x00269e, 0x00269f, 'A' },
+{ 0x0026a1, 0x0026a1, 'W' },
+{ 0x0026aa, 0x0026ab, 'W' },
+{ 0x0026bd, 0x0026be, 'W' },
+{ 0x0026bf, 0x0026bf, 'A' },
+{ 0x0026c4, 0x0026c5, 'W' },
+{ 0x0026c6, 0x0026cd, 'A' },
+{ 0x0026ce, 0x0026ce, 'W' },
+{ 0x0026cf, 0x0026d3, 'A' },
+{ 0x0026d4, 0x0026d4, 'W' },
+{ 0x0026d5, 0x0026e1, 'A' },
+{ 0x0026e3, 0x0026e3, 'A' },
+{ 0x0026e8, 0x0026e9, 'A' },
+{ 0x0026ea, 0x0026ea, 'W' },
+{ 0x0026eb, 0x0026f1, 'A' },
+{ 0x0026f2, 0x0026f3, 'W' },
+{ 0x0026f4, 0x0026f4, 'A' },
+{ 0x0026f5, 0x0026f5, 'W' },
+{ 0x0026f6, 0x0026f9, 'A' },
+{ 0x0026fa, 0x0026fa, 'W' },
+{ 0x0026fb, 0x0026fc, 'A' },
+{ 0x0026fd, 0x0026fd, 'W' },
+{ 0x0026fe, 0x0026ff, 'A' },
+{ 0x002705, 0x002705, 'W' },
+{ 0x00270a, 0x00270b, 'W' },
+{ 0x002728, 0x002728, 'W' },
+{ 0x00273d, 0x00273d, 'A' },
+{ 0x00274c, 0x00274c, 'W' },
+{ 0x00274e, 0x00274e, 'W' },
+{ 0x002753, 0x002755, 'W' },
+{ 0x002757, 0x002757, 'W' },
+{ 0x002776, 0x00277f, 'A' },
+{ 0x002795, 0x002797, 'W' },
+{ 0x0027b0, 0x0027b0, 'W' },
+{ 0x0027bf, 0x0027bf, 'W' },
+{ 0x002b1b, 0x002b1c, 'W' },
+{ 0x002b50, 0x002b50, 'W' },
+{ 0x002b55, 0x002b55, 'W' },
+{ 0x002b56, 0x002b59, 'A' },
+{ 0x002e80, 0x002ffb, 'W' },
+{ 0x003000, 0x003000, 'F' },
+{ 0x003001, 0x00303e, 'W' },
+{ 0x003041, 0x003247, 'W' },
+{ 0x003248, 0x00324f, 'A' },
+{ 0x003250, 0x004dbf, 'W' },
+{ 0x004e00, 0x00a4c6, 'W' },
+{ 0x00a960, 0x00a97c, 'W' },
+{ 0x00ac00, 0x00d7a3, 'W' },
+{ 0x00e000, 0x00f8ff, 'A' },
+{ 0x00f900, 0x00faff, 'W' },
+{ 0x00fe00, 0x00fe0f, 'A' },
+{ 0x00fe10, 0x00fe19, 'W' },
+{ 0x00fe30, 0x00fe6b, 'W' },
+{ 0x00ff01, 0x00ff60, 'F' },
+{ 0x00ffe0, 0x00ffe6, 'F' },
+{ 0x00fffd, 0x00fffd, 'A' },
+{ 0x016fe0, 0x01b2fb, 'W' },
+{ 0x01f004, 0x01f004, 'W' },
+{ 0x01f0cf, 0x01f0cf, 'W' },
+{ 0x01f100, 0x01f10a, 'A' },
+{ 0x01f110, 0x01f12d, 'A' },
+{ 0x01f130, 0x01f169, 'A' },
+{ 0x01f170, 0x01f18d, 'A' },
+{ 0x01f18e, 0x01f18e, 'W' },
+{ 0x01f18f, 0x01f190, 'A' },
+{ 0x01f191, 0x01f19a, 'W' },
+{ 0x01f19b, 0x01f1ac, 'A' },
+{ 0x01f200, 0x01f320, 'W' },
+{ 0x01f32d, 0x01f335, 'W' },
+{ 0x01f337, 0x01f37c, 'W' },
+{ 0x01f37e, 0x01f393, 'W' },
+{ 0x01f3a0, 0x01f3ca, 'W' },
+{ 0x01f3cf, 0x01f3d3, 'W' },
+{ 0x01f3e0, 0x01f3f0, 'W' },
+{ 0x01f3f4, 0x01f3f4, 'W' },
+{ 0x01f3f8, 0x01f43e, 'W' },
+{ 0x01f440, 0x01f440, 'W' },
+{ 0x01f442, 0x01f4fc, 'W' },
+{ 0x01f4ff, 0x01f53d, 'W' },
+{ 0x01f54b, 0x01f54e, 'W' },
+{ 0x01f550, 0x01f567, 'W' },
+{ 0x01f57a, 0x01f57a, 'W' },
+{ 0x01f595, 0x01f596, 'W' },
+{ 0x01f5a4, 0x01f5a4, 'W' },
+{ 0x01f5fb, 0x01f64f, 'W' },
+{ 0x01f680, 0x01f6c5, 'W' },
+{ 0x01f6cc, 0x01f6cc, 'W' },
+{ 0x01f6d0, 0x01f6d2, 'W' },
+{ 0x01f6d5, 0x01f6d5, 'W' },
+{ 0x01f6eb, 0x01f6ec, 'W' },
+{ 0x01f6f4, 0x01f6fa, 'W' },
+{ 0x01f7e0, 0x01f7eb, 'W' },
+{ 0x01f90d, 0x01f9ff, 'W' },
+{ 0x01fa70, 0x03fffd, 'W' },
+{ 0x0e0100, 0x10fffd, 'A' },

Added: branches/unicode_buf/teraterm/teraterm/unicode_combine.tbl
===================================================================
--- branches/unicode_buf/teraterm/teraterm/unicode_combine.tbl	                        (rev 0)
+++ branches/unicode_buf/teraterm/teraterm/unicode_combine.tbl	2019-06-25 14:05:37 UTC (rev 7810)
@@ -0,0 +1,37 @@
+{ 0x000300, 0x00036f },		// 'COMBINING GRAVE ACCENT'
+{ 0x000483, 0x000489 },		// 'COMBINING CYRILLIC TITLO'
+{ 0x0007eb, 0x0007f3 },		// 'NKO COMBINING SHORT HIGH TONE'
+{ 0x000c00, 0x000c00 },		// 'TELUGU SIGN COMBINING CANDRABINDU ABOVE'
+{ 0x000c04, 0x000c04 },		// 'TELUGU SIGN COMBINING ANUSVARA ABOVE'
+{ 0x000d00, 0x000d00 },		// 'MALAYALAM SIGN COMBINING ANUSVARA ABOVE'
+{ 0x00135d, 0x00135f },		// 'ETHIOPIC COMBINING GEMINATION AND VOWEL LENGTH MARK'
+{ 0x001a7f, 0x001a7f },		// 'TAI THAM COMBINING CRYPTOGRAMMIC DOT'
+{ 0x001ab0, 0x001abe },		// 'COMBINING DOUBLED CIRCUMFLEX ACCENT'
+{ 0x001b6b, 0x001b73 },		// 'BALINESE MUSICAL SYMBOL COMBINING TEGEH'
+{ 0x001dc0, 0x001df9 },		// 'COMBINING DOTTED GRAVE ACCENT'
+{ 0x0020d0, 0x0020f0 },		// 'COMBINING LEFT HARPOON ABOVE'
+{ 0x002cef, 0x002cf1 },		// 'COPTIC COMBINING NI ABOVE'
+{ 0x002de0, 0x002dff },		// 'COMBINING CYRILLIC LETTER BE'
+{ 0x003099, 0x00309a },		// 'COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK'
+{ 0x00a66f, 0x00a672 },		// 'COMBINING CYRILLIC VZMET'
+{ 0x00a674, 0x00a67d },		// 'COMBINING CYRILLIC LETTER UKRAINIAN IE'
+{ 0x00a69e, 0x00a69f },		// 'COMBINING CYRILLIC LETTER EF'
+{ 0x00a6f0, 0x00a6f1 },		// 'BAMUM COMBINING MARK KOQNDON'
+{ 0x00a8e0, 0x00a8f1 },		// 'COMBINING DEVANAGARI DIGIT ZERO'
+{ 0x00fe20, 0x00fe2f },		// 'COMBINING LIGATURE LEFT HALF'
+{ 0x0101fd, 0x0101fd },		// 'PHAISTOS DISC SIGN COMBINING OBLIQUE STROKE'
+{ 0x010376, 0x01037a },		// 'COMBINING OLD PERMIC LETTER AN'
+{ 0x010f46, 0x010f50 },		// 'SOGDIAN COMBINING DOT BELOW'
+{ 0x011300, 0x011300 },		// 'GRANTHA SIGN COMBINING ANUSVARA ABOVE'
+{ 0x01133b, 0x01133b },		// 'COMBINING BINDU BELOW'
+{ 0x011366, 0x01136c },		// 'COMBINING GRANTHA DIGIT ZERO'
+{ 0x016af0, 0x016af4 },		// 'BASSA VAH COMBINING HIGH TONE'
+{ 0x01d165, 0x01d169 },		// 'MUSICAL SYMBOL COMBINING STEM'
+{ 0x01d16d, 0x01d172 },		// 'MUSICAL SYMBOL COMBINING AUGMENTATION DOT'
+{ 0x01d17b, 0x01d182 },		// 'MUSICAL SYMBOL COMBINING ACCENT'
+{ 0x01d185, 0x01d18b },		// 'MUSICAL SYMBOL COMBINING DOIT'
+{ 0x01d1aa, 0x01d1ad },		// 'MUSICAL SYMBOL COMBINING DOWN BOW'
+{ 0x01d242, 0x01d244 },		// 'COMBINING GREEK MUSICAL TRISEME'
+{ 0x01e000, 0x01e006 },		// 'COMBINING GLAGOLITIC LETTER AZU'
+{ 0x01e8d0, 0x01e8d6 },		// 'MENDE KIKAKUI COMBINING NUMBER TEENS'
+{ 0x01f3fb, 0x01f3ff },		// 'EMOJI MODIFIER FITZPATRICK TYPE-1-2'

Added: branches/unicode_buf/teraterm/teraterm/unicode_test.h
===================================================================
--- branches/unicode_buf/teraterm/teraterm/unicode_test.h	                        (rev 0)
+++ branches/unicode_buf/teraterm/teraterm/unicode_test.h	2019-06-25 14:05:37 UTC (rev 7810)
@@ -0,0 +1,16 @@
+/*
+ * \x83e\x83X\x83g\x82̂\xBD\x82߂ɒlj\xC1
+ *	teraterm.h\x82Ȃǂɓ\xFC\x82\xEA\x82\xE9\x82ƈˑ\xB6\x83t\x83@\x83C\x83\x8B\x82\xAA\x91\xBD\x82\xA2\x82\xBD\x82߃r\x83\x8B\x83h\x82Ɏ\x9E\x8AԂ\xAA\x82\xA9\x82\xA9\x82邽\x82\xDF
+ *	\x83e\x83X\x83g\x97p\x83w\x83b\x83_\x82ɕ\xAA\x97\xA3
+ *	\x8F\xAB\x97\x88\x82͂Ȃ\xAD\x82Ȃ\xE9
+ *
+ */
+#pragma once
+
+#define	UNICODE_INTERNAL_BUFF	1	// 1 = \x93\xE0\x95\x94\x83o\x83b\x83t\x83 @ unicode\x89\xBB
+#define UNICODE_DISPLAY			1	// 0/1 = DispStr()/DispStrW()
+
+// UNICODE_INTERNAL_BUFF\x82̉e\x8B\xBF\x82\xF0\x8E󂯂Ȃ\xA2
+#define UNICODE_API				1	// UNICODE API\x82\xF0\x8B\x96\x89\xC2
+#define	UNICODE_DEBUG			1	// \x83f\x83o\x83O\x97p\x8B@\x94\enable
+#define	UNICODE_DEBUG_CARET_OFF	0	// \x83J\x81[\x83\\x83\x8B\x93_\x96Ōn\x82\xF0\x8E~\x82߂\xE9\x83f\x83o\x83O\x97p

Modified: branches/unicode_buf/teraterm/teraterm/vtdisp.c
===================================================================
--- branches/unicode_buf/teraterm/teraterm/vtdisp.c	2019-06-25 13:58:11 UTC (rev 7809)
+++ branches/unicode_buf/teraterm/teraterm/vtdisp.c	2019-06-25 14:05:37 UTC (rev 7810)
@@ -43,6 +43,8 @@
 #include <locale.h>
 #include <olectl.h>
 
+#include "unicode_test.h"
+
 #define CurWidth 2
 
 static const BYTE DefaultColorTable[256][3] = {
@@ -2203,6 +2205,9 @@
 void CaretOn()
 // Turn on the cursor
 {
+#if UNICODE_DEBUG_CARET_OFF
+	return;
+#endif
 	if (ts.KillFocusCursor == 0 && !Active)
 		return;
 
@@ -2300,6 +2305,9 @@
 
 void DispEnableCaret(BOOL On)
 {
+#if UNICODE_DEBUG_CARET_OFF
+  On = FALSE;
+#endif
   if (! On) CaretOff();
   CaretEnabled = On;
 }
@@ -2758,9 +2766,37 @@
   }
 }
 
-#if 1
-// \x93\x96\x96ʂ͂\xB1\x82\xBF\x82\xE7\x82̊֐\x94\x82\xF0\x8Eg\x82\xA4\x81B(2004.11.4 yutaka)
-void DispStr(PCHAR Buff, int Count, int Y, int* X)
+static void DrawTextBGImage(HDC hdcBGBuffer, int X, int Y, int width, int height)
+{
+	RECT  rect;
+	SetRect(&rect,0,0,width,height);
+
+	//\x91\x8B\x82̈ړ\xAE\x81A\x83\x8A\x83T\x83C\x83Y\x92\x86\x82͔w\x8Ci\x82\xF0 BGBrushInSizeMove \x82œh\x82\xE8\x82‚Ԃ\xB7
+	if(BGInSizeMove)
+		FillRect(hdcBGBuffer,&rect,BGBrushInSizeMove);
+
+	BitBlt(hdcBGBuffer,0,0,width,height,hdcBG,X,Y,SRCCOPY);
+
+	if(BGReverseText == TRUE)
+	{
+		if(BGReverseTextAlpha < 255)
+		{
+			BLENDFUNCTION bf;
+			HBRUSH hbr;
+
+			hbr = CreateSolidBrush(GetBkColor(hdcBGBuffer));
+			FillRect(hdcBGWork,&rect,hbr);
+			DeleteObject(hbr);
+
+			ZeroMemory(&bf,sizeof(bf));
+			bf.BlendOp             = AC_SRC_OVER;
+			bf.SourceConstantAlpha = BGReverseTextAlpha;
+
+			BGAlphaBlend(hdcBGBuffer,0,0,width,height,hdcBGWork,0,0,width,height,bf);
+		}
+	}
+}
+
 // Display a string
 //   Buff: points the string
 //   Y: vertical position in window cordinate
@@ -2767,159 +2803,171 @@
 //  *X: horizontal position
 // Return:
 //  *X: horizontal position shifted by the width of the string
+void DispStr(PCHAR Buff, int Count, int Y, int* X)
 {
-  RECT RText;
-
-  if ((ts.Language==IdRussian) &&
-      (ts.RussClient!=ts.RussFont))
-    RussConvStr(ts.RussClient,ts.RussFont,Buff,Count);
-
-  RText.top = Y;
-  RText.bottom = Y+FontHeight;
-  RText.left = *X;
-  RText.right = *X + Count*FontWidth;
-
 #ifdef ALPHABLEND_TYPE2
-//<!--by AKASI
-  if(!BGEnable)
-  {
-    ExtTextOut(VTDC,*X+ts.FontDX,Y+ts.FontDY,
-               ETO_CLIPPED | ETO_OPAQUE,
-               &RText,Buff,Count,&Dx[0]);
-  }else{
+	const BOOL draw_bg_enable = BGEnable;
+#else
+	const BOOL draw_bg_enable = FALSE;
+#endif
 
-    int   width;
-    int   height;
-    int   eto_options = ETO_CLIPPED;
-    RECT  rect;
-    HFONT hPrevFont;
+	{
+		char b[128];
+		memcpy(b, Buff, Count);
+		b[Count] = 0;
+		OutputDebugPrintf("(%d,%d)'%s'\n", *X, Y, b);
+	}
 
-    width  = Count*FontWidth;
-    height = FontHeight;
-    SetRect(&rect,0,0,width,height);
+	if ((ts.Language==IdRussian) &&
+		(ts.RussClient!=ts.RussFont))
+		RussConvStr(ts.RussClient,ts.RussFont,Buff,Count);
 
-    //hdcBGBuffer \x82̑\xAE\x90\xAB\x82\xF0\x90ݒ\xE8
-    hPrevFont = SelectObject(hdcBGBuffer,GetCurrentObject(VTDC,OBJ_FONT));
-    SetTextColor(hdcBGBuffer,GetTextColor(VTDC));
-    SetBkColor(hdcBGBuffer,GetBkColor(VTDC));
+	if(!draw_bg_enable)
+	{
+		RECT RText;
+		RText.top = Y;
+		RText.bottom = Y+FontHeight;
+		RText.left = *X;
+		RText.right = *X + Count*FontWidth;
 
-    //\x91\x8B\x82̈ړ\xAE\x81A\x83\x8A\x83T\x83C\x83Y\x92\x86\x82͔w\x8Ci\x82\xF0 BGBrushInSizeMove \x82œh\x82\xE8\x82‚Ԃ\xB7
-    if(BGInSizeMove)
-      FillRect(hdcBGBuffer,&rect,BGBrushInSizeMove);
+		ExtTextOutA(VTDC,*X+ts.FontDX,Y+ts.FontDY,
+					ETO_CLIPPED | ETO_OPAQUE,
+					&RText,Buff,Count,&Dx[0]);
+	}
+#ifdef ALPHABLEND_TYPE2
+	else {
+		HFONT hPrevFont;
+		RECT  rect;
+		int   eto_options;
+		const int width  = Count*FontWidth;
+		const int height = FontHeight;
+		SetRect(&rect,0,0,width,height);
 
-    BitBlt(hdcBGBuffer,0,0,width,height,hdcBG,*X,Y,SRCCOPY);
+		//hdcBGBuffer \x82̑\xAE\x90\xAB\x82\xF0\x90ݒ\xE8
+		hPrevFont = SelectObject(hdcBGBuffer,GetCurrentObject(VTDC,OBJ_FONT));
+		SetTextColor(hdcBGBuffer,GetTextColor(VTDC));
+		SetBkColor(hdcBGBuffer,GetBkColor(VTDC));
 
-    if(BGReverseText == TRUE)
-    {
-      if(BGReverseTextAlpha < 255)
-      {
-        BLENDFUNCTION bf;
-        HBRUSH hbr;
+		// \x95\xB6\x8E\x9A\x82̔w\x8Ci\x82\xF0\x95`\x89\xE6
+		DrawTextBGImage(hdcBGBuffer, *X, Y, width, height);
 
-        hbr = CreateSolidBrush(GetBkColor(hdcBGBuffer));
-        FillRect(hdcBGWork,&rect,hbr);
-        DeleteObject(hbr);
+		// \x95\xB6\x8E\x9A\x82\xF0\x95`\x89\xE6
+		eto_options = ETO_CLIPPED;
+		if(BGReverseText == TRUE && BGReverseTextAlpha < 255) {
+			eto_options |= ETO_OPAQUE;
+		}
+		ExtTextOutA(hdcBGBuffer,ts.FontDX,ts.FontDY,eto_options,&rect,Buff,Count,&Dx[0]);
 
-        ZeroMemory(&bf,sizeof(bf));
-        bf.BlendOp             = AC_SRC_OVER;
-        bf.SourceConstantAlpha = BGReverseTextAlpha;
+		// Window\x82ɓ\\x82\xE8\x95t\x82\xAF
+		BitBlt(VTDC,*X,Y,width,height,hdcBGBuffer,0,0,SRCCOPY);
 
-        BGAlphaBlend(hdcBGBuffer,0,0,width,height,hdcBGWork,0,0,width,height,bf);
-      }else{
-        eto_options |= ETO_OPAQUE;
-      }
-    }
+		SelectObject(hdcBGBuffer,hPrevFont);
+	}
+#endif
 
-    ExtTextOut(hdcBGBuffer,ts.FontDX,ts.FontDY,eto_options,&rect,Buff,Count,&Dx[0]);
-    BitBlt(VTDC,*X,Y,width,height,hdcBGBuffer,0,0,SRCCOPY);
+	*X += Count*FontWidth;
 
-    SelectObject(hdcBGBuffer,hPrevFont);
-  }
-//-->
-#else
-  ExtTextOut(VTDC,*X+ts.FontDX,Y+ts.FontDY,
-             ETO_CLIPPED | ETO_OPAQUE,
-             &RText,Buff,Count,&Dx[0]);
-#endif
-  *X = RText.right;
-
-  if ((ts.Language==IdRussian) &&
-      (ts.RussClient!=ts.RussFont))
-    RussConvStr(ts.RussFont,ts.RussClient,Buff,Count);
+	if ((ts.Language==IdRussian) && (ts.RussClient!=ts.RussFont))
+		RussConvStr(ts.RussFont,ts.RussClient,Buff,Count);
 }
 
+// DispStr() \x82\xCC wchar_t\x94\xC5
+// TODO: \x8D\xA1\x82̂Ƃ\xB1\x82\xEB ExtTextOutW() \x82𒼌Ă\xD1
+#if defined(UNICODE_DISPLAY)
+void DispStrW(const wchar_t *StrW, const char *WidthInfo, int Count, int Y, int* X)
+{
+#ifdef ALPHABLEND_TYPE2
+	const BOOL draw_bg_enable = BGEnable;
 #else
-void DispStr(PCHAR Buff, int Count, int Y, int* X)
-// Display a string
-//   Buff: points the string
-//   Y: vertical position in window cordinate
-//  *X: horizontal position
-// Return:
-//  *X: horizontal position shifted by the width of the string
-{
-	RECT RText;
-	wchar_t *wc;
-	int len, wclen;
-	CHAR ch;
+	const BOOL draw_bg_enable = FALSE;
+#endif
 
 #if 0
-#include <crtdbg.h>
-	_CrtSetBreakAlloc(52);
-	Buff[0] = 0x82;
-	Buff[1] = 0xe4;
-	Buff[2] = 0x82;
-	Buff[3] = 0xbd;
-	Buff[4] = 0x82;
-	Buff[5] = 0xa9;
-	Count = 6;
+	{
+		int b[TermWidthMax];
+		memcpy(b, StrW, Count*sizeof(wchar_t));
+		b[Count] = 0;
+		OutputDebugPrintfW(L"(%d,%d)'%s'\n", *X, Y, b);
+		OutputDebugPrintfW(L"       '%hs'\n", WidthInfo);
+	}
 #endif
 
-	setlocale(LC_ALL, ts.Locale);	// TODO \x83R\x81[\x83h\x95ϊ\xB7\x82\xB1\x82\xB1\x82ł\xB7\x82\xE9?,\x96\xB3\x8C\x{27B0B3}\x82ꂽ\x83R\x81[\x83h
+	int Dx2[TermWidthMax];
+	int dx3 = 0;
+	int HalfCharCount = 0;
+	int i;
+	for(i=0; i<Count; i++) {
+		if (WidthInfo[i] == 'H') {
+			HalfCharCount++;
+			dx3++;
+			Dx2[i] = FontWidth;
+		} else if (WidthInfo[i] == '0') {
+			if (i == 0) {
+				Dx2[i] = 0;
+			} else {
+				Dx2[i] = Dx2[i-1];
+				Dx2[i-1] = 0;
+			}
+		} else {
+			HalfCharCount += 2;
+			Dx2[i] = FontWidth * 2;
+			dx3 += 2;
+		}
+	}
 
-	ch = Buff[Count];
-	Buff[Count] = 0;
-	len = mbstowcs(NULL, Buff, 0);
+	if(!draw_bg_enable)
+	{
+		RECT RText;
+		RText.top = Y;
+		RText.bottom = Y+FontHeight;
+		RText.left = *X;
+		RText.right = *X + HalfCharCount * FontWidth;
+		RText.right = *X + dx3 * FontWidth;
 
-	wc = malloc(sizeof(wchar_t) * (len + 1));
-	if (wc == NULL)
-		return;
-	wclen = mbstowcs(wc, Buff, len + 1);
-	Buff[Count] = ch;
+#if 0
+		ExtTextOutW(VTDC, *X + ts.FontDX, Y + ts.FontDY,
+			ETO_CLIPPED | ETO_OPAQUE,
+			&RText, Buff, Count, &Dx[0]);
+#endif
+		ExtTextOutW(VTDC, *X + ts.FontDX, Y + ts.FontDY,
+			ETO_CLIPPED | ETO_OPAQUE,
+			&RText, StrW, Count, &Dx2[0]);
+	}
+#ifdef ALPHABLEND_TYPE2
+	else {
+		HFONT hPrevFont;
+		RECT  rect;
+		int   eto_options;
+		const int width  = Count*FontWidth*2;
+		const int height = FontHeight;
+		SetRect(&rect,0,0,width,height);
 
-	if ((ts.Language==IdRussian) &&
-		(ts.RussClient!=ts.RussFont))
-		RussConvStr(ts.RussClient,ts.RussFont,Buff,Count);
+		//hdcBGBuffer \x82̑\xAE\x90\xAB\x82\xF0\x90ݒ\xE8
+		hPrevFont = SelectObject(hdcBGBuffer,GetCurrentObject(VTDC,OBJ_FONT));
+		SetTextColor(hdcBGBuffer,GetTextColor(VTDC));
+		SetBkColor(hdcBGBuffer,GetBkColor(VTDC));
 
-	RText.top = Y;
-	RText.bottom = Y+FontHeight;
-	RText.left = *X;
-	RText.right = *X + Count*FontWidth; //
+		// \x95\xB6\x8E\x9A\x82̔w\x8Ci\x82\xF0\x95`\x89\xE6
+		DrawTextBGImage(hdcBGBuffer, *X, Y, width, height);
 
-	// Unicode\x82ŏo\x97͂\xB7\x82\xE9\x81B
-#if 1
-	// UTF-8\x8A‹\xAB\x82ɂ\xA8\x82\xA2\x82āAtcsh\x82\xAAEUC\x8Fo\x97͂\xB5\x82\xBD\x8Fꍇ\x81A\x89\xE6\x96ʂɉ\xBD\x82\xE0\x95\\x8E\xA6\x82\xB3\x82\xEA\x82Ȃ\xA2\x82\xB1\x82Ƃ\xAA\x82\xA0\x82\xE9\x81B
-	// \x83}\x83E\x83X\x82Ńh\x83\x89\x83b\x83O\x82\xB5\x82\xBD\x82\xE8\x81A\x83\x8D\x83O\x83t\x83@\x83C\x83\x8B\x82֕ۑ\xB6\x82\xB5\x82Ă݂\xE9\x82ƁA\x95\xB6\x8E\x9A\x89\xBB\x82\xAF\x82\xB5\x82\xBD\x95\xB6\x8E\x9A\x97\xF1\x82\xF0
-	// \x8Am\x94F\x82\xB7\x82邱\x82Ƃ\xAA\x82ł\xAB\x82\xE9\x81B(2004.8.6 yutaka)
-	ExtTextOutW(VTDC,*X+ts.FontDX,Y+ts.FontDY,
-		ETO_CLIPPED | ETO_OPAQUE,
-		&RText, wc, wclen, NULL);
-//		&RText, wc, wclen, &Dx[0]);
-#else
-	TextOutW(VTDC, *X+ts.FontDX, Y+ts.FontDY, wc, wclen);
+		// \x95\xB6\x8E\x9A\x82\xF0\x95`\x89\xE6
+		eto_options = ETO_CLIPPED;
+		if(BGReverseText == TRUE && BGReverseTextAlpha < 255) {
+			eto_options |= ETO_OPAQUE;
+		}
+		ExtTextOutW(hdcBGBuffer,ts.FontDX,ts.FontDY,eto_options,&rect, StrW,Count,&Dx[0]);
 
+		// Window\x82ɓ\\x82\xE8\x95t\x82\xAF
+		BitBlt(VTDC,*X,Y,width,height,hdcBGBuffer,0,0,SRCCOPY);
+
+		SelectObject(hdcBGBuffer,hPrevFont);
+	}
 #endif
 
-	*X = RText.right;
-
-	if ((ts.Language==IdRussian) &&
-		(ts.RussClient!=ts.RussFont))
-		RussConvStr(ts.RussFont,ts.RussClient,Buff,Count);
-
-	free(wc);
+	*X += dx3 *FontWidth;
 }
 #endif
 
-
 void DispEraseCurToEnd(int YEnd)
 {
   RECT R;

Modified: branches/unicode_buf/teraterm/teraterm/vtdisp.h
===================================================================
--- branches/unicode_buf/teraterm/teraterm/vtdisp.h	2019-06-25 13:58:11 UTC (rev 7809)
+++ branches/unicode_buf/teraterm/teraterm/vtdisp.h	2019-06-25 14:05:37 UTC (rev 7810)
@@ -80,6 +80,7 @@
 void DispReleaseDC();
 void DispSetupDC(TCharAttr Attr, BOOL Reverse);
 void DispStr(PCHAR Buff, int Count, int Y, int* X);
+void DispStrW(const wchar_t *StrW, const char *WidthInfo, int Count, int Y, int* X);
 void DispEraseCurToEnd(int YEnd);
 void DispEraseHomeToCur(int YHome);
 void DispEraseCharsInLine(int XStart, int Count);

Modified: branches/unicode_buf/teraterm/teraterm/vtterm.c
===================================================================
--- branches/unicode_buf/teraterm/teraterm/vtterm.c	2019-06-25 13:58:11 UTC (rev 7809)
+++ branches/unicode_buf/teraterm/teraterm/vtterm.c	2019-06-25 14:05:37 UTC (rev 7810)
@@ -64,6 +64,8 @@
 #define _strdup(s)	  _strdup_dbg((s), _NORMAL_BLOCK, __FILE__, __LINE__)
 #endif
 
+#include "unicode_test.h"
+
 void ParseFirst(BYTE b);
 
 #define MAPSIZE(x) (sizeof(x)/sizeof((x)[0]))
@@ -661,7 +663,11 @@
 	else
 		CharAttrTmp.Attr |= CharAttr.Attr;
 
+#if UNICODE_INTERNAL_BUFF
+	BuffPutUnicode(b, CharAttrTmp, InsertMode);
+#else
 	BuffPutChar(b, CharAttrTmp, InsertMode);
+#endif
 
 	if (CursorX == CursorRightM || CursorX >= NumOfColumns-1) {
 		UpdateStr();
@@ -672,7 +678,7 @@
 	}
 }
 
-void PutDecSp(BYTE b)
+static void PutDecSp(BYTE b)
 {
 	TCharAttr CharAttrTmp;
 
@@ -717,7 +723,7 @@
 	}
 }
 
-void PutKanji(BYTE b)
+static void PutKanji(BYTE b)
 {
 	int LineEnd;
 	TCharAttr CharAttrTmp;
@@ -848,7 +854,7 @@
 	}
 }
 
-void PrnParseControl(BYTE b) // printer mode
+static void PrnParseControl(BYTE b) // printer mode
 {
 	switch (b) {
 	case NUL:
@@ -897,7 +903,7 @@
 	WriteToPrnFile(b, TRUE);
 }
 
-void ParseControl(BYTE b)
+static void ParseControl(BYTE b)
 {
 	if (PrinterMode) { // printer mode
 		PrnParseControl(b);
@@ -5460,6 +5466,75 @@
 	return (index);
 }
 
+// unicode(UTF-32,wchar_t)\x82\xF0\x83o\x83b\x83t\x83@\x82֏\x91\x82\xAB\x8D\x9E\x82\xDE
+// TODO @@
+#if UNICODE_INTERNAL_BUFF
+// \x93\xE0\x95\x94\x83R\x81[\x83h unicode\x94\xC5
+static void UnicodeToCP932(unsigned int code)
+{
+	unsigned short cset;
+	char r;
+
+	TCharAttr CharAttrTmp;
+	CharAttrTmp = CharAttr;
+	if (code <= US) {
+		// C0
+		ParseControl(code);
+#if 0
+	} else if ((0x80<=code) && (code<=0x9F)) {
+		// C1
+		ParseControl(code);
+	} else if (code < 0x20) {
+		PutChar(code);
+#endif
+#if 0
+	} else if (code <= 0xff) {
+		PutChar(code);
+#endif
+	} else {
+		// Unicode\x82\xA9\x82\xE7DEC\x93\xC1\x8Eꕶ\x8E\x9A\x82ւ̃}\x83b\x83s\x83\x93\x83O
+		if (ts.UnicodeDecSpMapping) {
+			cset = UTF32ToDecSp(code);
+			if (((cset >> 8) & ts.UnicodeDecSpMapping) != 0) {
+				code = cset & 0xff;
+				CharAttrTmp.Attr |= AttrSpecial;
+			}
+		}
+
+		if ((CharAttrTmp.Attr & AttrSpecial) == 0) {
+			if (Special) {
+				UpdateStr();
+				Special = FALSE;
+			}
+		} else {
+			if (!Special) {
+				UpdateStr();
+				Special = TRUE;
+			}
+		}
+
+		r = BuffPutUnicode(code, CharAttrTmp, InsertMode);
+		if (CursorX == CursorRightM || CursorX >= NumOfColumns - 1) {
+			UpdateStr();
+			Wrap = AutoWrapMode;
+		}
+		else {
+			if (r == '0' || r == 'V') {
+				;
+			}
+			else {
+				if (r == 'W') {
+					// \x91S\x8Ap
+					MoveRight();
+				}
+				MoveRight();
+			}
+		}
+	}
+}
+
+#else
+
 // unicode(UTF-32)\x82\xF0\x83o\x83b\x83t\x83@(t.CodePage)\x82֏\x91\x82\xAB\x8D\x9E\x82\xDE
 static void UnicodeToCP932(unsigned int code)
 {
@@ -5505,6 +5580,24 @@
 	}
 }
 
+#endif
+
+// UTF-8\x82Ŏ\xF3\x90M\x83f\x81[\x83^\x82\xF0\x8F\x88\x97\x9D\x82\xB7\x82\xE9(sub)
+#if UNICODE_INTERNAL_BUFF
+static BOOL ParseFirstUTF8Sub(BYTE b)
+{
+	if (b<=US)
+		ParseControl(b);
+	else if ((b>=0x20) && (b<=0x7E))
+		PutChar(b);
+	else if ((b>=0x80) && (b<=0x9F))
+		ParseControl(b);
+	else if (b>=0xA0)
+		PutChar(b);
+	return TRUE;
+}
+#endif
+
 // UTF-8\x82Ŏ\xF3\x90M\x83f\x81[\x83^\x82\xF0\x8F\x88\x97\x9D\x82\xB7\x82\xE9
 // returns TRUE if b is processed
 //  (actually allways returns TRUE)
@@ -5533,10 +5626,19 @@
 			}
 
 			if (count == 1) {
+//#if UNICODE_INTERNAL_BUFF
+#if 0
+				ParseFirstUTF8Sub(buf[0]);
+#else
 				ParseASCII(buf[0]);
+#endif
 			}
+//#if UNICODE_INTERNAL_BUFF
+#if 0
+			ParseFirstUTF8Sub(b);
+#else
 			ParseASCII(b);
-
+#endif
 			count = 0;  // reset counter
 			return TRUE;
 		}
@@ -5636,7 +5738,7 @@
 		return TRUE;
 	}
 
-	if ((buf[0] & 0xf1) == 0xf0 &&
+	if ((buf[0] & 0xf8) == 0xf0 &&
 		(buf[1] & 0xc0) == 0x80 &&
 		(buf[2] & 0xc0) == 0x80 &&
 		(buf[3] & 0xc0) == 0x80)

Modified: branches/unicode_buf/teraterm/teraterm/vtwin.cpp
===================================================================
--- branches/unicode_buf/teraterm/teraterm/vtwin.cpp	2019-06-25 13:58:11 UTC (rev 7809)
+++ branches/unicode_buf/teraterm/teraterm/vtwin.cpp	2019-06-25 14:05:37 UTC (rev 7810)
@@ -85,6 +85,10 @@
 #include "tekwin.h"
 #include <htmlhelp.h>
 #include "compat_win.h"
+#include "unicode_test.h"
+#if UNICODE_DEBUG
+#include "tipwin.h"
+#endif
 
 #include "initguid.h"
 //#include "Usbiodef.h"
@@ -144,6 +148,10 @@
 #define WM_IME_COMPOSITION              0x010F
 #endif
 
+#if UNICODE_DEBUG
+static TipWin *TipWinCodeDebug;
+#endif
+
 /////////////////////////////////////////////////////////////////////////////
 // CVTWindow
 
@@ -2266,6 +2274,12 @@
 void CVTWindow::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
 {
 	KeyUp(nChar);
+#if UNICODE_DEBUG
+	if (TipWinCodeDebug != NULL) {
+		TipWinDestroy(TipWinCodeDebug);
+		TipWinCodeDebug = NULL;
+	}
+#endif
 }
 
 void CVTWindow::OnKillFocus(HWND hNewWnd)
@@ -2378,6 +2392,22 @@
 	int i;
 	BOOL mousereport;
 
+#if UNICODE_DEBUG
+    if (GetAsyncKeyState(VK_RCONTROL) != 0) {
+		wchar_t buf[128];
+		BuffCheckMouse(point.x, point.y, buf, _countof(buf));
+		POINT TipWinPos = { point.x, point.y };
+		ClientToScreen(m_hWnd, &TipWinPos);
+		if (TipWinCodeDebug == NULL) {
+			TipWinCodeDebug = TipWinCreate(m_hWnd, TipWinPos.x, TipWinPos.y, "test");
+			TipWinSetTextW(TipWinCodeDebug, buf);
+		} else {
+			TipWinSetPos(TipWinCodeDebug, TipWinPos.x, TipWinPos.y);
+			TipWinSetTextW(TipWinCodeDebug, buf);
+		}
+	}
+#endif
+
 	if (!IgnoreRelease)
 		mousereport = MouseReport(IdMouseEventMove, 0, point.x, point.y);
 
@@ -6286,7 +6316,9 @@
 		OnRButtonUp((UINT)wp, MAKEPOINTS(lp));
 		break;
 	case WM_SETFOCUS:
+#if !UNICODE_DEBUG_CARET_OFF
 		OnSetFocus((HWND)wp);
+#endif
 		DefWindowProc(msg, wp, lp);
 		break;
 	case WM_SIZE:

Modified: branches/unicode_buf/teraterm/ttpcmn/ttcmn.c
===================================================================
--- branches/unicode_buf/teraterm/ttpcmn/ttcmn.c	2019-06-25 13:58:11 UTC (rev 7809)
+++ branches/unicode_buf/teraterm/ttpcmn/ttcmn.c	2019-06-25 14:05:37 UTC (rev 7810)
@@ -40,6 +40,7 @@
 #include <setupapi.h>
 #include <locale.h>
 #include <htmlhelp.h>
+#include <assert.h>
 
 #define DllExport __declspec(dllexport)
 #include "language.h"
@@ -1920,20 +1921,129 @@
 	return i;
 }
 
-// TODO: UTF-16\x82\xA9\x82璼\x90ڕϊ\xB7\x82\xB5\x82ďo\x97͂\xB7\x82\xE9
+/**
+ * CommTextOut() \x82\xCC wchar_t \x94\xC5
+ * \x8D\xA1\x82̏\x8AIME\x82\xA9\x82炵\x82\xA9\x8Eg\x82\xC1\x82Ă\xA2\x82Ȃ\xA2\x82\xBD\x82\xDF
+ * \x90\xA7\x8C\xE4\x83R\x81[\x83h\x8Cn\x82͖\xA2\x83e\x83X\x83g
+ */
 int WINAPI CommTextOutW(PComVar cv, const wchar_t *B, int C)
 {
-	int CodePage = *cv->CodePage;
-	size_t mb_len;
-	int r;
-	char *mb_str = _WideCharToMultiByte(B, C, CodePage, &mb_len);
-	if (mb_str == NULL) {
-		r = 0;
-	} else {
-		r = CommTextOut(cv, mb_str, mb_len);
-		free(mb_str);
+#if 1
+	if (cv->KanjiCodeSend == IdUTF8 || cv->Language == IdUtf8) {
+		int i, TempLen;
+		char TempStr[12];
+		wchar_t d;
+		BOOL Full;
+
+		Full = FALSE;
+		i = 0;
+		while (! Full && (i < C)) {
+			TempLen = 0;
+			d = B[i];
+
+			if (d==CR) {
+				TempStr[TempLen++] = 0x0d;
+				if (cv->CRSend==IdCRLF) {
+					TempStr[TempLen++] = 0x0a;
+				}
+				else if ((cv->CRSend ==IdCR) &&
+						 cv->TelFlag && ! cv->TelBinSend) {
+					TempStr[TempLen++] = 0;
+				}
+				else if (cv->CRSend == IdLF) {
+					TempStr[TempLen-1] = 0x0a;
+				}
+				if (cv->TelLineMode) {
+					cv->Flush = TRUE;
+				}
+			}
+			else if (d== BS) {
+				if (cv->TelLineMode) {
+					if (cv->FlushLen < cv->LineModeBuffCount) {
+						cv->LineModeBuffCount--;
+					}
+				}
+				else {
+					TempStr[TempLen++] = BS;
+				}
+			}
+			else if (d==0x15) { // ctrl-u
+				if (cv->TelLineMode) {
+					cv->LineModeBuffCount = cv->FlushLen;
+				}
+				else {
+					TempStr[TempLen++] = 0x15;
+				}
+			}
+			else if (d>=0x80) {
+				unsigned int u32;
+				size_t u16_len = UTF16ToUTF32(&B[i], C - i, &u32);
+				if (u16_len == 0) {
+					// \x83f\x83R\x81[\x83h\x82ł\xAB\x82Ȃ\xA2\x95\xB6\x8E\x9A
+					TempStr[0] = '?';
+					TempLen = 1;
+					i++;
+				} else {
+					size_t utf8_len = sizeof(TempStr);
+					utf8_len = UTF32ToUTF8(u32, TempStr, utf8_len);
+					TempLen += utf8_len;
+					i += u16_len;
+				}
+			}
+
+			if (cv->TelLineMode) {
+				if (TempLen > 0) {
+					Full = OutBuffSize - cv->LineModeBuffCount - TempLen < 0;
+					if (!Full) {
+						memcpy(&(cv->LineModeBuff[cv->LineModeBuffCount]), TempStr, TempLen);
+						cv->LineModeBuffCount += TempLen;
+						if (cv->Flush) {
+							cv->FlushLen = cv->LineModeBuffCount;
+						}
+					} else {
+						// !?
+						assert(FALSE);
+					}
+				}
+				if (cv->FlushLen > 0) {
+					int OutLen = CommRawOut(cv, cv->LineModeBuff, cv->FlushLen);
+					cv->FlushLen -= OutLen;
+					cv->LineModeBuffCount -= OutLen;
+					memmove(cv->LineModeBuff, &(cv->LineModeBuff[OutLen]), cv->LineModeBuffCount);
+				}
+				cv->Flush = FALSE;
+			}
+			else {
+				if (TempLen > 0) {
+					Full = OutBuffSize -cv->OutBuffCount -TempLen < 0;
+					if (! Full) {
+						CommRawOut(cv,TempStr,TempLen);
+					} else {
+						// !?
+						assert(FALSE);
+					}
+				}
+			}
+
+		} // end of "while {}"
+
+		return i;
 	}
-	return r;
+#endif
+
+	{
+		int CodePage = *cv->CodePage;
+		size_t mb_len;
+		int r;
+		char *mb_str = _WideCharToMultiByte(B, C, CodePage, &mb_len);
+		if (mb_str == NULL) {
+			r = 0;
+		} else {
+			r = CommTextOut(cv, mb_str, mb_len);
+			free(mb_str);
+		}
+		return r;
+	}
 }
 
 // TODO: UTF-16\x82\xA9\x82璼\x90ڕϊ\xB7\x82\xB5\x82ďo\x97͂\xB7\x82\xE9


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