[ttssh2-commit] [10731] 入力文字コードをUnicodeに変換する箇所を分離

Back to archive index
scmno****@osdn***** scmno****@osdn*****
2023年 6月 4日 (日) 01:55:29 JST


Revision: 10731
          https://osdn.net/projects/ttssh2/scm/svn/commits/10731
Author:   zmatsuo
Date:     2023-06-04 01:55:29 +0900 (Sun, 04 Jun 2023)
Log Message:
-----------
入力文字コードをUnicodeに変換する箇所を分離

- charset.c を追加

Modified Paths:
--------------
    branches/input_charset/teraterm/teraterm/CMakeLists.txt
    branches/input_charset/teraterm/teraterm/ttermpro.v16.vcxproj
    branches/input_charset/teraterm/teraterm/ttermpro.v16.vcxproj.filters
    branches/input_charset/teraterm/teraterm/ttermpro.v17.vcxproj
    branches/input_charset/teraterm/teraterm/ttermpro.v17.vcxproj.filters
    branches/input_charset/teraterm/teraterm/vtterm.c

Added Paths:
-----------
    branches/input_charset/teraterm/teraterm/charset.c
    branches/input_charset/teraterm/teraterm/charset.h

-------------- next part --------------
Modified: branches/input_charset/teraterm/teraterm/CMakeLists.txt
===================================================================
--- branches/input_charset/teraterm/teraterm/CMakeLists.txt	2023-06-03 16:53:36 UTC (rev 10730)
+++ branches/input_charset/teraterm/teraterm/CMakeLists.txt	2023-06-03 16:55:29 UTC (rev 10731)
@@ -17,6 +17,8 @@
   broadcast.h
   buffer.c
   buffer.h
+  charset.c
+  charset.h
   checkeol.cpp
   checkeol.h
   clipboar.c

Added: branches/input_charset/teraterm/teraterm/charset.c
===================================================================
--- branches/input_charset/teraterm/teraterm/charset.c	                        (rev 0)
+++ branches/input_charset/teraterm/teraterm/charset.c	2023-06-03 16:55:29 UTC (rev 10731)
@@ -0,0 +1,876 @@
+/*
+ * (C) 2023- 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 "teraterm.h"
+#include "tttypes.h"
+#include <stdio.h>
+#include <string.h>
+#if !defined(_CRTDBG_MAP_ALLOC)
+#define _CRTDBG_MAP_ALLOC
+#endif
+#include <stdlib.h>
+#include <crtdbg.h>
+#include <assert.h>
+
+#include "buffer.h"	// for Wrap
+#include "ttwinman.h"
+#include "codeconv.h"
+#include "unicode.h"
+#include "language.h"	// for JIS2SJIS()
+
+#include "charset.h"
+
+static BOOL KanjiIn;				// TRUE = MBCS\x82\xCC1byte\x96ڂ\xF0\x8E\xF3\x90M\x82\xB5\x82Ă\xA2\x82\xE9
+static BOOL EUCkanaIn, EUCsupIn;
+static int  EUCcount;
+#if 0
+static BOOL Special;
+#endif
+
+/* GL for single shift 2/3 */
+static int GLtmp;
+/* single shift 2/3 flag */
+static BOOL SSflag;
+/* JIS -> SJIS conversion flag */
+static BOOL ConvJIS;
+static WORD Kanji;
+BOOL Fallbacked;
+
+typedef struct {
+	/* GL, GR code group */
+	int Glr[2];
+	/* G0, G1, G2, G3 code group */
+	int Gn[4];
+} VttermKanjiWork;
+
+static VttermKanjiWork KanjiWork;
+
+
+/**
+ *	ISO2022\x97p\x83\x8F\x81[\x83N\x82\xF0\x8F\x89\x8A\x{227B0B7}\x82\xE9
+ */
+static void CharSetInit2(VttermKanjiWork *w)
+{
+	if (ts.Language==IdJapanese) {
+		w->Gn[0] = IdASCII;
+		w->Gn[1] = IdKatakana;
+		w->Gn[2] = IdKatakana;
+		w->Gn[3] = IdKanji;
+		w->Glr[0] = 0;
+		if ((ts.KanjiCode==IdJIS) && (ts.JIS7Katakana==0))
+			w->Glr[1] = 2;	// 8-bit katakana
+		else
+			w->Glr[1] = 3;
+	}
+	else {
+		w->Gn[0] = IdASCII;
+		w->Gn[1] = IdSpecial;
+		w->Gn[2] = IdASCII;
+		w->Gn[3] = IdASCII;
+		w->Glr[0] = 0;
+		w->Glr[1] = 0;
+	}
+}
+
+/**
+ *	\x8A\xBF\x8E\x9A\x8A֘A\x83\x8F\x81[\x83N\x82\xF0\x8F\x89\x8A\x{227B0B7}\x82\xE9
+ */
+void CharSetInit(void)
+{
+	CharSetInit2(&KanjiWork);
+	SSflag = FALSE;
+
+	KanjiIn = FALSE;
+	EUCkanaIn = FALSE;
+	EUCsupIn = FALSE;
+	ConvJIS = FALSE;
+	Fallbacked = FALSE;
+}
+
+/**
+ *	1byte\x96ڃ`\x83F\x83b\x83N
+ */
+static BOOL CheckFirstByte(BYTE b, int lang, int kanji_code)
+{
+	switch (lang) {
+		case IdKorean:
+			return __ismbblead(b, 51949);
+		case IdChinese:
+			if (kanji_code == IdCnGB2312) {
+				return __ismbblead(b, 936);
+			}
+			else if (ts.KanjiCode == IdCnBig5) {
+				return __ismbblead(b, 950);
+			}
+			break;
+		default:
+			assert(FALSE);
+			break;
+	}
+	assert(FALSE);
+	return FALSE;
+}
+/**
+ *	ts.Language == IdJapanese \x8E\x9E
+ *	1byte\x96ڃ`\x83F\x83b\x83N
+ */
+static BOOL CheckKanji(BYTE b)
+{
+	VttermKanjiWork *w = &KanjiWork;
+	BOOL Check;
+
+	if (ts.Language!=IdJapanese)
+		return FALSE;
+
+	ConvJIS = FALSE;
+
+	if (ts.KanjiCode==IdSJIS ||
+	   (ts.FallbackToCP932 && ts.KanjiCode==IdUTF8)) {
+		if ((0x80<b) && (b<0xa0) || (0xdf<b) && (b<0xfd)) {
+			Fallbacked = TRUE;
+			return TRUE; // SJIS kanji
+		}
+		if ((0xa1<=b) && (b<=0xdf)) {
+			return FALSE; // SJIS katakana
+		}
+	}
+
+	if ((b>=0x21) && (b<=0x7e)) {
+		Check = (w->Gn[w->Glr[0]] == IdKanji);
+		ConvJIS = Check;
+	}
+	else if ((b>=0xA1) && (b<=0xFE)) {
+		Check = (w->Gn[w->Glr[1]] == IdKanji);
+		if (ts.KanjiCode==IdEUC) {
+			Check = TRUE;
+		}
+		else if (ts.KanjiCode==IdJIS && ((ts.TermFlag & TF_FIXEDJIS)!=0) && (ts.JIS7Katakana==0)) {
+			Check = FALSE; // 8-bit katakana
+		}
+		ConvJIS = Check;
+	}
+	else {
+		Check = FALSE;
+	}
+
+	return Check;
+}
+
+static void PutKanji(BYTE b)
+{
+	unsigned long u32 = 0;
+
+	Kanji = Kanji + b;
+
+	// codepage\x88ꗗ
+	// https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-ucoderef/28fefe92-d66c-4b03-90a9-97b473223d43
+	switch (ts.Language) {
+	case IdJapanese:
+		if (ConvJIS) {
+			// JIS -> Shift_JIS(CP932)
+			Kanji = JIS2SJIS((WORD)(Kanji & 0x7f7f));
+		}
+		u32 = CP932ToUTF32(Kanji);
+		break;
+	case IdKorean:
+		if (ts.KanjiCode == IdKoreanCP51949) {
+			// CP51949
+			u32 = MBCP_UTF32(Kanji, 51949);
+		}
+		else {
+			assert(FALSE);
+		}
+		break;
+	case IdChinese:
+		if (ts.KanjiCode == IdCnGB2312) {
+			// CP936 GB2312
+			u32 = MBCP_UTF32(Kanji, 936);
+		}
+		else if (ts.KanjiCode == IdCnBig5) {
+			// CP950 Big5
+			u32 = MBCP_UTF32(Kanji, 950);
+		}
+		else {
+			assert(FALSE);
+		}
+		break;
+	default:
+		assert(FALSE);
+		break;
+	}
+
+	PutU32(u32);
+}
+
+static BOOL ParseFirstJP(BYTE b)
+// returns TRUE if b is processed
+//  (actually allways returns TRUE)
+{
+	VttermKanjiWork *w = &KanjiWork;
+	if (KanjiIn) {
+		if ((! ConvJIS) && (0x3F<b) && (b<0xFD) ||
+		      ConvJIS && ( (0x20<b) && (b<0x7f) ||
+		                   (0xa0<b) && (b<0xff) ))
+		{
+			PutKanji(b);
+			KanjiIn = FALSE;
+			return TRUE;
+		}
+		else if ((ts.TermFlag & TF_CTRLINKANJI)==0) {
+			KanjiIn = FALSE;
+		}
+		else if ((b==CR) && Wrap) {
+			CarriageReturn(FALSE);
+			LineFeed(LF,FALSE);
+			Wrap = FALSE;
+		}
+	}
+
+	if (SSflag) {
+		if (w->Gn[GLtmp] == IdKanji) {
+			Kanji = b << 8;
+			KanjiIn = TRUE;
+			SSflag = FALSE;
+			return TRUE;
+		}
+		else if (w->Gn[GLtmp] == IdKatakana) {
+			b = b | 0x80;
+		}
+
+		PutChar(b);
+		SSflag = FALSE;
+		return TRUE;
+	}
+
+	if ((!EUCsupIn) && (!EUCkanaIn) && (!KanjiIn) && CheckKanji(b)) {
+		Kanji = b << 8;
+		KanjiIn = TRUE;
+		return TRUE;
+	}
+
+	if (b<=US) {
+		ParseControl(b);
+	}
+	else if (b==0x20) {
+		PutChar(b);
+	}
+	else if ((b>=0x21) && (b<=0x7E)) {
+		if (EUCsupIn) {
+			EUCcount--;
+			EUCsupIn = (EUCcount==0);
+			return TRUE;
+		}
+
+		if ((w->Gn[w->Glr[0]] == IdKatakana) || EUCkanaIn) {
+			b = b | 0x80;
+			EUCkanaIn = FALSE;
+			{
+				// b\x82\xCDsjis\x82̔\xBC\x8Ap\x83J\x83^\x83J\x83i
+				unsigned long u32 = CP932ToUTF32(b);
+				PutU32(u32);
+			}
+			return TRUE;
+		}
+		PutChar(b);
+	}
+	else if (b==0x7f) {
+		return TRUE;
+	}
+	else if ((b>=0x80) && (b<=0x8D)) {
+		ParseControl(b);
+	}
+	else if (b==0x8E) { // SS2
+		switch (ts.KanjiCode) {
+		case IdEUC:
+			if (ts.ISO2022Flag & ISO2022_SS2) {
+				EUCkanaIn = TRUE;
+			}
+			break;
+		case IdUTF8:
+			PutChar('?');
+			break;
+		default:
+			ParseControl(b);
+		}
+	}
+	else if (b==0x8F) { // SS3
+		switch (ts.KanjiCode) {
+		case IdEUC:
+			if (ts.ISO2022Flag & ISO2022_SS3) {
+				EUCcount = 2;
+				EUCsupIn = TRUE;
+			}
+			break;
+		case IdUTF8:
+			PutChar('?');
+			break;
+		default:
+			ParseControl(b);
+		}
+	}
+	else if ((b>=0x90) && (b<=0x9F)) {
+		ParseControl(b);
+	}
+	else if (b==0xA0) {
+		PutChar(0x20);
+	}
+	else if ((b>=0xA1) && (b<=0xFE)) {
+		if (EUCsupIn) {
+			EUCcount--;
+			EUCsupIn = (EUCcount==0);
+			return TRUE;
+		}
+
+		if ((w->Gn[w->Glr[1]] != IdASCII) ||
+		    (ts.KanjiCode==IdEUC) && EUCkanaIn ||
+		    (ts.KanjiCode==IdSJIS) ||
+		    (ts.KanjiCode==IdJIS) &&
+		    (ts.JIS7Katakana==0) &&
+		    ((ts.TermFlag & TF_FIXEDJIS)!=0)) {
+			// b\x82\xCDsjis\x82̔\xBC\x8Ap\x83J\x83^\x83J\x83i
+			unsigned long u32 = CP932ToUTF32(b);
+			PutU32(u32);
+		} else {
+			if (w->Gn[w->Glr[1]] == IdASCII) {
+				b = b & 0x7f;
+			}
+			PutChar(b);
+		}
+		EUCkanaIn = FALSE;
+	}
+	else {
+		PutChar(b);
+	}
+
+	return TRUE;
+}
+
+static BOOL ParseFirstKR(BYTE b)
+// returns TRUE if b is processed
+//  (actually allways returns TRUE)
+{
+	VttermKanjiWork *w = &KanjiWork;
+	if (KanjiIn) {
+		if ((0x41<=b) && (b<=0x5A) ||
+		    (0x61<=b) && (b<=0x7A) ||
+		    (0x81<=b) && (b<=0xFE))
+		{
+			PutKanji(b);
+			KanjiIn = FALSE;
+			return TRUE;
+		}
+		else if ((ts.TermFlag & TF_CTRLINKANJI)==0) {
+			KanjiIn = FALSE;
+		}
+		else if ((b==CR) && Wrap) {
+			CarriageReturn(FALSE);
+			LineFeed(LF,FALSE);
+			Wrap = FALSE;
+		}
+	}
+
+	if ((!KanjiIn) && CheckFirstByte(b, ts.Language, ts.KanjiCode)) {
+		Kanji = b << 8;
+		KanjiIn = TRUE;
+		return TRUE;
+	}
+
+	if (b<=US) {
+		ParseControl(b);
+	}
+	else if (b==0x20) {
+		PutChar(b);
+	}
+	else if ((b>=0x21) && (b<=0x7E)) {
+//		if (Gn[Glr[0]] == IdKatakana) {
+//			b = b | 0x80;
+//		}
+		PutChar(b);
+	}
+	else if (b==0x7f) {
+		return TRUE;
+	}
+	else if ((0x80<=b) && (b<=0x9F)) {
+		ParseControl(b);
+	}
+	else if (b==0xA0) {
+		PutChar(0x20);
+	}
+	else if ((b>=0xA1) && (b<=0xFE)) {
+		if (w->Gn[w->Glr[1]] == IdASCII) {
+			b = b & 0x7f;
+		}
+		PutChar(b);
+	}
+	else {
+		PutChar(b);
+	}
+
+	return TRUE;
+}
+
+static BOOL ParseFirstCn(BYTE b)
+// returns TRUE if b is processed
+//  (actually allways returns TRUE)
+{
+	VttermKanjiWork *w = &KanjiWork;
+	if (KanjiIn) {
+		// TODO
+		if ((0x40<=b) && (b<=0x7e) ||
+		    (0xa1<=b) && (b<=0xFE))
+		{
+			PutKanji(b);
+			KanjiIn = FALSE;
+			return TRUE;
+		}
+		else if ((ts.TermFlag & TF_CTRLINKANJI)==0) {
+			KanjiIn = FALSE;
+		}
+		else if ((b==CR) && Wrap) {
+			CarriageReturn(FALSE);
+			LineFeed(LF,FALSE);
+			Wrap = FALSE;
+		}
+	}
+
+	if ((!KanjiIn) && CheckFirstByte(b, ts.Language, ts.KanjiCode)) {
+		Kanji = b << 8;
+		KanjiIn = TRUE;
+		return TRUE;
+	}
+
+	if (b<=US) {
+		ParseControl(b);
+	}
+	else if (b==0x20) {
+		PutChar(b);
+	}
+	else if ((b>=0x21) && (b<=0x7E)) {
+//		if (Gn[Glr[0]] == IdKatakana) {
+//			b = b | 0x80;
+//		}
+		PutChar(b);
+	}
+	else if (b==0x7f) {
+		return TRUE;
+	}
+	else if ((0x80<=b) && (b<=0x9F)) {
+		ParseControl(b);
+	}
+	else if (b==0xA0) {
+		PutChar(0x20);
+	}
+	else if ((b>=0xA1) && (b<=0xFE)) {
+		if (w->Gn[w->Glr[1]] == IdASCII) {
+			b = b & 0x7f;
+		}
+		PutChar(b);
+	}
+	else {
+		PutChar(b);
+	}
+
+	return TRUE;
+}
+
+static void ParseASCII(BYTE b)
+{
+	if (SSflag) {
+		PutChar(b);
+		SSflag = FALSE;
+		return;
+	}
+
+	if (b<=US) {
+		ParseControl(b);
+	} else if ((b>=0x20) && (b<=0x7E)) {
+		//Kanji = 0;
+		//PutKanji(b);
+		PutChar(b);
+	} else if ((b==0x8E) || (b==0x8F)) {
+		PutChar('?');
+	} else if ((b>=0x80) && (b<=0x9F)) {
+		ParseControl(b);
+	} else if (b>=0xA0) {
+		//Kanji = 0;
+		//PutKanji(b);
+		PutChar(b);
+	}
+}
+
+// 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)
+static BOOL ParseFirstUTF8(BYTE b)
+{
+	static BYTE buf[4];
+	static int count = 0;
+
+	unsigned int code;
+	int i;
+
+	if (ts.FallbackToCP932 && Fallbacked) {
+		return ParseFirstJP(b);
+	}
+
+	// UTF-8\x83G\x83\x93\x83R\x81[\x83h
+	//	Unicode					1byte,		  2byte,	   3byte, 		  4byte
+	//	U+0000  ... U+007f		0x00 .. 0x7f
+	//	U+0080  ... U+07ff		0xc2 .. 0xdf, 0x80 .. 0xbf
+	//	U+0800  ... U+ffff		0xe0 .. 0xef, 0x80 .. 0xbf, 0x80 .. 0xbf
+	//	U+10000 ... U+10ffff	0xf0 .. 0xf4, 0x80 .. 0xbf, 0x80 .. 0xbf, 0x80 .. 0xbf
+	// UTF-8\x82Ńf\x83R\x81[\x83h\x82ł\xAB\x82Ȃ\xA2\x8Fꍇ
+	//	- 1byte\x96\xDA
+	//		- C1(0x80 - 0x9f)
+	//		- 0xa0 - 0xc1
+	//		- 0xf5 - 0xff
+	//	- 2byte\x96ڈȍ~
+	//		- 0x00 - 0x7f
+	//		- 0xc0 - 0xff
+
+	// 1byte(7bit)
+	if (count == 0) {
+		if ((b & 0x80) == 0x00) {
+			// 1byte(7bit)
+			//		0x7f\x88ȉ\xBA, \x82̂Ƃ\xAB\x81A\x82\xBB\x82̂܂܏o\x97\xCD
+			ParseASCII(b);
+			return TRUE;
+		}
+		if ((b & 0x40) == 0x00 || b >= 0xf6 ) {
+			// UTF-8\x82\xC51byte\x82ɏo\x8C\xBB\x82\xB5\x82Ȃ\xA2\x83R\x81[\x83h\x82̂Ƃ\xAB\x81A\x82\xBB\x82̂܂܏o\x97\xCD
+			//	0x40 = 0b1011_1111, 0b10xx_xxxx\x82Ƃ\xA2\x82\xA4bit\x83p\x83^\x81[\x83\x93\x82ɂ͂Ȃ\xE7\x82Ȃ\xA2
+			//  0xf6 \x88ȏ\xE3\x82̂Ƃ\xAB U+10FFFF\x82\xE6\x82\xE8\x91傫\x82\xAD\x82Ȃ\xE9
+			PutU32(b);
+			return TRUE;
+		}
+		// 1byte\x96ڕۑ\xB6
+		buf[count++] = b;
+		return TRUE;
+	}
+
+	// 2byte(11bit)
+	if ((buf[0] & 0xe0) == 0xc0) {
+		code = 0;
+		if((b & 0xc0) == 0x80) {
+			// 5bit + 6bit
+			code = ((buf[0] & 0x1f) << 6) | (b & 0x3f);
+			if (code < 0x80) {
+				// 11bit\x8Eg\x82\xC1\x82\xC47bit\x88ȉ\xBA\x82̎\x9E\x81AUTF-8\x82̏璷\x82ȕ\\x8C\xBB
+				code = 0;
+			}
+		}
+		if (code == 0){
+			// \x82\xBB\x82̂܂܏o\x97\xCD
+			PutU32(buf[0]);
+			PutU32(b);
+			count = 0;
+			return TRUE;
+		}
+		else {
+			PutU32(code);
+			count = 0;
+			return TRUE;
+		}
+	}
+
+	// 2byte\x96ڈȍ~\x95ۑ\xB6
+	buf[count++] = b;
+
+	// 3byte(16bit)
+	if ((buf[0] & 0xf0) == 0xe0) {
+		if(count < 3) {
+			return TRUE;
+		}
+		code = 0;
+		if ((buf[1] & 0xc0) == 0x80 && (buf[2] & 0xc0) == 0x80) {
+			// 4bit + 6bit + 6bit
+			code = ((buf[0] & 0xf) << 12);
+			code |= ((buf[1] & 0x3f) << 6);
+			code |= ((buf[2] & 0x3f));
+			if (code < 0x800) {
+				// 16bit\x8Eg\x82\xC1\x82\xC411bit\x88ȉ\xBA\x82̂Ƃ\xAB\x81AUTF-8\x82̏璷\x82ȕ\\x8C\xBB
+				code = 0;
+			}
+		}
+		if (code == 0) {
+			// \x82\xBB\x82̂܂܏o\x97\xCD
+			PutU32(buf[0]);
+			PutU32(buf[1]);
+			PutU32(buf[2]);
+			count = 0;
+			return TRUE;
+		} else {
+			PutU32(code);
+			count = 0;
+			return TRUE;
+		}
+	}
+
+	// 4byte(21bit)
+	if ((buf[0] & 0xf8) == 0xf0) {
+		if(count < 4) {
+			return TRUE;
+		}
+		code = 0;
+		if ((buf[1] & 0xc0) == 0x80 && (buf[2] & 0xc0) == 0x80 && (buf[3] & 0xc0) == 0x80) {
+			// 3bit + 6bit + 6bit + 6bit
+			code = ((buf[0] & 0x07) << 18);
+			code |= ((buf[1] & 0x3f) << 12);
+			code |= ((buf[2] & 0x3f) << 6);
+			code |= (buf[3] & 0x3f);
+			if (code < 0x10000) {
+				// 21bit\x8Eg\x82\xC1\x82\xC416bit\x88ȉ\xBA\x82̂Ƃ\xAB\x81AUTF-8\x82̏璷\x82ȕ\\x8C\xBB
+				code = 0;
+			}
+		}
+		if (code == 0) {
+			// \x82\xBB\x82̂܂܏o\x97\xCD
+			PutU32(buf[0]);
+			PutU32(buf[1]);
+			PutU32(buf[2]);
+			PutU32(buf[3]);
+			count = 0;
+			return TRUE;
+		} else {
+			PutU32(code);
+			count = 0;
+			return TRUE;
+		}
+	}
+
+	// \x82\xB1\x82\xB1\x82ɂ͗\x88\x82Ȃ\xA2
+	assert(FALSE);
+
+	for (i = 0; i < count; i++) {
+		ParseASCII(buf[i]);
+	}
+	count = 0;
+	return TRUE;
+}
+
+static BOOL ParseFirstRus(BYTE b)
+// returns if b is processed
+{
+	if (b>=128) {
+		PutChar(b);
+		return TRUE;
+	}
+	return FALSE;
+}
+
+static BOOL ParseEnglish(BYTE b)
+{
+	unsigned short u16 = 0;
+	int part = KanjiCodeToISO8859Part(ts.KanjiCode);
+	int r = UnicodeFromISO8859(part, b, &u16);
+	if (r == 0) {
+		return FALSE;
+	}
+	if (u16 < 0x100) {
+		ParseASCII((BYTE)u16);
+	}
+	else {
+		PutU32(u16);
+	}
+	return TRUE;
+}
+
+void ParseFirst(BYTE b) {
+	switch (ts.Language) {
+	  case IdUtf8:
+		  ParseFirstUTF8(b);
+		return;
+
+	  case IdJapanese:
+		switch (ts.KanjiCode) {
+		  case IdUTF8:
+			  if (ParseFirstUTF8(b)) {
+				return;
+			}
+			break;
+		  default:
+			if (ParseFirstJP(b))  {
+				return;
+			}
+		}
+		break;
+
+	  case IdKorean:
+		switch (ts.KanjiCode) {
+		  case IdUTF8:
+			if (ParseFirstUTF8(b)) {
+				return;
+			}
+			break;
+		  default:
+			if (ParseFirstKR(b))  {
+				return;
+			}
+		}
+		break;
+
+	  case IdRussian:
+		if (ParseFirstRus(b)) {
+			return;
+		}
+		break;
+
+	case IdChinese:
+		switch (ts.KanjiCode) {
+		case IdUTF8:
+			if (ParseFirstUTF8(b)) {
+				return;
+			}
+			break;
+		default:
+			if (ParseFirstCn(b)) {
+				return;
+			}
+		}
+		break;
+	case IdEnglish: {
+		if (ParseEnglish(b)) {
+			return;
+		}
+		break;
+	}
+	}
+
+	if (SSflag) {
+		PutChar(b);
+		SSflag = FALSE;
+		return;
+	}
+
+	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);
+}
+
+/**
+ *	\x8Ew\x8E\xA6(Designate)
+ *
+ *	@param	Gn			0/1/2/3 = G0/G1/G2/G3
+ *	@param	codeset		IdASCII	   0
+ *						IdKatakana 1
+ *						IdKanji	   2
+ *						IdSpecial  3
+ */
+void CharSet2022Designate(int gn, int cs)
+{
+	VttermKanjiWork *w = &KanjiWork;
+	w->Gn[gn] = cs;
+}
+
+/**
+ *	\x8CĂяo\x82\xB5(Invoke)
+ *	@param	glr				0/1 = GL/GR (Locking shift\x8E\x9E\x82̂ݗL\x8C\xF8)
+ *	@param	gn				0/1/2/3 = G0/G1/G2/G3
+ *	@param	single_shift	FALSE	Locking shift
+ *							TRUE	Single shift
+ */
+void CharSet2022Invoke(int glr, int gn, BOOL single_shift)
+{
+	VttermKanjiWork *w = &KanjiWork;
+	if (single_shift == FALSE) {
+		// Locking shift
+		w->Glr[glr] = gn;
+	}
+	else {
+		// Single shift
+		GLtmp = gn;
+		SSflag = TRUE;
+	}
+}
+
+/**
+ *	DEC\x93\xC1\x8E\xEA\x83t\x83H\x83\x93\x83g(Tera Special font)
+ *	0140(0x60) ... 0176(0x7f) \x82Ɍr\x90\xFC\x82ŃA\x83T\x83C\x83\x93\x82\xB3\x82\xEA\x82Ă\xA2\x82\xE9
+ *	<ESC>(0 \x82Ƃ\xA2\x82\xA4\x93\xC1\x8E\xEA\x82ȃG\x83X\x83P\x81[\x83v\x83V\x81[\x83P\x83\x93\x83X\x82Œ\xE8\x8B`
+ *	about/emulations.html
+ *
+ *	@param	b		\x83R\x81[\x83h
+ */
+BOOL CharSetIsSpecial(BYTE b)
+{
+	VttermKanjiWork *w = &KanjiWork;
+	BOOL SpecialNew = FALSE;
+
+	if ((b>0x5F) && (b<0x80)) {
+		if (SSflag)
+			SpecialNew = (w->Gn[GLtmp]==IdSpecial);
+		else
+			SpecialNew = (w->Gn[w->Glr[0]]==IdSpecial);
+	}
+	else if (b>0xDF) {
+		if (SSflag)
+			SpecialNew = (w->Gn[GLtmp]==IdSpecial);
+		else
+			SpecialNew = (w->Gn[w->Glr[1]]==IdSpecial);
+	}
+
+	return SpecialNew;
+}
+
+static void CharSetSaveStateLow(CharSetState *state, const VttermKanjiWork *w)
+{
+	int i;
+	state->infos[0] = w->Glr[0];
+	state->infos[1] = w->Glr[1];
+	for (i=0 ; i<=3; i++) {
+		state->infos[2 + i] = w->Gn[i];
+	}
+}
+
+/**
+ *	\x8F\xF3\x91Ԃ\xF0\x95ۑ\xB6\x82\xB7\x82\xE9
+ */
+void CharSetSaveState(CharSetState *state)
+{
+	VttermKanjiWork *w = &KanjiWork;
+	CharSetSaveStateLow(state, w);
+}
+
+/**
+ *	\x8F\xF3\x91Ԃ𕜋A\x82\xB7\x82\xE9
+ */
+void CharSetLoadState(const CharSetState *state)
+{
+	VttermKanjiWork *w = &KanjiWork;
+	int i;
+	w->Glr[0] = state->infos[0];
+	w->Glr[1] = state->infos[1];
+	for (i=0 ; i<=3; i++) {
+		w->Gn[i] = state->infos[2 + i];
+	}
+}

Added: branches/input_charset/teraterm/teraterm/charset.h
===================================================================
--- branches/input_charset/teraterm/teraterm/charset.h	                        (rev 0)
+++ branches/input_charset/teraterm/teraterm/charset.h	2023-06-03 16:55:29 UTC (rev 10731)
@@ -0,0 +1,51 @@
+/*
+ * (C) 2023- 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.
+ */
+
+typedef struct {
+	int infos[6];
+} CharSetState;
+
+extern BOOL Fallbacked;
+
+// input
+void ParseFirst(BYTE b);
+
+// output buffer
+void PutChar(BYTE b);
+void PutU32(unsigned int code);
+void CarriageReturn(BOOL logFlag);
+void LineFeed(BYTE b, BOOL logFlag);
+void ParseControl(BYTE b);
+
+// control
+void CharSetInit(void);
+void CharSet2022Designate(int gn, int cs);
+void CharSet2022Invoke(int glr, int gn, BOOL single_shift);
+BOOL CharSetIsSpecial(BYTE b);
+void CharSetSaveState(CharSetState *state);
+void CharSetLoadState(const CharSetState *state);

Modified: branches/input_charset/teraterm/teraterm/ttermpro.v16.vcxproj
===================================================================
--- branches/input_charset/teraterm/teraterm/ttermpro.v16.vcxproj	2023-06-03 16:53:36 UTC (rev 10730)
+++ branches/input_charset/teraterm/teraterm/ttermpro.v16.vcxproj	2023-06-03 16:55:29 UTC (rev 10731)
@@ -160,6 +160,7 @@
     <ClCompile Include="addsetting.cpp" />
     <ClCompile Include="broadcast.cpp" />
     <ClCompile Include="buffer.c" />
+    <ClCompile Include="charset.c" />
     <ClCompile Include="checkeol.cpp" />
     <ClCompile Include="clipboar.c" />
     <ClCompile Include="coding_pp.cpp" />
@@ -220,6 +221,7 @@
     <ClInclude Include="..\ttpset\ttset.h" />
     <ClInclude Include="..\ttpset\ttset_i.h" />
     <ClInclude Include="broadcast.h" />
+    <ClInclude Include="charset.h" />
     <ClInclude Include="checkeol.h" />
     <ClInclude Include="coding_pp.h" />
     <ClInclude Include="coding_pp_res.h" />

Modified: branches/input_charset/teraterm/teraterm/ttermpro.v16.vcxproj.filters
===================================================================
--- branches/input_charset/teraterm/teraterm/ttermpro.v16.vcxproj.filters	2023-06-03 16:53:36 UTC (rev 10730)
+++ branches/input_charset/teraterm/teraterm/ttermpro.v16.vcxproj.filters	2023-06-03 16:55:29 UTC (rev 10731)
@@ -225,6 +225,9 @@
     <ClCompile Include="scp.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="charset.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <Image Include="..\..\cygterm\cygterm.ico">
@@ -519,5 +522,8 @@
     <ClInclude Include="scp.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="charset.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
 </Project>
\ No newline at end of file

Modified: branches/input_charset/teraterm/teraterm/ttermpro.v17.vcxproj
===================================================================
--- branches/input_charset/teraterm/teraterm/ttermpro.v17.vcxproj	2023-06-03 16:53:36 UTC (rev 10730)
+++ branches/input_charset/teraterm/teraterm/ttermpro.v17.vcxproj	2023-06-03 16:55:29 UTC (rev 10731)
@@ -160,6 +160,7 @@
     <ClCompile Include="addsetting.cpp" />
     <ClCompile Include="broadcast.cpp" />
     <ClCompile Include="buffer.c" />
+    <ClCompile Include="charset.c" />
     <ClCompile Include="checkeol.cpp" />
     <ClCompile Include="clipboar.c" />
     <ClCompile Include="coding_pp.cpp" />
@@ -220,6 +221,7 @@
     <ClInclude Include="..\ttpset\ttset.h" />
     <ClInclude Include="..\ttpset\ttset_i.h" />
     <ClInclude Include="broadcast.h" />
+    <ClInclude Include="charset.h" />
     <ClInclude Include="checkeol.h" />
     <ClInclude Include="coding_pp.h" />
     <ClInclude Include="coding_pp_res.h" />

Modified: branches/input_charset/teraterm/teraterm/ttermpro.v17.vcxproj.filters
===================================================================
--- branches/input_charset/teraterm/teraterm/ttermpro.v17.vcxproj.filters	2023-06-03 16:53:36 UTC (rev 10730)
+++ branches/input_charset/teraterm/teraterm/ttermpro.v17.vcxproj.filters	2023-06-03 16:55:29 UTC (rev 10731)
@@ -225,6 +225,9 @@
     <ClCompile Include="scp.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="charset.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <Image Include="..\..\cygterm\cygterm.ico">
@@ -519,5 +522,8 @@
     <ClInclude Include="scp.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="charset.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
 </Project>
\ No newline at end of file

Modified: branches/input_charset/teraterm/teraterm/vtterm.c
===================================================================
--- branches/input_charset/teraterm/teraterm/vtterm.c	2023-06-03 16:53:36 UTC (rev 10730)
+++ branches/input_charset/teraterm/teraterm/vtterm.c	2023-06-03 16:55:29 UTC (rev 10731)
@@ -54,10 +54,10 @@
 #include "ttime.h"
 #include "clipboar.h"
 #include "codeconv.h"
-#include "unicode.h"
 #include "ttdde.h"
 #include "checkeol.h"
 #include "asprintf.h"
+#include "charset.h"
 
 #include "vtterm.h"
 
@@ -64,8 +64,6 @@
 #include "unicode_test.h"
 // #define DEBUG_DUMP_INPUTCODE 1
 
-static void ParseFirst(BYTE b);
-
 #define Accept8BitCtrl ((VTlevel >= 2) && (ts.TermFlag & TF_ACCEPT8BITCTRL))
 
   /* Parsing modes */
@@ -123,7 +121,7 @@
 typedef struct {
 	int CursorX, CursorY;
 	TCharAttr Attr;
-	int Glr[2], Gn[4]; // G0-G3, GL & GR
+	CharSetState CharSetState;
 	BOOL AutoWrapMode;
 	BOOL RelativeOrgMode;
 } TStatusBuff;
@@ -139,9 +137,6 @@
 static TStatusBuff SBuff1, SBuff2, SBuff3;
 
 static BOOL ESCFlag, JustAfterESC;
-static BOOL KanjiIn;				// TRUE = MBCS\x82\xCC1byte\x96ڂ\xF0\x8E\xF3\x90M\x82\xB5\x82Ă\xA2\x82\xE9
-static BOOL EUCkanaIn, EUCsupIn;
-static int  EUCcount;
 static BOOL Special;
 
 static int Param[NParamMax+1];
@@ -164,19 +159,6 @@
 /* user defined keys */
 static BOOL WaitKeyId, WaitHi;
 
-/* GL, GR code group */
-static int Glr[2];
-/* G0, G1, G2, G3 code group */
-static int Gn[4];
-/* GL for single shift 2/3 */
-static int GLtmp;
-/* single shift 2/3 flag */
-static BOOL SSflag;
-/* JIS -> SJIS conversion flag */
-static BOOL ConvJIS;
-static WORD Kanji;
-static BOOL Fallbacked;
-
 // variables for status line mode
 static int StatusX=0;
 static BOOL StatusWrap=FALSE;
@@ -223,7 +205,7 @@
 
 static vtterm_work_t vtterm_work;
 
-void ClearParams()
+static void ClearParams(void)
 {
 	ICount = 0;
 	NParam = 1;
@@ -232,54 +214,72 @@
 	Prv = 0;
 }
 
-void ResetSBuffer(PStatusBuff sbuff)
+static void SaveCursorBuf(PStatusBuff Buff)
 {
-	sbuff->CursorX = 0;
-	sbuff->CursorY = 0;
-	sbuff->Attr = DefCharAttr;
-	if (ts.Language==IdJapanese) {
-		sbuff->Gn[0] = IdASCII;
-		sbuff->Gn[1] = IdKatakana;
-		sbuff->Gn[2] = IdKatakana;
-		sbuff->Gn[3] = IdKanji;
-		sbuff->Glr[0] = 0;
-		if ((ts.KanjiCode==IdJIS) && (ts.JIS7Katakana==0))
-			sbuff->Glr[1] = 2;	// 8-bit katakana
-		else
-			sbuff->Glr[1] = 3;
-	}
-	else {
-		sbuff->Gn[0] = IdASCII;
-		sbuff->Gn[1] = IdSpecial;
-		sbuff->Gn[2] = IdASCII;
-		sbuff->Gn[3] = IdASCII;
-		sbuff->Glr[0] = 0;
-		sbuff->Glr[1] = 0;
-	}
-	sbuff->AutoWrapMode = TRUE;
-	sbuff->RelativeOrgMode = FALSE;
+	Buff->CursorX = CursorX;
+	Buff->CursorY = CursorY;
+	Buff->Attr = CharAttr;
+
+	CharSetSaveState(&Buff->CharSetState);
+	Buff->AutoWrapMode = AutoWrapMode;
+	Buff->RelativeOrgMode = RelativeOrgMode;
 }
 
-void ResetAllSBuffers()
+static void SaveCursor()
 {
-	ResetSBuffer(&SBuff1);
-	// copy SBuff1 to SBuff2
-	SBuff2 = SBuff1;
-	SBuff3 = SBuff1;
+	PStatusBuff Buff;
+
+	if (isCursorOnStatusLine)
+		Buff = &SBuff2; // for status line
+	else if (AltScr)
+		Buff = &SBuff3; // for alternate screen
+	else
+		Buff = &SBuff1; // for main screen
+
+	SaveCursorBuf(Buff);
 }
 
-void ResetCurSBuffer()
+static void RestoreCursorBuff(PStatusBuff Buff)
 {
+	if (Buff->CursorX > NumOfColumns-1)
+		Buff->CursorX = NumOfColumns-1;
+	if (Buff->CursorY > NumOfLines-1-StatusLine)
+		Buff->CursorY = NumOfLines-1-StatusLine;
+	MoveCursor(Buff->CursorX, Buff->CursorY);
+
+	CharAttr = Buff->Attr;
+	BuffSetCurCharAttr(CharAttr);
+	CharSetLoadState(&Buff->CharSetState);
+
+	AutoWrapMode = Buff->AutoWrapMode;
+	RelativeOrgMode = Buff->RelativeOrgMode;
+}
+
+static void RestoreCursor()
+{
 	PStatusBuff Buff;
 
-	if (AltScr) {
-		Buff = &SBuff3; // Alternate screen buffer
-	}
-	else {
-		Buff = &SBuff1; // Normal screen buffer
-	}
-	ResetSBuffer(Buff);
-	SBuff2 = *Buff;
+	UpdateStr();
+
+	if (isCursorOnStatusLine)
+		Buff = &SBuff2; // for status line
+	else if (AltScr)
+		Buff = &SBuff3; // for alternate screen
+	else
+		Buff = &SBuff1; // for main screen
+
+	if (Buff->CursorX > NumOfColumns-1)
+		Buff->CursorX = NumOfColumns-1;
+	if (Buff->CursorY > NumOfLines-1-StatusLine)
+		Buff->CursorY = NumOfLines-1-StatusLine;
+	MoveCursor(Buff->CursorX, Buff->CursorY);
+
+	CharAttr = Buff->Attr;
+	BuffSetCurCharAttr(CharAttr);
+	CharSetLoadState(&Buff->CharSetState);
+
+	AutoWrapMode = Buff->AutoWrapMode;
+	RelativeOrgMode = Buff->RelativeOrgMode;
 }
 
 void ResetTerminal() /*reset variables but don't update screen */
@@ -322,6 +322,10 @@
 
 	/* Character sets */
 	ResetCharSet();
+	// status buffers
+	SaveCursorBuf(&SBuff1);
+	SaveCursorBuf(&SBuff2);
+	SaveCursorBuf(&SBuff3);
 
 	/* ESC flag for device control sequence */
 	ESCFlag = FALSE;
@@ -334,9 +338,6 @@
 	/* Clear printer mode */
 	PrinterMode = FALSE;
 
-	// status buffers
-	ResetAllSBuffers();
-
 	// Alternate Screen Buffer
 	AltScr = FALSE;
 
@@ -375,34 +376,10 @@
 
 void ResetCharSet()
 {
-	if (ts.Language==IdJapanese) {
-		Gn[0] = IdASCII;
-		Gn[1] = IdKatakana;
-		Gn[2] = IdKatakana;
-		Gn[3] = IdKanji;
-		Glr[0] = 0;
-		if ((ts.KanjiCode==IdJIS) && (ts.JIS7Katakana==0))
-			Glr[1] = 2;	// 8-bit katakana
-		else
-			Glr[1] = 3;
-	}
-	else {
-		Gn[0] = IdASCII;
-		Gn[1] = IdSpecial;
-		Gn[2] = IdASCII;
-		Gn[3] = IdASCII;
-		Glr[0] = 0;
-		Glr[1] = 0;
+	if (ts.Language != IdJapanese) {
 		cv.SendCode = IdASCII;
 		cv.EchoCode = IdASCII;
 	}
-	/* Kanji flag */
-	KanjiIn = FALSE;
-	EUCkanaIn = FALSE;
-	EUCsupIn = FALSE;
-	SSflag = FALSE;
-	ConvJIS = FALSE;
-	Fallbacked = FALSE;
 
 	cv.Language = ts.Language;
 	cv.CRSend = ts.CRSend;
@@ -412,6 +389,8 @@
 	cv.JIS7KatakanaSend = ts.JIS7KatakanaSend;
 	cv.KanjiIn = ts.KanjiIn;
 	cv.KanjiOut = ts.KanjiOut;
+
+	CharSetInit();
 }
 
 void ResetKeypadMode(BOOL DisabledModeOnly)
@@ -422,7 +401,7 @@
 		AppliCursorMode = FALSE;
 }
 
-void MoveToMainScreen()
+static void MoveToMainScreen(void)
 {
 	StatusX = CursorX;
 	StatusWrap = Wrap;
@@ -586,7 +565,8 @@
 	MainBottom = NumOfLines-StatusLine-1;
 }
 
-void SendCSIstr(char *str, int len) {
+static void SendCSIstr(char *str, int len)
+{
 	size_t l;
 
 	if (str == NULL || len < 0)
@@ -607,7 +587,8 @@
 	CommBinaryOut(&cv, str, l);
 }
 
-static void SendOSCstr(char *str, int len, char TermChar) {
+static void SendOSCstr(char *str, int len, char TermChar)
+{
 	size_t l;
 
 	if (str == NULL || len < 0)
@@ -638,7 +619,8 @@
 
 }
 
-void SendDCSstr(char *str, int len) {
+static void SendDCSstr(char *str, int len)
+{
 	size_t l;
 
 	if (str == NULL || len < 0)
@@ -664,7 +646,7 @@
 
 }
 
-void BackSpace()
+static void BackSpace(void)
 {
 	if (CursorX == CursorLeftM || CursorX == 0) {
 		if (CursorY > 0 && (ts.TermFlag & TF_BACKWRAP)) {
@@ -678,7 +660,7 @@
 	}
 }
 
-static void CarriageReturn(BOOL logFlag)
+void CarriageReturn(BOOL logFlag)
 {
 	if (!ts.EnableContinuedLineCopy || logFlag)
 		if (NeedsOutputBufs()) OutputLogByte(CR);
@@ -691,7 +673,7 @@
 	Fallbacked = FALSE;
 }
 
-static void LineFeed(BYTE b, BOOL logFlag)
+void LineFeed(BYTE b, BOOL logFlag)
 {
 	/* for auto print mode */
 	if ((AutoPrintMode) &&
@@ -714,7 +696,7 @@
 	Fallbacked = FALSE;
 }
 
-void Tab()
+static void Tab(void)
 {
 	if (Wrap && !ts.VTCompatTab) {
 		CarriageReturn(FALSE);
@@ -728,7 +710,7 @@
 	if (NeedsOutputBufs()) OutputLogByte(HT);
 }
 
-void RepeatChar(BYTE b, int count)
+static void RepeatChar(BYTE b, int count)
 {
 	int i;
 	BOOL SpecialNew;
@@ -740,20 +722,7 @@
 	CharAttrTmp = CharAttr;
 	LastPutCharacter = 0;
 
-	SpecialNew = FALSE;
-	if ((b>0x5F) && (b<0x80)) {
-		if (SSflag)
-			SpecialNew = (Gn[GLtmp]==IdSpecial);
-		else
-			SpecialNew = (Gn[Glr[0]]==IdSpecial);
-	}
-	else if (b>0xDF) {
-		if (SSflag)
-			SpecialNew = (Gn[GLtmp]==IdSpecial);
-		else
-			SpecialNew = (Gn[Glr[1]]==IdSpecial);
-	}
-
+	SpecialNew = CharSetIsSpecial(b);
 	if (SpecialNew != Special) {
 		UpdateStr();
 		Special = SpecialNew;
@@ -789,7 +758,7 @@
 	}
 }
 
-static void PutChar(BYTE b)
+void PutChar(BYTE b)
 {
 	BOOL SpecialNew;
 	TCharAttr CharAttrTmp;
@@ -829,20 +798,7 @@
 
 	Wrap = FALSE;
 
-	SpecialNew = FALSE;
-	if ((b>0x5F) && (b<0x80)) {
-		if (SSflag)
-			SpecialNew = (Gn[GLtmp]==IdSpecial);
-		else
-			SpecialNew = (Gn[Glr[0]]==IdSpecial);
-	}
-	else if (b>0xDF) {
-		if (SSflag)
-			SpecialNew = (Gn[GLtmp]==IdSpecial);
-		else
-			SpecialNew = (Gn[Glr[1]]==IdSpecial);
-	}
-
+	SpecialNew = CharSetIsSpecial(b);
 	if (SpecialNew != Special) {
 		UpdateStr();
 		Special = SpecialNew;
@@ -897,173 +853,8 @@
 	}
 }
 
-static void PutDecSp(BYTE b)
+static void PutDebugChar(BYTE b)
 {
-	TCharAttr CharAttrTmp;
-
-	CharAttrTmp = CharAttr;
-
-	if (PrinterMode) { // printer mode
-		WriteToPrnFile(PrintFile_, b, TRUE);
-		return;
-	}
-
-	if (Wrap) {
-		CarriageReturn(FALSE);
-		LineFeed(LF, FALSE);
-		CharAttrTmp.Attr |= ts.EnableContinuedLineCopy ? AttrLineContinued : 0;
-	}
-
-	if (NeedsOutputBufs()) OutputLogByte(b);
-/*
-	if (ts.LogTypePlainText && __isascii(b) && !isprint(b)) {
-		// ASCII\x95\xB6\x8E\x9A\x82ŁA\x94\xF1\x95\\x8E\xA6\x82ȕ\xB6\x8E\x9A\x82̓\x8D\x83O\x8D̎悵\x82Ȃ\xA2\x81B
-	} else {
-		if (NeedsOutputBufs()) OutputLogByte(b);
-	}
- */
-
-	Wrap = FALSE;
-
-	if (!Special) {
-		UpdateStr();
-		Special = TRUE;
-	}
-
-	CharAttrTmp.Attr |= AttrSpecial;
-	CharAttrTmp.AttrEx = CharAttrTmp.Attr;
-	BuffPutChar(b, CharAttrTmp, InsertMode);
-
-	if (CursorX == CursorRightM || CursorX >= NumOfColumns-1) {
-		UpdateStr();
-		Wrap = AutoWrapMode;
-	}
-	else {
-		MoveRight();
-	}
-}
-
-/**
- *	mbcs\x82\xF0\x8Fo\x97\xCD
- */
-static void PutKanji(BYTE b)
-{
-	int LineEnd;
-	TCharAttr CharAttrTmp;
-	CharAttrTmp = CharAttr;
-
-	Kanji = Kanji + b;
-
-	if (PrinterMode && DirectPrn) {
-		WriteToPrnFile(PrintFile_, HIBYTE(Kanji),FALSE);
-		WriteToPrnFile(PrintFile_, LOBYTE(Kanji),TRUE);
-		return;
-	}
-
-	if (ConvJIS)
-		Kanji = JIS2SJIS((WORD)(Kanji & 0x7f7f));
-
-	if (PrinterMode) { // printer mode
-		WriteToPrnFile(PrintFile_, HIBYTE(Kanji),FALSE);
-		WriteToPrnFile(PrintFile_, LOBYTE(Kanji),TRUE);
-		return;
-	}
-
-	if (CursorX > CursorRightM)
-		LineEnd = NumOfColumns - 1;
-	else
-		LineEnd = CursorRightM;
-
-	if (Wrap) {
-		CarriageReturn(FALSE);
-		LineFeed(LF,FALSE);
-		if (ts.EnableContinuedLineCopy) {
-			CharAttrTmp.Attr |= AttrLineContinued;
-			CharAttrTmp.AttrEx = CharAttrTmp.Attr;
-		}
-	}
-	else if (CursorX > LineEnd - 1) {
-		if (AutoWrapMode) {
-			if (ts.EnableContinuedLineCopy) {
-				CharAttrTmp.Attr |= AttrLineContinued;
-				CharAttrTmp.AttrEx = CharAttrTmp.Attr;
-				if (CursorX == LineEnd)
-					BuffPutChar(0x20, CharAttr, FALSE);
-			}
-			CarriageReturn(FALSE);
-			LineFeed(LF,FALSE);
-		}
-		else {
-			return;
-		}
-	}
-
-	Wrap = FALSE;
-
-	if (NeedsOutputBufs()) {
-		OutputLogByte(HIBYTE(Kanji));
-		OutputLogByte(LOBYTE(Kanji));
-	}
-
-	if (Special) {
-		UpdateStr();
-		Special = FALSE;
-	}
-
-	{
-		// codepage\x88ꗗ
-		// https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-ucoderef/28fefe92-d66c-4b03-90a9-97b473223d43
-		unsigned long u32 = 0;
-		switch (ts.Language) {
-		case IdJapanese:
-			// \x82\xB1\x82\xB1\x82ɗ\x88\x82\xBD\x8E\x9E\x93_\x82\xC5CP932\x82ɂȂ\xC1\x82Ă\xA2\x82\xE9
-			u32 = CP932ToUTF32(Kanji);
-			break;
-		case IdKorean:
-			if (ts.KanjiCode == IdKoreanCP51949) {
-				// CP51949
-				u32 = MBCP_UTF32(Kanji, 51949);
-			}
-			else {
-				assert(FALSE);
-			}
-			break;
-		case IdChinese:
-			if (ts.KanjiCode == IdCnGB2312) {
-				// CP936 GB2312
-				u32 = MBCP_UTF32(Kanji, 936);
-			}
-			else if (ts.KanjiCode == IdCnBig5) {
-				// CP950 Big5
-				u32 = MBCP_UTF32(Kanji, 950);
-			}
-			else {
-				assert(FALSE);
-			}
-			break;
-		default:
-			assert(FALSE);
-			break;
-		}
-		CharAttrTmp.AttrEx = CharAttrTmp.Attr;
-		BuffPutUnicode(u32, CharAttrTmp, InsertMode);
-	}
-
-	if (CursorX < LineEnd - 1) {
-		MoveRight();
-		MoveRight();
-	}
-	else {
-		if (CursorX == LineEnd - 1) {
-			MoveRight();
-		}
-		UpdateStr();
-		Wrap = AutoWrapMode;
-	}
-}
-
-void PutDebugChar(BYTE b)
-{
 	static BYTE buff[3];
 	int i;
 	BOOL svInsertMode, svAutoWrapMode;
@@ -1132,15 +923,17 @@
 			    (ts.JIS7Katakana==1) &&
 			    ((ts.TermFlag & TF_FIXEDJIS)!=0))
 			{
-				Gn[1] = IdKatakana;
+				CharSet2022Designate(1, IdKatakana);
 			}
-			Glr[0] = 1; /* LS1 */
+			/* LS1 */
+			CharSet2022Invoke(0, 1, FALSE);
 			return;
 		}
 		break;
 	case SI:
 		if ((ts.ISO2022Flag & ISO2022_SI) && ! DirectPrn) {
-			Glr[0] = 0; /* LS0 */
+			/* LS0 */
+			CharSet2022Invoke(0, 0, FALSE);
 			return;
 		}
 		break;
@@ -1169,7 +962,7 @@
 	WriteToPrnFile(PrintFile_, b, TRUE);
 }
 
-static void ParseControl(BYTE b)
+void ParseControl(BYTE b)
 {
 	if (PrinterMode) { // printer mode
 		PrnParseControl(b);
@@ -1272,15 +1065,15 @@
 			    (ts.JIS7Katakana==1) &&
 			    ((ts.TermFlag & TF_FIXEDJIS)!=0))
 			{
-				Gn[1] = IdKatakana;
+				CharSet2022Designate(1, IdKatakana);
 			}
 
-			Glr[0] = 1;
+			CharSet2022Invoke(0, 1, FALSE);
 		}
 		break;
 	case SI: /* LS0 */
 		if (ts.ISO2022Flag & ISO2022_SI) {
-			Glr[0] = 0;
+			CharSet2022Invoke(0, 0, FALSE);
 		}
 		break;
 	case DLE:
@@ -1330,14 +1123,12 @@
 		break;
 	case SS2:
 		if (ts.ISO2022Flag & ISO2022_SS2) {
-			GLtmp = 2;
-			SSflag = TRUE;
+			CharSet2022Invoke(0, 2, TRUE);
 		}
 		break;
 	case SS3:
 		if (ts.ISO2022Flag & ISO2022_SS3) {
-			GLtmp = 3;
-			SSflag = TRUE;
+			CharSet2022Invoke(0, 3, TRUE);
 		}
 		break;
 	case DCS:
@@ -1366,63 +1157,6 @@
 	}
 }
 
-void SaveCursor()
-{
-	int i;
-	PStatusBuff Buff;
-
-	if (isCursorOnStatusLine)
-		Buff = &SBuff2; // for status line
-	else if (AltScr)
-		Buff = &SBuff3; // for alternate screen
-	else
-		Buff = &SBuff1; // for main screen
-
-	Buff->CursorX = CursorX;
-	Buff->CursorY = CursorY;
-	Buff->Attr = CharAttr;
-
-	Buff->Glr[0] = Glr[0];
-	Buff->Glr[1] = Glr[1];
-	for (i=0 ; i<=3; i++)
-		Buff->Gn[i] = Gn[i];
-
-	Buff->AutoWrapMode = AutoWrapMode;
-	Buff->RelativeOrgMode = RelativeOrgMode;
-}
-
-void RestoreCursor()
-{
-	int i;
-	PStatusBuff Buff;
-
-	UpdateStr();
-
-	if (isCursorOnStatusLine)
-		Buff = &SBuff2; // for status line
-	else if (AltScr)
-		Buff = &SBuff3; // for alternate screen
-	else
-		Buff = &SBuff1; // for main screen
-
-	if (Buff->CursorX > NumOfColumns-1)
-		Buff->CursorX = NumOfColumns-1;
-	if (Buff->CursorY > NumOfLines-1-StatusLine)
-		Buff->CursorY = NumOfLines-1-StatusLine;
-	MoveCursor(Buff->CursorX, Buff->CursorY);
-
-	CharAttr = Buff->Attr;
-	BuffSetCurCharAttr(CharAttr);
-
-	Glr[0] = Buff->Glr[0];
-	Glr[1] = Buff->Glr[1];
-	for (i=0 ; i<=3; i++)
-		Gn[i] = Buff->Gn[i];
-
-	AutoWrapMode = Buff->AutoWrapMode;
-	RelativeOrgMode = Buff->RelativeOrgMode;
-}
-
 static void AnswerTerminalType(void)
 {
 	char Tmp[50];
@@ -1514,14 +1248,34 @@
 
 	switch (ICount) {
 		case 1:
+			// - ESC $ @ (01/11 02/04 04/00) (0x1b 0x24 0x40)
+			//		- G0 <- \x8B\x8CJIS\x8A\xBF\x8E\x9A
+			//		- \x8B\x8CJIS\x8A\xBF\x8E\x9A = JIS X 0208-1978 (JIS C 6226-1978)
+			// - ESC $ B (01/11 02/04 04/02) (0x1b 0x24 0x42)
+			//		- G0 <- \x90VJIS\x8A\xBF\x8E\x9A
+			//		- \x90VJIS\x8A\xBF\x8E\x9A = JIS X 0208-1990
 			if ((b=='@') || (b=='B'))
 			{
-				Gn[0] = IdKanji; /* Kanji -> G0 */
-				if ((ts.TermFlag & TF_AUTOINVOKE)!=0)
-					Glr[0] = 0; /* G0->GL */
+				/* Kanji -> G0 */
+				CharSet2022Designate(0, IdKanji);
+				if ((ts.TermFlag & TF_AUTOINVOKE)!=0) {
+					/* G0->GL */
+					CharSet2022Invoke(0, 0, FALSE);
+				}
 			}
 			break;
 		case 2:
+			// - ESC $ ( @ (01/11 02/04 02/08 04/00) (0x1b 0x24 0x28 0x40)
+			// - ESC $ ) @ (01/11 02/04 02/09 04/00) (0x1b 0x24 0x29 0x40)
+			// - ESC $ * @ (01/11 02/04 02/10 04/00) (0x1b 0x24 0x2a 0x40)
+			// - ESC $ + @ (01/11 02/04 02/11 04/00) (0x1b 0x24 0x2b 0x40)
+			//		- G0..G3 <- \x8B\x8CJIS\x8A\xBF\x8E\x9A
+			// - ESC $ ( B (01/11 02/04 02/08 04/02) (0x1b 0x24 0x28 0x42)
+			// - ESC $ ) B (01/11 02/04 02/09 04/02) (0x1b 0x24 0x29 0x42)
+			// - ESC $ * B (01/11 02/04 02/10 04/02) (0x1b 0x24 0x2a 0x42)
+			// - ESC $ + B (01/11 02/04 02/11 04/02) (0x1b 0x24 0x2b 0x42)
+			//		- G0..G3 <- \x90VJIS\x8A\xBF\x8E\x9A
+			//
 			/* Second intermediate char must be
 				 '(' or ')' or '*' or '+'. */
 			Dist = (IntChar[2]-'(') & 3; /* G0 - G3 */
@@ -1528,10 +1282,12 @@
 			if ((b=='1') || (b=='3') ||
 					(b=='@') || (b=='B'))
 			{
-				Gn[Dist] = IdKanji; /* Kanji -> G0-3 */
-				if (((ts.TermFlag & TF_AUTOINVOKE)!=0) &&
-						(Dist==0))
-					Glr[0] = 0; /* G0->GL */
+				/* Kanji -> G0-3 */
+				CharSet2022Designate(Dist, IdKanji);
+				if (((ts.TermFlag & TF_AUTOINVOKE)!=0) && (Dist==0)) {
+					/* G0->GL */
+					CharSet2022Invoke(0, 0, FALSE);
+				}
 			}
 			break;
 	}
@@ -1556,24 +1312,32 @@
 	Dist = (IntChar[1]-'(') & 3; /* G0 - G3 */
 
 	switch (b) {
-	case '0': Gn[Dist] = IdSpecial; break;
-	case '<': Gn[Dist] = IdASCII; break;
-	case '>': Gn[Dist] = IdASCII; break;
-	case 'A': Gn[Dist] = IdASCII; break;
-	case 'B': Gn[Dist] = IdASCII; break;
-	case 'H': Gn[Dist] = IdASCII; break;
+	case '0':
+		CharSet2022Designate(Dist, IdSpecial);
+		break;
+	case '<':
+	case '>':
+	case 'A':
+	case 'B':
+	case 'H':
+		CharSet2022Designate(Dist, IdASCII);
+		break;
 	case 'I':
 		if (ts.Language==IdJapanese)
-			Gn[Dist] = IdKatakana;
+			CharSet2022Designate(Dist, IdKatakana);
 		break;
-	case 'J': Gn[Dist] = IdASCII; break;
+	case 'J':
+		CharSet2022Designate(Dist, IdASCII);
+		break;
 	}
 
-	if (((ts.TermFlag & TF_AUTOINVOKE)!=0) && (Dist==0))
-		Glr[0] = 0;  /* G0->GL */
+	if (((ts.TermFlag & TF_AUTOINVOKE)!=0) && (Dist==0)) {
+		/* G0->GL */
+		CharSet2022Invoke(0, 0, FALSE);
+	}
 }
 
-void PrnParseEscape(BYTE b) // printer mode
+static void PrnParseEscape(BYTE b) // printer mode
 {
 	int i;
 
@@ -1630,7 +1394,7 @@
 	WriteToPrnFile(PrintFile_, b,TRUE);
 }
 
-void ParseEscape(BYTE b) /* b is the final char */
+static void ParseEscape(BYTE b) /* b is the final char */
 {
 	if (PrinterMode) { // printer mode
 		PrnParseEscape(b);
@@ -1678,14 +1442,12 @@
 			break;
 		case 'N': /* SS2 */
 			if (ts.ISO2022Flag & ISO2022_SS2) {
-				GLtmp = 2;
-				SSflag = TRUE;
+				CharSet2022Invoke(0, 2, TRUE);
 			}
 			break;
 		case 'O': /* SS3 */
 			if (ts.ISO2022Flag & ISO2022_SS3) {
-				GLtmp = 3;
-				SSflag = TRUE;
+				CharSet2022Invoke(0, 3, TRUE);
 			}
 			break;
 		case 'P': /* DCS */
@@ -1725,27 +1487,27 @@
 			break;
 		case 'n': /* LS2 */
 			if (ts.ISO2022Flag & ISO2022_LS2) {
-				Glr[0] = 2;
+				CharSet2022Invoke(0, 2, FALSE);
 			}
 			break;
 		case 'o': /* LS3 */
 			if (ts.ISO2022Flag & ISO2022_LS3) {
-				Glr[0] = 3;
+				CharSet2022Invoke(0, 3, FALSE);
 			}
 			break;
 		case '|': /* LS3R */
 			if (ts.ISO2022Flag & ISO2022_LS3R) {
-				Glr[1] = 3;
+				CharSet2022Invoke(1, 3, FALSE);
 			}
 			break;
 		case '}': /* LS2R */
 			if (ts.ISO2022Flag & ISO2022_LS2R) {
-				Glr[1] = 2;
+				CharSet2022Invoke(1, 2, FALSE);
 			}
 			break;
 		case '~': /* LS1R */
 			if (ts.ISO2022Flag & ISO2022_LS1R) {
-				Glr[1] = 1;
+				CharSet2022Invoke(1, 1, FALSE);
 			}
 			break;
 		}
@@ -1777,7 +1539,7 @@
 	ParseMode = ModeFirst;
 }
 
-void EscapeSequence(BYTE b)
+static void EscapeSequence(BYTE b)
 {
 	if (b<=US)
 		ParseControl(b);
@@ -1831,7 +1593,7 @@
 	BuffInsertSpace(Param[1]);
 }
 
-void CSCursorUp(BOOL AffectMargin)	// CUU / VPB
+static void CSCursorUp(BOOL AffectMargin)	// CUU / VPB
 {
 	int topMargin, NewY;
 
@@ -1849,13 +1611,13 @@
 	MoveCursor(CursorX, NewY);
 }
 
-void CSCursorUp1()			// CPL
+static void CSCursorUp1()			// CPL
 {
 	MoveCursor(CursorLeftM, CursorY);
 	CSCursorUp(TRUE);
 }
 
-void CSCursorDown(BOOL AffectMargin)	// CUD / VPR
+static void CSCursorDown(BOOL AffectMargin)	// CUD / VPR
 {
 	int bottomMargin, NewY;
 
@@ -1873,13 +1635,13 @@
 	MoveCursor(CursorX, NewY);
 }
 
-void CSCursorDown1()			// CNL
+static void CSCursorDown1()			// CNL
 {
 	MoveCursor(CursorLeftM, CursorY);
 	CSCursorDown(TRUE);
 }
 
-void CSScreenErase()
+static void CSScreenErase()
 {
 	BuffUpdateScroll();
 	switch (Param[1]) {
@@ -1927,7 +1689,7 @@
 	}
 }
 
-void CSQSelScreenErase()
+static void CSQSelScreenErase()
 {
 	BuffUpdateScroll();
 	switch (Param[1]) {
@@ -1954,7 +1716,7 @@
 	}
 }
 
-void CSInsertLine()
+static void CSInsertLine()
 {
 	// Insert lines at current position
 	int Count, YEnd;
@@ -1977,7 +1739,7 @@
 	BuffInsertLines(Count,YEnd);
 }
 
-void CSLineErase()
+static void CSLineErase()
 {
 	BuffUpdateScroll();
 	switch (Param[1]) {
@@ -2013,7 +1775,7 @@
 	}
 }
 
-void CSDeleteNLines()
+static void CSDeleteNLines()
 // Delete lines from current line
 {
 	int Count, YEnd;
@@ -2054,7 +1816,7 @@
 	BuffEraseChars(Param[1]);
 }
 
-void CSRepeatCharacter()
+static void CSRepeatCharacter()
 {
 	CheckParamVal(Param[1], NumOfColumns * NumOfLines);
 
@@ -2062,7 +1824,7 @@
 	RepeatChar(LastPutCharacter, Param[1]);
 }
 
-void CSScrollUp()
+static void CSScrollUp()
 {
 	// TODO: \x83X\x83N\x83\x8D\x81[\x83\x8B\x82̍ő\xE5\x92l\x82\xF0\x92[\x96\x96\x8Ds\x90\x94\x82ɐ\xA7\x8C\xC0\x82\xB7\x82ׂ\xAB\x82\xA9\x97v\x8C\x9F\x93\xA2
 	CheckParamVal(Param[1], INT_MAX);
@@ -2071,7 +1833,7 @@
 	BuffRegionScrollUpNLines(Param[1]);
 }
 
-void CSScrollDown()
+static void CSScrollDown()
 {
 	CheckParamVal(Param[1], NumOfLines);
 
@@ -2079,19 +1841,19 @@
 	BuffRegionScrollDownNLines(Param[1]);
 }
 
-void CSForwardTab()
+static void CSForwardTab()
 {
 	CheckParamVal(Param[1], NumOfColumns);
 	CursorForwardTab(Param[1], AutoWrapMode);
 }
 
-void CSBackwardTab()
+static void CSBackwardTab()
 {
 	CheckParamVal(Param[1], NumOfColumns);
 	CursorBackwardTab(Param[1]);
 }
 
-void CSMoveToColumnN()		// CHA / HPA
+static void CSMoveToColumnN()		// CHA / HPA
 {
 	CheckParamVal(Param[1], NumOfColumns);
 
@@ -2108,7 +1870,7 @@
 	}
 }
 
-void CSCursorRight(BOOL AffectMargin)	// CUF / HPR
+static void CSCursorRight(BOOL AffectMargin)	// CUF / HPR
 {
 	int NewX, rightMargin;
 
@@ -2128,7 +1890,7 @@
 	MoveCursor(NewX, CursorY);
 }
 
-void CSCursorLeft(BOOL AffectMargin)	// CUB / HPB
+static void CSCursorLeft(BOOL AffectMargin)	// CUB / HPB
 {
 	int NewX, leftMargin;
 
@@ -2149,7 +1911,7 @@
 	MoveCursor(NewX, CursorY);
 }
 
-void CSMoveToLineN()		// VPA
+static void CSMoveToLineN()		// VPA
 {
 	CheckParamVal(Param[1], NumOfLines-StatusLine);
 
@@ -2168,7 +1930,7 @@
 	Fallbacked = FALSE;
 }
 
-void CSMoveToXY()		// CUP / HVP
+static void CSMoveToXY()		// CUP / HVP
 {
 	int NewX, NewY;
 
@@ -2199,12 +1961,12 @@
 	Fallbacked = FALSE;
 }
 
-void CSDeleteTabStop()
+static void CSDeleteTabStop()
 {
 	ClearTabStop(Param[1]);
 }
 
-void CS_h_Mode()		// SM
+static void CS_h_Mode()		// SM
 {
 	switch (Param[1]) {
 	  case 2:	// KAM
@@ -2236,7 +1998,7 @@
 	}
 }
 
-void CS_i_Mode()		// MC
+static void CS_i_Mode()		// MC
 {
 	switch (Param[1]) {
 	  /* print screen */
@@ -2261,7 +2023,7 @@
 	}
 }
 
-void CS_l_Mode()		// RM
+static void CS_l_Mode()		// RM
 {
 	switch (Param[1]) {
 	  case 2:	// KAM
@@ -2293,7 +2055,7 @@
 	}
 }
 
-void CS_n_Mode()		// DSR
+static void CS_n_Mode()		// DSR
 {
 	char Report[16];
 	int X, Y, len;
@@ -2323,7 +2085,7 @@
 	}
 }
 
-void ParseSGRParams(PCharAttr attr, PCharAttr mask, int start)
+static void ParseSGRParams(PCharAttr attr, PCharAttr mask, int start)
 {
 	int i, j, P, r, g, b, color;
 	TCharAttr dummy;
@@ -2610,7 +2372,7 @@
 	BuffSetCurCharAttr(CharAttr);
 }
 
-void CSSetScrollRegion()	// DECSTBM
+static void CSSetScrollRegion()	// DECSTBM
 {
 	if (isCursorOnStatusLine) {
 		MoveCursor(0,CursorY);
@@ -2634,7 +2396,7 @@
 		MoveCursor(0, 0);
 }
 
-void CSSetLRScrollRegion()	// DECSLRM
+static void CSSetLRScrollRegion()	// DECSLRM
 {
 //	TODO: \x83X\x83e\x81[\x83^\x83X\x83\x89\x83C\x83\x93\x8F\xE3\x82ł̋\x93\x93\xAE\x8Am\x94F\x81B
 //	if (isCursorOnStatusLine) {
@@ -2658,7 +2420,7 @@
 		MoveCursor(0, 0);
 }
 
-void CSSunSequence() /* Sun terminal private sequences */
+static void CSSunSequence() /* Sun terminal private sequences */
 {
 	int x, y, len;
 	char Report[TitleBuffSize*2+10];
@@ -2935,7 +2697,7 @@
 	}
 }
 
-void CSLT(BYTE b)
+static void CSLT(BYTE b)
 {
 	switch (b) {
 	  case 'r':
@@ -2958,7 +2720,7 @@
 	}
 }
 
-void CSEQ(BYTE b)
+static void CSEQ(BYTE b)
 {
 	char Report[16];
 	int len;
@@ -2973,7 +2735,7 @@
 	}
 }
 
-void CSGT(BYTE b)
+static void CSGT(BYTE b)
 {
 	switch (b) {
 	  case 'c': /* second terminal report (Secondary DA) */
@@ -3053,7 +2815,7 @@
 	UpdateWindow(HVTWin);
 }
 
-void CSQChangeColumnMode(int width)		// DECCOLM
+static void CSQChangeColumnMode(int width)		// DECCOLM
 {
 	ChangeTerminalSize(width, NumOfLines-StatusLine);
 	LRMarginMode = FALSE;
@@ -3069,7 +2831,7 @@
 	}
 }
 
-void CSQ_h_Mode() // DECSET
+static void CSQ_h_Mode() // DECSET
 {
 	int i;
 
@@ -3116,16 +2878,16 @@
 		  case 59:
 			if (ts.Language==IdJapanese) {
 				/* kanji terminal */
-				Gn[0] = IdASCII;
-				Gn[1] = IdKatakana;
-				Gn[2] = IdKatakana;
-				Gn[3] = IdKanji;
-				Glr[0] = 0;
-				if ((ts.KanjiCode==IdJIS) &&
-				    (ts.JIS7Katakana==0))
-					Glr[1] = 2;  // 8-bit katakana
+				CharSet2022Designate(0, IdASCII);
+				CharSet2022Designate(1, IdKatakana);
+				CharSet2022Designate(2, IdKatakana);
+				CharSet2022Designate(3, IdKanji);
+				CharSet2022Invoke(0, 0, FALSE);
+				if ((ts.KanjiCode==IdJIS) && (ts.JIS7Katakana==0))
+					// 8-bit katakana
+					CharSet2022Invoke(1, 2, FALSE);
 				else
-					Glr[1] = 3;
+					CharSet2022Invoke(1, 3, FALSE);
 			}
 			break;
 		  case 66: AppliKeyMode = TRUE; break;		// DECNKM
@@ -3246,7 +3008,7 @@
 	}
 }
 
-void CSQ_l_Mode()		// DECRST
+static void CSQ_l_Mode()		// DECRST
 {
 	int i;
 
@@ -3286,16 +3048,16 @@
 		  case 59:
 			if (ts.Language==IdJapanese) {
 				/* katakana terminal */
-				Gn[0] = IdASCII;
-				Gn[1] = IdKatakana;
-				Gn[2] = IdKatakana;
-				Gn[3] = IdKanji;
-				Glr[0] = 0;
-				if ((ts.KanjiCode==IdJIS) &&
-				    (ts.JIS7Katakana==0))
-					Glr[1] = 2;	// 8-bit katakana
+				CharSet2022Designate(0, IdASCII);
+				CharSet2022Designate(1, IdKatakana);
+				CharSet2022Designate(2, IdKatakana);
+				CharSet2022Designate(3, IdKanji);
+				CharSet2022Invoke(0, 0, FALSE);
+				if ((ts.KanjiCode==IdJIS) && (ts.JIS7Katakana==0))
+					// 8-bit katakana
+					CharSet2022Invoke(1, 2, FALSE);
 				else
-					Glr[1] = 3;
+					CharSet2022Invoke(1, 3, FALSE);
 			}
 			break;
 		  case 66: AppliKeyMode = FALSE; break;		// DECNKM
@@ -3363,7 +3125,7 @@
 	}
 }
 
-void CSQ_n_Mode()		// DECDSR
+static void CSQ_n_Mode()		// DECDSR
 {
 	switch (Param[1]) {
 	  case 53:
@@ -3386,7 +3148,7 @@
 	}
 }
 
-void SoftReset()
+static void SoftReset()
 // called by software-reset escape sequence handler
 {
 	UpdateStr();
@@ -3412,13 +3174,29 @@
 	BuffSetCurCharAttr(CharAttr);
 
 	// status buffers
-	ResetCurSBuffer();
+	{
+		PStatusBuff Buff;
+		int save_x = CursorX;
+		int save_y = CursorY;
 
+		if (AltScr) {
+			Buff = &SBuff3; // Alternate screen buffer
+		}
+		else {
+			Buff = &SBuff1; // Normal screen buffer
+		}
+		CursorX = 0;
+		CursorY = 0;
+		SaveCursorBuf(Buff);
+		CursorX = save_x;
+		CursorY = save_y;
+	}
+
 	// Saved IME status
 	IMEstat = FALSE;
 }
 
-void CSExc(BYTE b)
+static void CSExc(BYTE b)
 {
 	switch (b) {
 	  case 'p':
@@ -3428,7 +3206,7 @@
 	}
 }
 
-void CSDouble(BYTE b)
+static void CSDouble(BYTE b)
 {
 	switch (b) {
 	  case 'p': // DECSCL
@@ -3772,7 +3550,7 @@
 	SendCSIstr(buff, len);
 }
 
-void CSDol(BYTE b)
+static void CSDol(BYTE b)
 {
 	TCharAttr attr, mask;
 	attr = DefCharAttr;
@@ -3975,7 +3753,7 @@
 	}
 }
 
-void CSQDol(BYTE b)
+static void CSQDol(BYTE b)
 {
 	switch (b) {
 	  case 'p':
@@ -3984,7 +3762,7 @@
 	}
 }
 
-void CSQuote(BYTE b)
+static void CSQuote(BYTE b)
 {
 	int i, x, y;
 	switch (b) {
@@ -4071,7 +3849,8 @@
 	}
 }
 
-void CSSpace(BYTE b) {
+static void CSSpace(BYTE b)
+{
 	switch (b) {
 	  case 'q': // DECSCUSR
 		if (ts.WindowFlag & WF_CURSORCHANGE) {
@@ -4110,7 +3889,7 @@
 	}
 }
 
-void CSAster(BYTE b)
+static void CSAster(BYTE b)
 {
 	switch (b) {
 	  case 'x': // DECSACE
@@ -4127,7 +3906,7 @@
 	}
 }
 
-void PrnParseCS(BYTE b) // printer mode
+static void PrnParseCS(BYTE b) // printer mode
 {
 	ParseMode = ModeFirst;
 	switch (ICount) {
@@ -4262,7 +4041,7 @@
 	ParseMode = ModeFirst;
 }
 
-void ControlSequence(BYTE b)
+static void ControlSequence(BYTE b)
 {
 	if ((b<=US) || (b>=0x80) && (b<=0x9F))
 		ParseControl(b); /* ctrl char */
@@ -4348,7 +4127,7 @@
 	return utf8_stat;
 }
 
-void IgnoreString(BYTE b)
+static void IgnoreString(BYTE b)
 {
 	static int utf8_stat = 0;
 
@@ -4519,7 +4298,7 @@
 	SendDCSstr(RepStr, len);
 }
 
-int toHexStr(unsigned char *buff, int buffsize, unsigned char *str)
+static int toHexStr(unsigned char *buff, int buffsize, unsigned char *str)
 {
 	int len, i, copylen = 0;
 	unsigned char c;
@@ -4707,7 +4486,7 @@
 
 #define ModeDcsFirst     1
 #define ModeDcsString    2
-void DeviceControl(BYTE b)
+static void DeviceControl(BYTE b)
 {
 	static unsigned char StrBuff[256];
 	static int DcsParseMode = ModeDcsFirst;
@@ -4790,7 +4569,7 @@
 	}
 }
 
-void DCUserKey(BYTE b)
+static void DCUserKey(BYTE b)
 {
 	static int utf8_stat = 0;
 
@@ -4842,7 +4621,7 @@
 	}
 }
 
-BOOL XsParseColor(char *colspec, COLORREF *color)
+static BOOL XsParseColor(char *colspec, COLORREF *color)
 {
 	unsigned int r, g, b;
 //	double dr, dg, db;
@@ -5415,7 +5194,7 @@
 	}
 }
 
-void DLESeen(BYTE b)
+static void DLESeen(BYTE b)
 {
 	ParseMode = ModeFirst;
 	if (((ts.FTFlag & FT_BPAUTO)!=0) && (b=='B'))
@@ -5423,7 +5202,7 @@
 	ChangeEmu = -1;
 }
 
-void CANSeen(BYTE b)
+static void CANSeen(BYTE b)
 {
 	static int state = 0;
 
@@ -5462,7 +5241,7 @@
  *
  *	PutChar() \x82\xCC UTF-32\x94\xC5
  */
-static void PutU32(unsigned int code)
+void PutU32(unsigned int code)
 {
 	unsigned short cset;
 	int LineEnd;
@@ -5605,624 +5384,6 @@
 }
 
 /**
- *	1byte\x96ڃ`\x83F\x83b\x83N
- */
-static BOOL CheckFirstByte(BYTE b, int lang, int kanji_code)
-{
-	switch (lang) {
-		case IdKorean:
-			return __ismbblead(b, 51949);
-		case IdChinese:
-			if (kanji_code == IdCnGB2312) {
-				return __ismbblead(b, 936);
-			}
-			else if (ts.KanjiCode == IdCnBig5) {
-				return __ismbblead(b, 950);
-			}
-			break;
-		default:
-			assert(FALSE);
-			break;
-	}
-	assert(FALSE);
-	return FALSE;
-}
-
-/**
- *	ts.Language == IdJapanese \x8E\x9E
- *	1byte\x96ڃ`\x83F\x83b\x83N
- */
-static BOOL CheckKanji(BYTE b)
-{
-	BOOL Check;
-
-	if (ts.Language!=IdJapanese)
-		return FALSE;
-
-	ConvJIS = FALSE;
-
-	if (ts.KanjiCode==IdSJIS ||
-	   (ts.FallbackToCP932 && ts.KanjiCode==IdUTF8)) {
-		if ((0x80<b) && (b<0xa0) || (0xdf<b) && (b<0xfd)) {
-			Fallbacked = TRUE;
-			return TRUE; // SJIS kanji
-		}
-		if ((0xa1<=b) && (b<=0xdf)) {
-			return FALSE; // SJIS katakana
-		}
-	}
-
-	if ((b>=0x21) && (b<=0x7e)) {
-		Check = (Gn[Glr[0]]==IdKanji);
-		ConvJIS = Check;
-	}
-	else if ((b>=0xA1) && (b<=0xFE)) {
-		Check = (Gn[Glr[1]]==IdKanji);
-		if (ts.KanjiCode==IdEUC) {
-			Check = TRUE;
-		}
-		else if (ts.KanjiCode==IdJIS && ((ts.TermFlag & TF_FIXEDJIS)!=0) && (ts.JIS7Katakana==0)) {
-			Check = FALSE; // 8-bit katakana
-		}
-		ConvJIS = Check;
-	}
-	else {
-		Check = FALSE;
-	}
-
-	return Check;
-}
-
-static BOOL ParseFirstJP(BYTE b)
-// returns TRUE if b is processed
-//  (actually allways returns TRUE)
-{
-	if (KanjiIn) {
-		if ((! ConvJIS) && (0x3F<b) && (b<0xFD) ||
-		      ConvJIS && ( (0x20<b) && (b<0x7f) ||
-		                   (0xa0<b) && (b<0xff) ))
-		{
-			PutKanji(b);
-			KanjiIn = FALSE;
-			return TRUE;
-		}
-		else if ((ts.TermFlag & TF_CTRLINKANJI)==0) {
-			KanjiIn = FALSE;
-		}
-		else if ((b==CR) && Wrap) {
-			CarriageReturn(FALSE);
-			LineFeed(LF,FALSE);
-			Wrap = FALSE;
-		}
-	}
-
-	if (SSflag) {
-		if (Gn[GLtmp] == IdKanji) {
-			Kanji = b << 8;
-			KanjiIn = TRUE;
-			SSflag = FALSE;
-			return TRUE;
-		}
-		else if (Gn[GLtmp] == IdKatakana) {
-			b = b | 0x80;
-		}
-
-		PutChar(b);
-		SSflag = FALSE;
-		return TRUE;
-	}
-
-	if ((!EUCsupIn) && (!EUCkanaIn) && (!KanjiIn) && CheckKanji(b)) {
-		Kanji = b << 8;
-		KanjiIn = TRUE;
-		return TRUE;
-	}
-
-	if (b<=US) {
-		ParseControl(b);
-	}
-	else if (b==0x20) {
-		PutChar(b);
-	}
-	else if ((b>=0x21) && (b<=0x7E)) {
-		if (EUCsupIn) {
-			EUCcount--;
-			EUCsupIn = (EUCcount==0);
-			return TRUE;
-		}
-
-		if ((Gn[Glr[0]] == IdKatakana) || EUCkanaIn) {
-			b = b | 0x80;
-			EUCkanaIn = FALSE;
-			{
-				// b\x82\xCDsjis\x82̔\xBC\x8Ap\x83J\x83^\x83J\x83i
-				unsigned long u32 = CP932ToUTF32(b);
-				PutU32(u32);
-			}
-			return TRUE;
-		}
-		PutChar(b);
-	}
-	else if (b==0x7f) {
-		return TRUE;
-	}
-	else if ((b>=0x80) && (b<=0x8D)) {
-		ParseControl(b);
-	}
-	else if (b==0x8E) { // SS2
-		switch (ts.KanjiCode) {
-		case IdEUC:
-			if (ts.ISO2022Flag & ISO2022_SS2) {
-				EUCkanaIn = TRUE;
-			}
-			break;
-		case IdUTF8:
-			PutChar('?');
-			break;
-		default:
-			ParseControl(b);
-		}
-	}
-	else if (b==0x8F) { // SS3
-		switch (ts.KanjiCode) {
-		case IdEUC:
-			if (ts.ISO2022Flag & ISO2022_SS3) {
-				EUCcount = 2;
-				EUCsupIn = TRUE;
-			}
-			break;
-		case IdUTF8:
-			PutChar('?');
-			break;
-		default:
-			ParseControl(b);
-		}
-	}
-	else if ((b>=0x90) && (b<=0x9F)) {
-		ParseControl(b);
-	}
-	else if (b==0xA0) {
-		PutChar(0x20);
-	}
-	else if ((b>=0xA1) && (b<=0xFE)) {
-		if (EUCsupIn) {
-			EUCcount--;
-			EUCsupIn = (EUCcount==0);
-			return TRUE;
-		}
-
-		if ((Gn[Glr[1]] != IdASCII) ||
-		    (ts.KanjiCode==IdEUC) && EUCkanaIn ||
-		    (ts.KanjiCode==IdSJIS) ||
-		    (ts.KanjiCode==IdJIS) &&
-		    (ts.JIS7Katakana==0) &&
-		    ((ts.TermFlag & TF_FIXEDJIS)!=0)) {
-			// b\x82\xCDsjis\x82̔\xBC\x8Ap\x83J\x83^\x83J\x83i
-			unsigned long u32 = CP932ToUTF32(b);
-			PutU32(u32);
-		} else {
-			if (Gn[Glr[1]] == IdASCII) {
-				b = b & 0x7f;
-			}
-			PutChar(b);
-		}
-		EUCkanaIn = FALSE;
-	}
-	else {
-		PutChar(b);
-	}
-
-	return TRUE;
-}
-
-static BOOL ParseFirstKR(BYTE b)
-// returns TRUE if b is processed
-//  (actually allways returns TRUE)
-{
-	if (KanjiIn) {
-		if ((0x41<=b) && (b<=0x5A) ||
-		    (0x61<=b) && (b<=0x7A) ||
-		    (0x81<=b) && (b<=0xFE))
-		{
-			PutKanji(b);
-			KanjiIn = FALSE;
-			return TRUE;
-		}
-		else if ((ts.TermFlag & TF_CTRLINKANJI)==0) {
-			KanjiIn = FALSE;
-		}
-		else if ((b==CR) && Wrap) {
-			CarriageReturn(FALSE);
-			LineFeed(LF,FALSE);
-			Wrap = FALSE;
-		}
-	}
-
-	if ((!KanjiIn) && CheckFirstByte(b, ts.Language, ts.KanjiCode)) {
-		Kanji = b << 8;
-		KanjiIn = TRUE;
-		return TRUE;
-	}
-
-	if (b<=US) {
-		ParseControl(b);
-	}
-	else if (b==0x20) {
-		PutChar(b);
-	}
-	else if ((b>=0x21) && (b<=0x7E)) {
-//		if (Gn[Glr[0]] == IdKatakana) {
-//			b = b | 0x80;
-//		}
-		PutChar(b);
-	}
-	else if (b==0x7f) {
-		return TRUE;
-	}
-	else if ((0x80<=b) && (b<=0x9F)) {
-		ParseControl(b);
-	}
-	else if (b==0xA0) {
-		PutChar(0x20);
-	}
-	else if ((b>=0xA1) && (b<=0xFE)) {
-		if (Gn[Glr[1]] == IdASCII) {
-			b = b & 0x7f;
-		}
-		PutChar(b);
-	}
-	else {
-		PutChar(b);
-	}
-
-	return TRUE;
-}
-
-static BOOL ParseFirstCn(BYTE b)
-// returns TRUE if b is processed
-//  (actually allways returns TRUE)
-{
-	if (KanjiIn) {
-		// TODO
-		if ((0x40<=b) && (b<=0x7e) ||
-		    (0xa1<=b) && (b<=0xFE))
-		{
-			PutKanji(b);
-			KanjiIn = FALSE;
-			return TRUE;
-		}
-		else if ((ts.TermFlag & TF_CTRLINKANJI)==0) {
-			KanjiIn = FALSE;
-		}
-		else if ((b==CR) && Wrap) {
-			CarriageReturn(FALSE);
-			LineFeed(LF,FALSE);
-			Wrap = FALSE;
-		}
-	}
-
-	if ((!KanjiIn) && CheckFirstByte(b, ts.Language, ts.KanjiCode)) {
-		Kanji = b << 8;
-		KanjiIn = TRUE;
-		return TRUE;
-	}
-
-	if (b<=US) {
-		ParseControl(b);
-	}
-	else if (b==0x20) {
-		PutChar(b);
-	}
-	else if ((b>=0x21) && (b<=0x7E)) {
-//		if (Gn[Glr[0]] == IdKatakana) {
-//			b = b | 0x80;
-//		}
-		PutChar(b);
-	}
-	else if (b==0x7f) {
-		return TRUE;
-	}
-	else if ((0x80<=b) && (b<=0x9F)) {
-		ParseControl(b);
-	}
-	else if (b==0xA0) {
-		PutChar(0x20);
-	}
-	else if ((b>=0xA1) && (b<=0xFE)) {
-		if (Gn[Glr[1]] == IdASCII) {
-			b = b & 0x7f;
-		}
-		PutChar(b);
-	}
-	else {
-		PutChar(b);
-	}
-
-	return TRUE;
-}
-
-static void ParseASCII(BYTE b)
-{
-	if (SSflag) {
-		PutChar(b);
-		SSflag = FALSE;
-		return;
-	}
-
-	if (b<=US) {
-		ParseControl(b);
-	} else if ((b>=0x20) && (b<=0x7E)) {
-		//Kanji = 0;
-		//PutKanji(b);
-		PutChar(b);
-	} else if ((b==0x8E) || (b==0x8F)) {
-		PutChar('?');
-	} else if ((b>=0x80) && (b<=0x9F)) {
-		ParseControl(b);
-	} else if (b>=0xA0) {
-		//Kanji = 0;
-		//PutKanji(b);
-		PutChar(b);
-	}
-}
-
-// 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)
-static BOOL ParseFirstUTF8(BYTE b)
-{
-	static BYTE buf[4];
-	static int count = 0;
-
-	unsigned int code;
-	int i;
-
-	if (ts.FallbackToCP932 && Fallbacked) {
-		return ParseFirstJP(b);
-	}
-
-	// UTF-8\x83G\x83\x93\x83R\x81[\x83h
-	//	Unicode					1byte,		  2byte,	   3byte, 		  4byte
-	//	U+0000  ... U+007f		0x00 .. 0x7f
-	//	U+0080  ... U+07ff		0xc2 .. 0xdf, 0x80 .. 0xbf
-	//	U+0800  ... U+ffff		0xe0 .. 0xef, 0x80 .. 0xbf, 0x80 .. 0xbf
-	//	U+10000 ... U+10ffff	0xf0 .. 0xf4, 0x80 .. 0xbf, 0x80 .. 0xbf, 0x80 .. 0xbf
-	// UTF-8\x82Ńf\x83R\x81[\x83h\x82ł\xAB\x82Ȃ\xA2\x8Fꍇ
-	//	- 1byte\x96\xDA
-	//		- C1(0x80 - 0x9f)
-	//		- 0xa0 - 0xc1
-	//		- 0xf5 - 0xff
-	//	- 2byte\x96ڈȍ~
-	//		- 0x00 - 0x7f
-	//		- 0xc0 - 0xff
-
-	// 1byte(7bit)
-	if (count == 0) {
-		if ((b & 0x80) == 0x00) {
-			// 1byte(7bit)
-			//		0x7f\x88ȉ\xBA, \x82̂Ƃ\xAB\x81A\x82\xBB\x82̂܂܏o\x97\xCD
-			ParseASCII(b);
-			return TRUE;
-		}
-		if ((b & 0x40) == 0x00 || b >= 0xf6 ) {
-			// UTF-8\x82\xC51byte\x82ɏo\x8C\xBB\x82\xB5\x82Ȃ\xA2\x83R\x81[\x83h\x82̂Ƃ\xAB\x81A\x82\xBB\x82̂܂܏o\x97\xCD
-			//	0x40 = 0b1011_1111, 0b10xx_xxxx\x82Ƃ\xA2\x82\xA4bit\x83p\x83^\x81[\x83\x93\x82ɂ͂Ȃ\xE7\x82Ȃ\xA2
-			//  0xf6 \x88ȏ\xE3\x82̂Ƃ\xAB U+10FFFF\x82\xE6\x82\xE8\x91傫\x82\xAD\x82Ȃ\xE9
-			PutU32(b);
-			return TRUE;
-		}
-		// 1byte\x96ڕۑ\xB6
-		buf[count++] = b;
-		return TRUE;
-	}
-
-	// 2byte(11bit)
-	if ((buf[0] & 0xe0) == 0xc0) {
-		code = 0;
-		if((b & 0xc0) == 0x80) {
-			// 5bit + 6bit
-			code = ((buf[0] & 0x1f) << 6) | (b & 0x3f);
-			if (code < 0x80) {
-				// 11bit\x8Eg\x82\xC1\x82\xC47bit\x88ȉ\xBA\x82̎\x9E\x81AUTF-8\x82̏璷\x82ȕ\\x8C\xBB
-				code = 0;
-			}
-		}
-		if (code == 0){
-			// \x82\xBB\x82̂܂܏o\x97\xCD
-			PutU32(buf[0]);
-			PutU32(b);
-			count = 0;
-			return TRUE;
-		}
-		else {
-			PutU32(code);
-			count = 0;
-			return TRUE;
-		}
-	}
-
-	// 2byte\x96ڈȍ~\x95ۑ\xB6
-	buf[count++] = b;
-
-	// 3byte(16bit)
-	if ((buf[0] & 0xf0) == 0xe0) {
-		if(count < 3) {
-			return TRUE;
-		}
-		code = 0;
-		if ((buf[1] & 0xc0) == 0x80 && (buf[2] & 0xc0) == 0x80) {
-			// 4bit + 6bit + 6bit
-			code = ((buf[0] & 0xf) << 12);
-			code |= ((buf[1] & 0x3f) << 6);
-			code |= ((buf[2] & 0x3f));
-			if (code < 0x800) {
-				// 16bit\x8Eg\x82\xC1\x82\xC411bit\x88ȉ\xBA\x82̂Ƃ\xAB\x81AUTF-8\x82̏璷\x82ȕ\\x8C\xBB
-				code = 0;
-			}
-		}
-		if (code == 0) {
-			// \x82\xBB\x82̂܂܏o\x97\xCD
-			PutU32(buf[0]);
-			PutU32(buf[1]);
-			PutU32(buf[2]);
-			count = 0;
-			return TRUE;
-		} else {
-			PutU32(code);
-			count = 0;
-			return TRUE;
-		}
-	}
-
-	// 4byte(21bit)
-	if ((buf[0] & 0xf8) == 0xf0) {
-		if(count < 4) {
-			return TRUE;
-		}
-		code = 0;
-		if ((buf[1] & 0xc0) == 0x80 && (buf[2] & 0xc0) == 0x80 && (buf[3] & 0xc0) == 0x80) {
-			// 3bit + 6bit + 6bit + 6bit
-			code = ((buf[0] & 0x07) << 18);
-			code |= ((buf[1] & 0x3f) << 12);
-			code |= ((buf[2] & 0x3f) << 6);
-			code |= (buf[3] & 0x3f);
-			if (code < 0x10000) {
-				// 21bit\x8Eg\x82\xC1\x82\xC416bit\x88ȉ\xBA\x82̂Ƃ\xAB\x81AUTF-8\x82̏璷\x82ȕ\\x8C\xBB
-				code = 0;
-			}
-		}
-		if (code == 0) {
-			// \x82\xBB\x82̂܂܏o\x97\xCD
-			PutU32(buf[0]);
-			PutU32(buf[1]);
-			PutU32(buf[2]);
-			PutU32(buf[3]);
-			count = 0;
-			return TRUE;
-		} else {
-			PutU32(code);
-			count = 0;
-			return TRUE;
-		}
-	}
-
-	// \x82\xB1\x82\xB1\x82ɂ͗\x88\x82Ȃ\xA2
-	assert(FALSE);
-
-	for (i = 0; i < count; i++) {
-		ParseASCII(buf[i]);
-	}
-	count = 0;
-	return TRUE;
-}
-
-
-static BOOL ParseFirstRus(BYTE b)
-// returns if b is processed
-{
-	if (b>=128) {
-		PutChar(b);
-		return TRUE;
-	}
-	return FALSE;
-}
-
-static BOOL ParseEnglish(BYTE b)
-{
-	unsigned short u16 = 0;
-	int part = KanjiCodeToISO8859Part(ts.KanjiCode);
-	int r = UnicodeFromISO8859(part, b, &u16);
-	if (r == 0) {
-		return FALSE;
-	}
-	if (u16 < 0x100) {
-		ParseASCII((BYTE)u16);
-	}
-	else {
-		PutU32(u16);
-	}
-	return TRUE;
-}
-
-static void ParseFirst(BYTE b)
-{
-	switch (ts.Language) {
-	  case IdUtf8:
-		  ParseFirstUTF8(b);
-		return;
-
-	  case IdJapanese:
-		switch (ts.KanjiCode) {
-		  case IdUTF8:
-			  if (ParseFirstUTF8(b)) {
-				return;
-			}
-			break;
-		  default:
-			if (ParseFirstJP(b))  {
-				return;
-			}
-		}
-		break;
-
-	  case IdKorean:
-		switch (ts.KanjiCode) {
-		  case IdUTF8:
-			if (ParseFirstUTF8(b)) {
-				return;
-			}
-			break;
-		  default:
-			if (ParseFirstKR(b))  {
-				return;
-			}
-		}
-		break;
-
-	  case IdRussian:
-		if (ParseFirstRus(b)) {
-			return;
-		}
-		break;
-
-	case IdChinese:
-		switch (ts.KanjiCode) {
-		case IdUTF8:
-			if (ParseFirstUTF8(b)) {
-				return;
-			}
-			break;
-		default:
-			if (ParseFirstCn(b)) {
-				return;
-			}
-		}
-		break;
-	case IdEnglish: {
-		if (ParseEnglish(b)) {
-			return;
-		}
-		break;
-	}
-	}
-
-	if (SSflag) {
-		PutChar(b);
-		SSflag = FALSE;
-		return;
-	}
-
-	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);
-}
-
-/**
  *	1byte\x82\xE6\x82݂\xBE\x82\xB5
  *	\x82\xBD\x82\xBE\x82\xB5\x8E\x9F\x82̏ꍇ\x81A\x93ǂݏo\x82\xB5\x82\xF0\x8Ds\x82\xED\x82Ȃ\xA2
  *		- macro\x91\x97\x90M\x83o\x83b\x83t\x83@\x82ɗ]\x97T\x82\xAA\x82Ȃ\xA2


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