[ttssh2-commit] [10782] charset.cppのワークを動的に確保するようにした

Back to archive index
scmno****@osdn***** scmno****@osdn*****
2023年 6月 27日 (火) 22:36:25 JST


Revision: 10782
          https://osdn.net/projects/ttssh2/scm/svn/commits/10782
Author:   zmatsuo
Date:     2023-06-27 22:36:25 +0900 (Tue, 27 Jun 2023)
Log Message:
-----------
charset.cppのワークを動的に確保するようにした

- charset.cpp からの出力関数を設定できるようにした
  - charset.h の CharSetOp
  - PutU32()
  - ParseControl()

Modified Paths:
--------------
    trunk/teraterm/teraterm/charset.cpp
    trunk/teraterm/teraterm/charset.h
    trunk/teraterm/teraterm/keyboard.c
    trunk/teraterm/teraterm/ttdde.c
    trunk/teraterm/teraterm/vtterm.c
    trunk/teraterm/teraterm/vtterm.h

-------------- next part --------------
Modified: trunk/teraterm/teraterm/charset.cpp
===================================================================
--- trunk/teraterm/teraterm/charset.cpp	2023-06-27 13:28:58 UTC (rev 10781)
+++ trunk/teraterm/teraterm/charset.cpp	2023-06-27 13:36:25 UTC (rev 10782)
@@ -52,35 +52,40 @@
 //#define REPLACEMENT_CHARACTER	0x20
 //#define REPLACEMENT_CHARACTER	0xfffd
 
-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;
-
-/* 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;
-
-static BYTE DebugFlag = DEBUG_FLAG_NONE;
-
-typedef struct {
+typedef struct CharSetDataTag {
 	/* GL, GR code group */
 	int Glr[2];
 	/* G0, G1, G2, G3 code group */
 	int Gn[4];
+	/* GL for single shift 2/3 */
+	int GLtmp;
+	/* single shift 2/3 flag */
+	BOOL SSflag;
 	//
 	char32_t replacement_char;
 	// UTF-8 work
 	BYTE buf[4];
 	int count;
-} VttermKanjiWork;
+	BOOL Fallbacked;
 
-static VttermKanjiWork KanjiWork;
+	// MBCS
+	BOOL KanjiIn;				// TRUE = MBCS\x82\xCC1byte\x96ڂ\xF0\x8E\xF3\x90M\x82\xB5\x82Ă\xA2\x82\xE9
+	WORD Kanji;
 
+	// EUC
+	BOOL EUCkanaIn;
+	BOOL EUCsupIn;
+	int  EUCcount;
+
+	/* JIS -> SJIS conversion flag */
+	BOOL ConvJIS;
+	BYTE DebugFlag;
+
+	// Operations
+	CharSetOp Op;
+	void *ClientData;
+} CharSetData;
+
 static BOOL IsC0(char32_t b)
 {
 	return (b <= US);
@@ -92,18 +97,9 @@
 }
 
 /**
- *	PutU32() wrapper
- *	Unicode\x83x\x81[\x83X\x82ɐ؂\xE8\x91ւ\xA6
- */
-static void PutChar(BYTE b)
-{
-	PutU32(b);
-}
-
-/**
  *	ISO2022\x97p\x83\x8F\x81[\x83N\x82\xF0\x8F\x89\x8A\x{227B0B7}\x82\xE9
  */
-static void CharSetInit2(VttermKanjiWork *w)
+static void CharSetInit2(CharSetData *w)
 {
 	if (ts.Language==IdJapanese) {
 		w->Gn[0] = IdASCII;
@@ -129,22 +125,40 @@
 /**
  *	\x8A\xBF\x8E\x9A\x8A֘A\x83\x8F\x81[\x83N\x82\xF0\x8F\x89\x8A\x{227B0B7}\x82\xE9
  */
-void CharSetInit(void)
+CharSetData *CharSetInit(const CharSetOp *op, void *client_data)
 {
-	VttermKanjiWork *w = &KanjiWork;
+	CharSetData *w = (CharSetData *)calloc(sizeof(*w), 1);
+	if (w == NULL) {
+		return NULL;
+	}
 
+	w->Op = *op;
+	w->ClientData = client_data;
+
 	CharSetInit2(w);
+	w->GLtmp = 0;
+	w->SSflag = FALSE;
 
+	w->DebugFlag = DEBUG_FLAG_NONE;
+
 	w->replacement_char = REPLACEMENT_CHARACTER;
-	SSflag = FALSE;
+	w->SSflag = FALSE;
 
-	KanjiIn = FALSE;
-	EUCkanaIn = FALSE;
-	EUCsupIn = FALSE;
-	ConvJIS = FALSE;
-	Fallbacked = FALSE;
+	w->KanjiIn = FALSE;
+	w->EUCkanaIn = FALSE;
+	w->EUCsupIn = FALSE;
+	w->ConvJIS = FALSE;
+	w->Fallbacked = FALSE;
+
+	return w;
 }
 
+void CharSetFinish(CharSetData *w)
+{
+	assert(w != NULL);
+	free(w);
+}
+
 /**
  *	1byte\x96ڃ`\x83F\x83b\x83N
  */
@@ -188,20 +202,19 @@
  *	ts.Language == IdJapanese \x8E\x9E
  *	1byte\x96ڃ`\x83F\x83b\x83N
  */
-static BOOL CheckKanji(BYTE b)
+static BOOL CheckKanji(CharSetData *w, BYTE b)
 {
-	VttermKanjiWork *w = &KanjiWork;
 	BOOL Check;
 
 	if (ts.Language!=IdJapanese)
 		return FALSE;
 
-	ConvJIS = FALSE;
+	w->ConvJIS = FALSE;
 
 	if (ts.KanjiCode==IdSJIS ||
 	   (ts.FallbackToCP932 && ts.KanjiCode==IdUTF8)) {
 		if (((0x80<b) && (b<0xa0)) || ((0xdf<b) && (b<0xfd))) {
-			Fallbacked = TRUE;
+			w->Fallbacked = TRUE;
 			return TRUE; // SJIS kanji
 		}
 		if ((0xa1<=b) && (b<=0xdf)) {
@@ -211,7 +224,7 @@
 
 	if ((b>=0x21) && (b<=0x7e)) {
 		Check = (w->Gn[w->Glr[0]] == IdKanji);
-		ConvJIS = Check;
+		w->ConvJIS = Check;
 	}
 	else if ((b>=0xA1) && (b<=0xFE)) {
 		Check = (w->Gn[w->Glr[1]] == IdKanji);
@@ -221,7 +234,7 @@
 		else if (ts.KanjiCode==IdJIS && ((ts.TermFlag & TF_FIXEDJIS)!=0) && (ts.JIS7Katakana==0)) {
 			Check = FALSE; // 8-bit katakana
 		}
-		ConvJIS = Check;
+		w->ConvJIS = Check;
 	}
 	else {
 		Check = FALSE;
@@ -230,97 +243,96 @@
 	return Check;
 }
 
-static BOOL ParseFirstJP(BYTE b)
+static BOOL ParseFirstJP(CharSetData *w, 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)) ||
+	if (w->KanjiIn) {
+		if (((! w->ConvJIS) && (0x3F<b) && (b<0xFD)) ||
+			(w->ConvJIS && ( ((0x20<b) && (b<0x7f)) ||
 						  ((0xa0<b) && (b<0xff)) )) )
 		{
 			unsigned long u32;
-			Kanji = Kanji + b;
-			if (ConvJIS) {
+			w->Kanji = w->Kanji + b;
+			if (w->ConvJIS) {
 				// JIS -> Shift_JIS(CP932)
-				Kanji = JIS2SJIS((WORD)(Kanji & 0x7f7f));
+				w->Kanji = JIS2SJIS((WORD)(w->Kanji & 0x7f7f));
 			}
-			u32 = CP932ToUTF32(Kanji);
-			PutU32(u32);
-			KanjiIn = FALSE;
+			u32 = CP932ToUTF32(w->Kanji);
+			w->Op.PutU32(u32, w->ClientData);
+			w->KanjiIn = FALSE;
 			return TRUE;
 		}
 		else if ((ts.TermFlag & TF_CTRLINKANJI)==0) {
-			KanjiIn = FALSE;
+			w->KanjiIn = FALSE;
 		}
 	}
 
-	if (SSflag) {
-		if (w->Gn[GLtmp] == IdKanji) {
-			Kanji = b << 8;
-			KanjiIn = TRUE;
-			SSflag = FALSE;
+	if (w->SSflag) {
+		if (w->Gn[w->GLtmp] == IdKanji) {
+			w->Kanji = b << 8;
+			w->KanjiIn = TRUE;
+			w->SSflag = FALSE;
 			return TRUE;
 		}
-		else if (w->Gn[GLtmp] == IdKatakana) {
+		else if (w->Gn[w->GLtmp] == IdKatakana) {
 			b = b | 0x80;
 		}
 
-		PutChar(b);
-		SSflag = FALSE;
+		w->Op.PutU32(b, w->ClientData);
+		w->SSflag = FALSE;
 		return TRUE;
 	}
 
-	if ((!EUCsupIn) && (!EUCkanaIn) && (!KanjiIn) && CheckKanji(b)) {
-		Kanji = b << 8;
-		KanjiIn = TRUE;
+	if ((!w->EUCsupIn) && (!w->EUCkanaIn) && (!w->KanjiIn) && CheckKanji(w, b)) {
+		w->Kanji = b << 8;
+		w->KanjiIn = TRUE;
 		return TRUE;
 	}
 
 	if (b<=US) {
-		ParseControl(b);
+		w->Op.ParseControl(b, w->ClientData);
 	}
 	else if (b==0x20) {
-		PutChar(b);
+		w->Op.PutU32(b, w->ClientData);
 	}
 	else if ((b>=0x21) && (b<=0x7E)) {
-		if (EUCsupIn) {
-			EUCcount--;
-			EUCsupIn = (EUCcount==0);
+		if (w->EUCsupIn) {
+			w->EUCcount--;
+			w->EUCsupIn = (w->EUCcount==0);
 			return TRUE;
 		}
 
-		if ((w->Gn[w->Glr[0]] == IdKatakana) || EUCkanaIn) {
+		if ((w->Gn[w->Glr[0]] == IdKatakana) || w->EUCkanaIn) {
 			b = b | 0x80;
-			EUCkanaIn = FALSE;
+			w->EUCkanaIn = FALSE;
 			{
 				// b\x82\xCDsjis\x82̔\xBC\x8Ap\x83J\x83^\x83J\x83i
 				unsigned long u32 = CP932ToUTF32(b);
-				PutU32(u32);
+				w->Op.PutU32(u32, w->ClientData);
 			}
 			return TRUE;
 		}
-		PutChar(b);
+		w->Op.PutU32(b, w->ClientData);
 	}
 	else if (b==0x7f) {
 		return TRUE;
 	}
 	else if ((b>=0x80) && (b<=0x8D)) {
-		ParseControl(b);
+		w->Op.ParseControl(b, w->ClientData);
 	}
 	else if (b==0x8E) { // SS2
 		switch (ts.KanjiCode) {
 		case IdEUC:
 			if (ts.ISO2022Flag & ISO2022_SS2) {
-				EUCkanaIn = TRUE;
+				w->EUCkanaIn = TRUE;
 			}
 			break;
 		case IdUTF8:
-			PutU32(REPLACEMENT_CHARACTER);
+			w->Op.PutU32(REPLACEMENT_CHARACTER, w->ClientData);
 			break;
 		default:
-			ParseControl(b);
+			w->Op.ParseControl(b, w->ClientData);
 		}
 	}
 	else if (b==0x8F) { // SS3
@@ -327,32 +339,32 @@
 		switch (ts.KanjiCode) {
 		case IdEUC:
 			if (ts.ISO2022Flag & ISO2022_SS3) {
-				EUCcount = 2;
-				EUCsupIn = TRUE;
+				w->EUCcount = 2;
+				w->EUCsupIn = TRUE;
 			}
 			break;
 		case IdUTF8:
-			PutU32(REPLACEMENT_CHARACTER);
+			w->Op.PutU32(REPLACEMENT_CHARACTER, w->ClientData);
 			break;
 		default:
-			ParseControl(b);
+			w->Op.ParseControl(b, w->ClientData);
 		}
 	}
 	else if ((b>=0x90) && (b<=0x9F)) {
-		ParseControl(b);
+		w->Op.ParseControl(b, w->ClientData);
 	}
 	else if (b==0xA0) {
-		PutChar(0x20);
+		w->Op.PutU32(0x20, w->ClientData);
 	}
 	else if ((b>=0xA1) && (b<=0xFE)) {
-		if (EUCsupIn) {
-			EUCcount--;
-			EUCsupIn = (EUCcount==0);
+		if (w->EUCsupIn) {
+			w->EUCcount--;
+			w->EUCsupIn = (w->EUCcount==0);
 			return TRUE;
 		}
 
 		if ((w->Gn[w->Glr[1]] != IdASCII) ||
-		    ((ts.KanjiCode==IdEUC) && EUCkanaIn) ||
+		    ((ts.KanjiCode==IdEUC) && w->EUCkanaIn) ||
 		    (ts.KanjiCode==IdSJIS) ||
 		    ((ts.KanjiCode==IdJIS) &&
 			 (ts.JIS7Katakana==0) &&
@@ -359,28 +371,27 @@
 			 ((ts.TermFlag & TF_FIXEDJIS)!=0))) {
 			// b\x82\xCDsjis\x82̔\xBC\x8Ap\x83J\x83^\x83J\x83i
 			unsigned long u32 = CP932ToUTF32(b);
-			PutU32(u32);
+			w->Op.PutU32(u32, w->ClientData);
 		} else {
 			if (w->Gn[w->Glr[1]] == IdASCII) {
 				b = b & 0x7f;
 			}
-			PutChar(b);
+			w->Op.PutU32(b, w->ClientData);
 		}
-		EUCkanaIn = FALSE;
+		w->EUCkanaIn = FALSE;
 	}
 	else {
-		PutChar(b);
+		w->Op.PutU32(b, w->ClientData);
 	}
 
 	return TRUE;
 }
 
-static BOOL ParseFirstKR(BYTE b)
+static BOOL ParseFirstKR(CharSetData *w, BYTE b)
 // returns TRUE if b is processed
 //  (actually allways returns TRUE)
 {
-	VttermKanjiWork *w = &KanjiWork;
-	if (KanjiIn) {
+	if (w->KanjiIn) {
 		if (((0x41<=b) && (b<=0x5A)) ||
 			((0x61<=b) && (b<=0x7A)) ||
 			((0x81<=b) && (b<=0xFE)))
@@ -388,151 +399,150 @@
 			unsigned long u32 = 0;
 			if (ts.KanjiCode == IdKoreanCP949) {
 				// CP949
-				Kanji = Kanji + b;
-				u32 = MBCP_UTF32(Kanji, 949);
+				w->Kanji = w->Kanji + b;
+				u32 = MBCP_UTF32(w->Kanji, 949);
 			}
 			else {
 				assert(FALSE);
 			}
-			PutU32(u32);
-			KanjiIn = FALSE;
+			w->Op.PutU32(u32, w->ClientData);
+			w->KanjiIn = FALSE;
 			return TRUE;
 		}
 		else if ((ts.TermFlag & TF_CTRLINKANJI)==0) {
-			KanjiIn = FALSE;
+			w->KanjiIn = FALSE;
 		}
 	}
 
-	if ((!KanjiIn) && CheckFirstByte(b, ts.Language, ts.KanjiCode)) {
-		Kanji = b << 8;
-		KanjiIn = TRUE;
+	if ((!w->KanjiIn) && CheckFirstByte(b, ts.Language, ts.KanjiCode)) {
+		w->Kanji = b << 8;
+		w->KanjiIn = TRUE;
 		return TRUE;
 	}
 
 	if (b<=US) {
-		ParseControl(b);
+		w->Op.ParseControl(b, w->ClientData);
 	}
 	else if (b==0x20) {
-		PutChar(b);
+		w->Op.PutU32(b, w->ClientData);
 	}
 	else if ((b>=0x21) && (b<=0x7E)) {
 //		if (Gn[Glr[0]] == IdKatakana) {
 //			b = b | 0x80;
 //		}
-		PutChar(b);
+		w->Op.PutU32(b, w->ClientData);
 	}
 	else if (b==0x7f) {
 		return TRUE;
 	}
 	else if ((0x80<=b) && (b<=0x9F)) {
-		ParseControl(b);
+		w->Op.ParseControl(b, w->ClientData);
 	}
 	else if (b==0xA0) {
-		PutChar(0x20);
+		w->Op.PutU32(0x20, w->ClientData);
 	}
 	else if ((b>=0xA1) && (b<=0xFE)) {
 		if (w->Gn[w->Glr[1]] == IdASCII) {
 			b = b & 0x7f;
 		}
-		PutChar(b);
+		w->Op.PutU32(b, w->ClientData);
 	}
 	else {
-		PutChar(b);
+		w->Op.PutU32(b, w->ClientData);
 	}
 
 	return TRUE;
 }
 
-static BOOL ParseFirstCn(BYTE b)
+static BOOL ParseFirstCn(CharSetData *w, BYTE b)
 // returns TRUE if b is processed
 //  (actually allways returns TRUE)
 {
-	VttermKanjiWork *w = &KanjiWork;
-	if (KanjiIn) {
+	if (w->KanjiIn) {
 		// TODO
 		if (((0x40<=b) && (b<=0x7e)) ||
 		    ((0xa1<=b) && (b<=0xFE)))
 		{
 			unsigned long u32 = 0;
-			Kanji = Kanji + b;
+			w->Kanji = w->Kanji + b;
 			if (ts.KanjiCode == IdCnGB2312) {
 				// CP936 GB2312
-				u32 = MBCP_UTF32(Kanji, 936);
+				u32 = MBCP_UTF32(w->Kanji, 936);
 			}
 			else if (ts.KanjiCode == IdCnBig5) {
 				// CP950 Big5
-				u32 = MBCP_UTF32(Kanji, 950);
+				u32 = MBCP_UTF32(w->Kanji, 950);
 			}
 			else {
 				assert(FALSE);
 			}
-			PutU32(u32);
-			KanjiIn = FALSE;
+			w->Op.PutU32(u32, w->ClientData);
+			w->KanjiIn = FALSE;
 			return TRUE;
 		}
 		else if ((ts.TermFlag & TF_CTRLINKANJI)==0) {
-			KanjiIn = FALSE;
+			w->KanjiIn = FALSE;
 		}
 	}
 
-	if ((!KanjiIn) && CheckFirstByte(b, ts.Language, ts.KanjiCode)) {
-		Kanji = b << 8;
-		KanjiIn = TRUE;
+	if ((!w->KanjiIn) && CheckFirstByte(b, ts.Language, ts.KanjiCode)) {
+		w->Kanji = b << 8;
+		w->KanjiIn = TRUE;
 		return TRUE;
 	}
 
 	if (b<=US) {
-		ParseControl(b);
+		w->Op.ParseControl(b, w->ClientData);
 	}
 	else if (b==0x20) {
-		PutChar(b);
+		w->Op.PutU32(b, w->ClientData);
 	}
 	else if ((b>=0x21) && (b<=0x7E)) {
 //		if (Gn[Glr[0]] == IdKatakana) {
 //			b = b | 0x80;
 //		}
-		PutChar(b);
+		w->Op.PutU32(b, w->ClientData);
 	}
 	else if (b==0x7f) {
 		return TRUE;
 	}
 	else if ((0x80<=b) && (b<=0x9F)) {
-		ParseControl(b);
+		w->Op.ParseControl(b, w->ClientData);
 	}
 	else if (b==0xA0) {
-		PutChar(0x20);
+		w->Op.PutU32(0x20, w->ClientData);
 	}
 	else if ((b>=0xA1) && (b<=0xFE)) {
 		if (w->Gn[w->Glr[1]] == IdASCII) {
 			b = b & 0x7f;
 		}
-		PutChar(b);
+		w->Op.PutU32(b, w->ClientData);
 	}
 	else {
-		PutChar(b);
+		w->Op.PutU32(b, w->ClientData);
 	}
 
 	return TRUE;
 }
 
-static void ParseASCII(BYTE b)
+static void ParseASCII(CharSetData *w, BYTE b)
 {
-	if (SSflag) {
-		PutChar(b);
-		SSflag = FALSE;
+	if (w->SSflag) {
+		w->Op.PutU32(b, w->ClientData);
+		w->SSflag = FALSE;
 		return;
 	}
 
 	if (b<=US) {
-		ParseControl(b);
+		w->Op.ParseControl(b, w->ClientData);
 	} else if ((b>=0x20) && (b<=0x7E)) {
-		PutU32(b);
+		w->Op.PutU32(b, w->ClientData);
 	} else if ((b==0x8E) || (b==0x8F)) {
-		PutU32(REPLACEMENT_CHARACTER);
+		w->Op.PutU32(REPLACEMENT_CHARACTER, w->ClientData);
 	} else if ((b>=0x80) && (b<=0x9F)) {
-		ParseControl(b);
+		w->Op.ParseControl(b, w->ClientData);
 	} else if (b>=0xA0) {
-		PutU32(b);
+		w->Op.PutU32(b, w->ClientData);
 	}
 }
 
@@ -540,7 +550,7 @@
  *	REPLACEMENT_CHARACTER \x82̕\\x8E\xA6
  *	UTF-8 \x83f\x83R\x81[\x83h\x82\xA9\x82\xE7\x8Eg\x97p
  */
-static void PutReplacementChr(VttermKanjiWork *w, const BYTE *ptr, size_t len, BOOL fallback)
+static void PutReplacementChr(CharSetData *w, const BYTE *ptr, size_t len, BOOL fallback)
 {
 	const char32_t replacement_char = w->replacement_char;
 	int i;
@@ -549,7 +559,7 @@
 		assert(IsC0(c));
 		if (fallback) {
 			// fallback ISO8859-1
-			PutU32(c);
+			w->Op.PutU32(c, w->ClientData);
 		}
 		else {
 			// fallback\x82\xB5\x82Ȃ\xA2
@@ -556,10 +566,10 @@
 			if (c < 0x80) {
 				// \x95s\x90\xB3\x82\xC8UTF-8\x95\xB6\x8E\x9A\x97\xF1\x82̂Ȃ\xA9\x82\xC90x80\x96\xA2\x96\x9E\x82\xAA\x82\xA0\x82\xEA\x82΁A
 				// 1\x95\xB6\x8E\x9A\x82\xCCUTF-8\x95\xB6\x8E\x9A\x82Ƃ\xB5\x82Ă\xBB\x82̂܂ܕ\\x8E\xA6\x82\xB7\x82\xE9
-				PutU32(c);
+				w->Op.PutU32(c, w->ClientData);
 			}
 			else {
-				PutU32(replacement_char);
+				w->Op.PutU32(replacement_char, w->ClientData);
 			}
 		}
 	}
@@ -570,14 +580,13 @@
  *
  * returns TRUE if b is processed
  */
-static BOOL ParseFirstUTF8(BYTE b)
+static BOOL ParseFirstUTF8(CharSetData *w, BYTE b)
 {
-	VttermKanjiWork *w = &KanjiWork;
 	char32_t code;
 
-	if (Fallbacked) {
-		BOOL r = ParseFirstJP(b);
-		Fallbacked = FALSE;
+	if (w->Fallbacked) {
+		BOOL r = ParseFirstJP(w, b);
+		w->Fallbacked = FALSE;
 		return r;
 	}
 
@@ -614,12 +623,12 @@
 		if (IsC0(b)) {
 			// U+0000 .. U+001f
 			// C0\x90\xA7\x8C䕶\x8E\x9A, C0 Coontrols
-			ParseControl(b);
+			w->Op.ParseControl(b, w->ClientData);
 			return TRUE;
 		}
 		else if (b <= 0x7f) {
 			// 0x7f\x88ȉ\xBA, \x82̂Ƃ\xAB\x81A\x82\xBB\x82̂܂܏o\x97\xCD
-			PutU32(b);
+			w->Op.PutU32(b, w->ClientData);
 			return TRUE;
 		}
 		else if (0xc2 <= b && b <= 0xf4) {
@@ -635,14 +644,14 @@
 			if ((ts.Language == IdJapanese) && ismbbleadSJIS(b)) {
 				// \x93\xFA\x96{\x8C\xEA\x82̏ꍇ && Shift_JIS 1byte\x96\xDA
 				// Shift_JIS \x82\xC9 fallback
-				Fallbacked = TRUE;
-				ConvJIS = FALSE;
-				Kanji = b << 8;
-				KanjiIn = TRUE;
+				w->Fallbacked = TRUE;
+				w->ConvJIS = FALSE;
+				w->Kanji = b << 8;
+				w->KanjiIn = TRUE;
 				return TRUE;
 			}
 			// fallback ISO8859-1
-			PutU32(b);
+			w->Op.PutU32(b, w->ClientData);
 			return TRUE;
 		}
 		else {
@@ -672,10 +681,10 @@
 			if (IsC1(code)) {
 				// U+0080 .. u+009f
 				// C1\x90\xA7\x8C䕶\x8E\x9A, C1 Controls
-				ParseControl((BYTE)code);
+				w->Op.ParseControl((BYTE)code, w->ClientData);
 			}
 			else {
-				PutU32(code);
+				w->Op.PutU32(code, w->ClientData);
 			}
 			w->count = 0;
 			return TRUE;
@@ -697,7 +706,7 @@
 			code = ((w->buf[0] & 0xf) << 12);
 			code |= ((w->buf[1] & 0x3f) << 6);
 			code |= ((w->buf[2] & 0x3f));
-			PutU32(code);
+			w->Op.PutU32(code, w->ClientData);
 			w->count = 0;
 			return TRUE;
 		}
@@ -719,16 +728,16 @@
 	code |= ((w->buf[1] & 0x3f) << 12);
 	code |= ((w->buf[2] & 0x3f) << 6);
 	code |= (w->buf[3] & 0x3f);
-	PutU32(code);
+	w->Op.PutU32(code, w->ClientData);
 	w->count = 0;
 	return TRUE;
 }
 
-static BOOL ParseFirstRus(BYTE b)
+static BOOL ParseFirstRus(CharSetData *w, BYTE b)
 // returns if b is processed
 {
 	if (IsC0(b)) {
-		ParseControl(b);
+		w->Op.ParseControl(b, w->ClientData);
 		return TRUE;
 	}
 	// CP1251\x82ɕϊ\xB7
@@ -735,11 +744,11 @@
 	BYTE c = RussConv(ts.KanjiCode, IdWindows, b);
 	// CP1251->Unicode
 	unsigned long u32 = MBCP_UTF32(c, 1251);
-	PutU32(u32);
+	w->Op.PutU32(u32, w->ClientData);
 	return TRUE;
 }
 
-static BOOL ParseEnglish(BYTE b)
+static BOOL ParseEnglish(CharSetData *w, BYTE b)
 {
 	unsigned short u16 = 0;
 	int part = KanjiCodeToISO8859Part(ts.KanjiCode);
@@ -748,15 +757,15 @@
 		return FALSE;
 	}
 	if (u16 < 0x100) {
-		ParseASCII((BYTE)u16);
+		ParseASCII(w, (BYTE)u16);
 	}
 	else {
-		PutU32(u16);
+		w->Op.PutU32(u16, w->ClientData);
 	}
 	return TRUE;
 }
 
-static void PutDebugChar(BYTE b)
+static void PutDebugChar(CharSetData *w, BYTE b)
 {
 	int i;
 	BOOL svInsertMode, svAutoWrapMode;
@@ -773,15 +782,15 @@
 	char_attr.Attr = AttrDefault;
 	TermSetAttr(&char_attr);
 
-	if (DebugFlag==DEBUG_FLAG_HEXD) {
+	if (w->DebugFlag==DEBUG_FLAG_HEXD) {
 		char buff[3];
 		_snprintf(buff, 3, "%02X", (unsigned int) b);
 
 		for (i=0; i<2; i++)
-			PutChar(buff[i]);
-		PutChar(' ');
+			w->Op.PutU32(buff[i], w->ClientData);
+		w->Op.PutU32(' ', w->ClientData);
 	}
-	else if (DebugFlag==DEBUG_FLAG_NORM) {
+	else if (w->DebugFlag==DEBUG_FLAG_NORM) {
 
 		if ((b & 0x80) == 0x80) {
 			//UpdateStr();
@@ -791,18 +800,18 @@
 		}
 
 		if (b<=US) {
-			PutChar('^');
-			PutChar((char)(b+0x40));
+			w->Op.PutU32('^', w->ClientData);
+			w->Op.PutU32((char)(b + 0x40), w->ClientData);
 		}
 		else if (b==DEL) {
-			PutChar('<');
-			PutChar('D');
-			PutChar('E');
-			PutChar('L');
-			PutChar('>');
+			w->Op.PutU32('<', w->ClientData);
+			w->Op.PutU32('D', w->ClientData);
+			w->Op.PutU32('E', w->ClientData);
+			w->Op.PutU32('L', w->ClientData);
+			w->Op.PutU32('>', w->ClientData);
 		}
 		else
-			PutChar(b);
+			w->Op.PutU32(b, w->ClientData);
 	}
 
 	TermSetAttr(&char_attr);
@@ -810,27 +819,31 @@
 	TermSetAutoWrapMode(svAutoWrapMode);
 }
 
-void ParseFirst(BYTE b)
+void ParseFirst(CharSetData *w, BYTE b)
 {
 	WORD language = ts.Language;
-	if (DebugFlag != DEBUG_FLAG_NONE) {
+	if (w->DebugFlag != DEBUG_FLAG_NONE) {
 		language = IdDebug;
 	}
 
 	switch (language) {
+	default:
+		assert(FALSE);
+		language = IdUtf8;
+		// FALLTHROUGH
 	case IdUtf8:
-		ParseFirstUTF8(b);
+		ParseFirstUTF8(w, b);
 		return;
 
 	case IdJapanese:
 		switch (ts.KanjiCode) {
 		case IdUTF8:
-			if (ParseFirstUTF8(b)) {
+			if (ParseFirstUTF8(w, b)) {
 				return;
 			}
 			break;
 		default:
-			if (ParseFirstJP(b))  {
+			if (ParseFirstJP(w, b))  {
 				return;
 			}
 		}
@@ -839,12 +852,12 @@
 	case IdKorean:
 		switch (ts.KanjiCode) {
 		case IdUTF8:
-			if (ParseFirstUTF8(b)) {
+			if (ParseFirstUTF8(w, b)) {
 				return;
 			}
 			break;
 		default:
-			if (ParseFirstKR(b))  {
+			if (ParseFirstKR(w, b))  {
 				return;
 			}
 		}
@@ -851,7 +864,7 @@
 		break;
 
 	case IdRussian:
-		if (ParseFirstRus(b)) {
+		if (ParseFirstRus(w, b)) {
 			return;
 		}
 		break;
@@ -859,42 +872,42 @@
 	case IdChinese:
 		switch (ts.KanjiCode) {
 		case IdUTF8:
-			if (ParseFirstUTF8(b)) {
+			if (ParseFirstUTF8(w, b)) {
 				return;
 			}
 			break;
 		default:
-			if (ParseFirstCn(b)) {
+			if (ParseFirstCn(w, b)) {
 				return;
 			}
 		}
 		break;
 	case IdEnglish: {
-		if (ParseEnglish(b)) {
+		if (ParseEnglish(w, b)) {
 			return;
 		}
 		break;
 	}
 	case IdDebug: {
-		PutDebugChar(b);
+		PutDebugChar(w, b);
 		return;
 	}
 	}
 
-	if (SSflag) {
-		PutChar(b);
-		SSflag = FALSE;
+	if (w->SSflag) {
+		w->Op.PutU32(b, w->ClientData);
+		w->SSflag = FALSE;
 		return;
 	}
 
 	if (b<=US)
-		ParseControl(b);
+		w->Op.ParseControl(b, w->ClientData);
 	else if ((b>=0x20) && (b<=0x7E))
-		PutChar(b);
+		w->Op.PutU32(b, w->ClientData);
 	else if ((b>=0x80) && (b<=0x9F))
-		ParseControl(b);
+		w->Op.ParseControl(b, w->ClientData);
 	else if (b>=0xA0)
-		PutChar(b);
+		w->Op.PutU32(b, w->ClientData);
 }
 
 /**
@@ -906,9 +919,8 @@
  *						IdKanji	   2
  *						IdSpecial  3
  */
-void CharSet2022Designate(int gn, int cs)
+void CharSet2022Designate(CharSetData *w, int gn, int cs)
 {
-	VttermKanjiWork *w = &KanjiWork;
 	w->Gn[gn] = cs;
 }
 
@@ -916,9 +928,8 @@
  *	\x8CĂяo\x82\xB5(Invoke)
  *	@param	shift
  */
-void CharSet2022Invoke(CharSet2022Shift shift)
+void CharSet2022Invoke(CharSetData *w, CharSet2022Shift shift)
 {
-	VttermKanjiWork *w = &KanjiWork;
 	switch (shift) {
 	case CHARSET_LS0:
 		// Locking Shift 0 (G0->GL)
@@ -950,13 +961,13 @@
 		break;
 	case CHARSET_SS2:
 		// Single Shift 2
-		GLtmp = 2;
-		SSflag = TRUE;
+		w->GLtmp = 2;
+		w->SSflag = TRUE;
 		break;
 	case CHARSET_SS3:
 		// Single Shift 3
-		GLtmp = 3;
-		SSflag = TRUE;
+		w->GLtmp = 3;
+		w->SSflag = TRUE;
 		break;
 	default:
 		assert(FALSE);
@@ -975,20 +986,19 @@
  *	@retval	TRUE	IdSpecial
  *	@retval	FALSE	IdSpecial\x82ł͂Ȃ\xA2
  */
-BOOL CharSetIsSpecial(BYTE b)
+BOOL CharSetIsSpecial(CharSetData *w, BYTE b)
 {
-	VttermKanjiWork *w = &KanjiWork;
 	BOOL SpecialNew = FALSE;
 
 	if ((b>0x5F) && (b<0x80)) {
-		if (SSflag)
-			SpecialNew = (w->Gn[GLtmp]==IdSpecial);
+		if (w->SSflag)
+			SpecialNew = (w->Gn[w->GLtmp]==IdSpecial);
 		else
 			SpecialNew = (w->Gn[w->Glr[0]]==IdSpecial);
 	}
 	else if (b>0xDF) {
-		if (SSflag)
-			SpecialNew = (w->Gn[GLtmp]==IdSpecial);
+		if (w->SSflag)
+			SpecialNew = (w->Gn[w->GLtmp]==IdSpecial);
 		else
 			SpecialNew = (w->Gn[w->Glr[1]]==IdSpecial);
 	}
@@ -996,7 +1006,7 @@
 	return SpecialNew;
 }
 
-static void CharSetSaveStateLow(CharSetState *state, const VttermKanjiWork *w)
+static void CharSetSaveStateLow(CharSetState *state, const CharSetData *w)
 {
 	int i;
 	state->infos[0] = w->Glr[0];
@@ -1009,9 +1019,8 @@
 /**
  *	\x8F\xF3\x91Ԃ\xF0\x95ۑ\xB6\x82\xB7\x82\xE9
  */
-void CharSetSaveState(CharSetState *state)
+void CharSetSaveState(CharSetData *w, CharSetState *state)
 {
-	VttermKanjiWork *w = &KanjiWork;
 	CharSetSaveStateLow(state, w);
 }
 
@@ -1018,9 +1027,8 @@
 /**
  *	\x8F\xF3\x91Ԃ𕜋A\x82\xB7\x82\xE9
  */
-void CharSetLoadState(const CharSetState *state)
+void CharSetLoadState(CharSetData *w, const CharSetState *state)
 {
-	VttermKanjiWork *w = &KanjiWork;
 	int i;
 	w->Glr[0] = state->infos[0];
 	w->Glr[1] = state->infos[1];
@@ -1034,28 +1042,28 @@
  *		\x8E\xF3\x90M\x83f\x81[\x83^UTF-8\x8E\x9E\x82ɁAShift_JIS\x8Fo\x97͒\x86(fallback\x8F\xF3\x91\xD4)\x82𒆒f\x82\xB7\x82\xE9
  *
  */
-void CharSetFallbackFinish(void)
+void CharSetFallbackFinish(CharSetData *w)
 {
-	Fallbacked = FALSE;
+	w->Fallbacked = FALSE;
 }
 
 /**
  *	\x83f\x83o\x83O\x8Fo\x97͂\xF0\x8E\x9F\x82̃\x82\x81[\x83h\x82ɕύX\x82\xB7\x82\xE9
  */
-void CharSetSetNextDebugMode(void)
+void CharSetSetNextDebugMode(CharSetData *w)
 {
 	// ts.DebugModes \x82ɂ\xCD tttypes.h \x82\xCC DBGF_* \x82\xAA OR \x82œ\xFC\x82\xC1\x82Ă\xE9
 	do {
-		DebugFlag = (DebugFlag + 1) % DEBUG_FLAG_MAXD;
-	} while (DebugFlag != DEBUG_FLAG_NONE && !((ts.DebugModes >> (DebugFlag - 1)) & 1));
+		w->DebugFlag = (w->DebugFlag + 1) % DEBUG_FLAG_MAXD;
+	} while (w->DebugFlag != DEBUG_FLAG_NONE && !((ts.DebugModes >> (w->DebugFlag - 1)) & 1));
 }
 
-BYTE CharSetGetDebugMode(void)
+BYTE CharSetGetDebugMode(CharSetData *w)
 {
-	return DebugFlag;
+	return w->DebugFlag;
 }
 
-void CharSetSetDebugMode(BYTE mode)
+void CharSetSetDebugMode(CharSetData *w, BYTE mode)
 {
-	DebugFlag = mode;
+	w->DebugFlag = mode % DEBUG_FLAG_MAXD;
 }

Modified: trunk/teraterm/teraterm/charset.h
===================================================================
--- trunk/teraterm/teraterm/charset.h	2023-06-27 13:28:58 UTC (rev 10781)
+++ trunk/teraterm/teraterm/charset.h	2023-06-27 13:36:25 UTC (rev 10782)
@@ -26,21 +26,29 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include "ttcstd.h"
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+typedef struct CharSetDataTag CharSetData;
+
 typedef struct {
 	int infos[6];
 } CharSetState;
 
+// \x95\xB6\x8E\x9A\x82̏o\x97\xCD
+typedef struct CharSetOpTag {
+	// \x8Fo\x97͂\xB3\x82\xEA\x82\xE9 Unicode \x95\xB6\x8E\x9A
+	void (*PutU32)(char32_t code, void *client_data);
+	// \x8Fo\x97͂\xB3\x82\xEA\x82\xE9 Control \x95\xB6\x8E\x9A
+	void (*ParseControl)(BYTE b, void *client_data);
+} CharSetOp;
+
 // input
-void ParseFirst(BYTE b);
+void ParseFirst(CharSetData *w, BYTE b);
 
-// output buffer
-void PutU32(unsigned int code);
-void ParseControl(BYTE b);
-
 // control
 typedef enum {
 	CHARSET_LS0,	// Locking Shift 0, SI, 0F (G0->GL)
@@ -53,14 +61,16 @@
 	CHARSET_SS2,	// Single Shift 2, SS2, 8E, ESC N, 1B 4E
 	CHARSET_SS3,	// Single Shift 3, SS3, 8F, ESC O, 1B 4F
 } CharSet2022Shift;
-void CharSetInit(void);
-void CharSet2022Designate(int gn, int cs);
-void CharSet2022Invoke(CharSet2022Shift shift);
-BOOL CharSetIsSpecial(BYTE b);
-void CharSetSaveState(CharSetState *state);
-void CharSetLoadState(const CharSetState *state);
-void CharSetFallbackFinish(void);
 
+CharSetData *CharSetInit(const CharSetOp *op, void *client_data);
+void CharSetFinish(CharSetData *w);
+void CharSet2022Designate(CharSetData *w, int gn, int cs);
+void CharSet2022Invoke(CharSetData *w, CharSet2022Shift shift);
+BOOL CharSetIsSpecial(CharSetData *w, BYTE b);
+void CharSetSaveState(CharSetData *w, CharSetState *state);
+void CharSetLoadState(CharSetData *w, const CharSetState *state);
+void CharSetFallbackFinish(CharSetData *w);
+
 // debug mode
 #define DEBUG_FLAG_NONE  0
 #define DEBUG_FLAG_NORM  1
@@ -67,9 +77,9 @@
 #define DEBUG_FLAG_HEXD  2
 #define DEBUG_FLAG_NOUT  3
 #define DEBUG_FLAG_MAXD  4
-void CharSetSetNextDebugMode(void);
-//BYTE CharSetGetDebugMode(void);
-void CharSetSetDebugMode(BYTE mode);
+void CharSetSetNextDebugMode(CharSetData *w);
+//BYTE CharSetGetDebugMode(CharSetData *w);
+void CharSetSetDebugMode(CharSetData *w, BYTE mode);
 
 #ifdef __cplusplus
 }

Modified: trunk/teraterm/teraterm/keyboard.c
===================================================================
--- trunk/teraterm/teraterm/keyboard.c	2023-06-27 13:28:58 UTC (rev 10781)
+++ trunk/teraterm/teraterm/keyboard.c	2023-06-27 13:36:25 UTC (rev 10782)
@@ -44,7 +44,7 @@
 #include "ttwinman.h"
 #include "ttdde.h"
 #include "codeconv.h"
-#include "charset.h"
+#include "vtterm.h"
 
 #include "keyboard.h"
 #include "keyboard_i.h"
@@ -1374,7 +1374,7 @@
 	/* debug mode */
 	if (ts.Debug && (VKey == VK_ESCAPE) && ShiftKey()) {
 		MessageBeep(0);
-		CharSetSetNextDebugMode();
+		TermSetNextDebugMode();
 		CodeCount = 0;
 		PeekMessage((LPMSG)&M, HWin, WM_CHAR, WM_CHAR, PM_REMOVE);
 		return KEYDOWN_CONTROL;

Modified: trunk/teraterm/teraterm/ttdde.c
===================================================================
--- trunk/teraterm/teraterm/ttdde.c	2023-06-27 13:28:58 UTC (rev 10781)
+++ trunk/teraterm/teraterm/ttdde.c	2023-06-27 13:36:25 UTC (rev 10782)
@@ -50,7 +50,7 @@
 #include "codeconv.h"
 #include "scp.h"
 #include "asprintf.h"
-#include "charset.h"
+#include "vtterm.h"
 
 #define ServiceName "TERATERM"
 #define ItemName "DATA"
@@ -664,7 +664,7 @@
 			TelChangeEcho();
 		break;
 	case CmdSetDebug:
-		CharSetSetDebugMode((Command[1] - '0') % DEBUG_FLAG_MAXD);
+		TermSetDebugMode(Command[1] - '0');
 		break;
 	case CmdSetTitle:
 		strncpy_s(ts.Title, sizeof(ts.Title),ParamFileName, _TRUNCATE);

Modified: trunk/teraterm/teraterm/vtterm.c
===================================================================
--- trunk/teraterm/teraterm/vtterm.c	2023-06-27 13:28:58 UTC (rev 10781)
+++ trunk/teraterm/teraterm/vtterm.c	2023-06-27 13:36:25 UTC (rev 10782)
@@ -203,6 +203,7 @@
 	int log_cr_type;
 } vtterm_work_t;
 
+static CharSetData *charset_data;
 static vtterm_work_t vtterm_work;
 
 static void ClearParams(void)
@@ -220,7 +221,7 @@
 	Buff->CursorY = CursorY;
 	Buff->Attr = CharAttr;
 
-	CharSetSaveState(&Buff->CharSetState);
+	CharSetSaveState(charset_data, &Buff->CharSetState);
 	Buff->AutoWrapMode = AutoWrapMode;
 	Buff->RelativeOrgMode = RelativeOrgMode;
 }
@@ -260,7 +261,7 @@
 
 	CharAttr = Buff->Attr;
 	BuffSetCurCharAttr(CharAttr);
-	CharSetLoadState(&Buff->CharSetState);
+	CharSetLoadState(charset_data, &Buff->CharSetState);
 
 	AutoWrapMode = Buff->AutoWrapMode;
 	RelativeOrgMode = Buff->RelativeOrgMode;
@@ -358,6 +359,8 @@
 	}
 }
 
+static CharSetData *CharSetInitTerm(void);
+
 void ResetCharSet()
 {
 	if (ts.Language != IdJapanese) {
@@ -374,7 +377,10 @@
 	cv.KanjiIn = ts.KanjiIn;
 	cv.KanjiOut = ts.KanjiOut;
 
-	CharSetInit();
+	if (charset_data != NULL) {
+		CharSetFinish(charset_data);
+	}
+	charset_data = CharSetInitTerm();
 }
 
 void ResetKeypadMode(BOOL DisabledModeOnly)
@@ -653,7 +659,7 @@
 	else if (CursorX < CursorLeftM)
 		MoveCursor(0, CursorY);
 
-	CharSetFallbackFinish();
+	CharSetFallbackFinish(charset_data);
 }
 
 static void LineFeed(BYTE b, BOOL logFlag)
@@ -676,7 +682,7 @@
 
 	if (LFMode) CarriageReturn(logFlag);
 
-	CharSetFallbackFinish();
+	CharSetFallbackFinish(charset_data);
 }
 
 static void Tab(void)
@@ -716,7 +722,7 @@
 		BOOL SpecialNew = FALSE;
 
 		if (code <= 0xff) {
-			SpecialNew = CharSetIsSpecial(code);
+			SpecialNew = CharSetIsSpecial(charset_data, code);
 			if (SpecialNew) {
 				code = code & 0x7F;
 			}
@@ -843,7 +849,7 @@
  *
  *	PutChar() \x82\xCC UTF-32\x94\xC5
  */
-void PutU32(unsigned int code)
+static void PutU32(unsigned int code)
 {
 	PutU32NoLog(code);
 
@@ -979,10 +985,10 @@
 			    (ts.JIS7Katakana==1) &&
 			    ((ts.TermFlag & TF_FIXEDJIS)!=0))
 			{
-				CharSet2022Designate(1, IdKatakana);
+				CharSet2022Designate(charset_data, 1, IdKatakana);
 			}
 			/* LS1 */
-			CharSet2022Invoke(CHARSET_LS1);
+			CharSet2022Invoke(charset_data, CHARSET_LS1);
 			return;
 		}
 		break;
@@ -989,7 +995,7 @@
 	case SI:
 		if ((ts.ISO2022Flag & ISO2022_SI) && ! DirectPrn) {
 			/* LS0 */
-			CharSet2022Invoke(CHARSET_LS0);
+			CharSet2022Invoke(charset_data, CHARSET_LS0);
 			return;
 		}
 		break;
@@ -1018,7 +1024,7 @@
 	WriteToPrnFile(PrintFile_, b, TRUE);
 }
 
-void ParseControl(BYTE b)
+static void ParseControl(BYTE b)
 {
 	if (PrinterMode) { // printer mode
 		PrnParseControl(b);
@@ -1121,15 +1127,15 @@
 			    (ts.JIS7Katakana==1) &&
 			    ((ts.TermFlag & TF_FIXEDJIS)!=0))
 			{
-				CharSet2022Designate(1, IdKatakana);
+				CharSet2022Designate(charset_data, 1, IdKatakana);
 			}
 
-			CharSet2022Invoke(CHARSET_LS1);
+			CharSet2022Invoke(charset_data, CHARSET_LS1);
 		}
 		break;
 	case SI: /* LS0 */
 		if (ts.ISO2022Flag & ISO2022_SI) {
-			CharSet2022Invoke(CHARSET_LS0);
+			CharSet2022Invoke(charset_data, CHARSET_LS0);
 		}
 		break;
 	case DLE:
@@ -1179,12 +1185,12 @@
 		break;
 	case SS2:
 		if (ts.ISO2022Flag & ISO2022_SS2) {
-			CharSet2022Invoke(CHARSET_SS2);
+			CharSet2022Invoke(charset_data, CHARSET_SS2);
 		}
 		break;
 	case SS3:
 		if (ts.ISO2022Flag & ISO2022_SS3) {
-			CharSet2022Invoke(CHARSET_SS3);
+			CharSet2022Invoke(charset_data, CHARSET_SS3);
 		}
 		break;
 	case DCS:
@@ -1213,6 +1219,26 @@
 	}
 }
 
+static void csPutU32(char32_t code, void *client_data)
+{
+	(void)client_data;
+	PutU32(code);
+}
+
+static void csParseControl(BYTE b, void *client_data)
+{
+	(void)client_data;
+	ParseControl(b);
+}
+
+static CharSetData *CharSetInitTerm(void)
+{
+	CharSetOp op;
+	op.PutU32 = csPutU32;
+	op.ParseControl = csParseControl;
+	return CharSetInit(&op, NULL);
+}
+
 static void AnswerTerminalType(void)
 {
 	char Tmp[50];
@@ -1313,10 +1339,10 @@
 			if ((b=='@') || (b=='B'))
 			{
 				/* Kanji -> G0 */
-				CharSet2022Designate(0, IdKanji);
+				CharSet2022Designate(charset_data, 0, IdKanji);
 				if ((ts.TermFlag & TF_AUTOINVOKE)!=0) {
 					/* G0->GL */
-					CharSet2022Invoke(CHARSET_LS0);
+					CharSet2022Invoke(charset_data, CHARSET_LS0);
 				}
 			}
 			break;
@@ -1339,10 +1365,10 @@
 					(b=='@') || (b=='B'))
 			{
 				/* Kanji -> G0-3 */
-				CharSet2022Designate(Dist, IdKanji);
+				CharSet2022Designate(charset_data, Dist, IdKanji);
 				if (((ts.TermFlag & TF_AUTOINVOKE)!=0) && (Dist==0)) {
 					/* G0->GL */
-					CharSet2022Invoke(CHARSET_LS0);
+					CharSet2022Invoke(charset_data, CHARSET_LS0);
 				}
 			}
 			break;
@@ -1369,7 +1395,7 @@
 
 	switch (b) {
 	case '0':
-		CharSet2022Designate(Dist, IdSpecial);
+		CharSet2022Designate(charset_data, Dist, IdSpecial);
 		break;
 	case '<':
 	case '>':
@@ -1376,20 +1402,20 @@
 	case 'A':
 	case 'B':
 	case 'H':
-		CharSet2022Designate(Dist, IdASCII);
+		CharSet2022Designate(charset_data, Dist, IdASCII);
 		break;
 	case 'I':
 		if (ts.Language==IdJapanese)
-			CharSet2022Designate(Dist, IdKatakana);
+			CharSet2022Designate(charset_data, Dist, IdKatakana);
 		break;
 	case 'J':
-		CharSet2022Designate(Dist, IdASCII);
+		CharSet2022Designate(charset_data, Dist, IdASCII);
 		break;
 	}
 
 	if (((ts.TermFlag & TF_AUTOINVOKE)!=0) && (Dist==0)) {
 		/* G0->GL */
-		CharSet2022Invoke(CHARSET_LS0);
+		CharSet2022Invoke(charset_data, CHARSET_LS0);
 	}
 }
 
@@ -1498,12 +1524,12 @@
 			break;
 		case 'N': /* SS2 */
 			if (ts.ISO2022Flag & ISO2022_SS2) {
-				CharSet2022Invoke(CHARSET_SS2);
+				CharSet2022Invoke(charset_data, CHARSET_SS2);
 			}
 			break;
 		case 'O': /* SS3 */
 			if (ts.ISO2022Flag & ISO2022_SS3) {
-				CharSet2022Invoke(CHARSET_SS3);
+				CharSet2022Invoke(charset_data, CHARSET_SS3);
 			}
 			break;
 		case 'P': /* DCS */
@@ -1543,27 +1569,27 @@
 			break;
 		case 'n': /* LS2 */
 			if (ts.ISO2022Flag & ISO2022_LS2) {
-				CharSet2022Invoke(CHARSET_LS2);
+				CharSet2022Invoke(charset_data, CHARSET_LS2);
 			}
 			break;
 		case 'o': /* LS3 */
 			if (ts.ISO2022Flag & ISO2022_LS3) {
-				CharSet2022Invoke(CHARSET_LS3);
+				CharSet2022Invoke(charset_data, CHARSET_LS3);
 			}
 			break;
 		case '|': /* LS3R */
 			if (ts.ISO2022Flag & ISO2022_LS3R) {
-				CharSet2022Invoke(CHARSET_LS3R);
+				CharSet2022Invoke(charset_data, CHARSET_LS3R);
 			}
 			break;
 		case '}': /* LS2R */
 			if (ts.ISO2022Flag & ISO2022_LS2R) {
-				CharSet2022Invoke(CHARSET_LS2R);
+				CharSet2022Invoke(charset_data, CHARSET_LS2R);
 			}
 			break;
 		case '~': /* LS1R */
 			if (ts.ISO2022Flag & ISO2022_LS1R) {
-				CharSet2022Invoke(CHARSET_LS1R);
+				CharSet2022Invoke(charset_data, CHARSET_LS1R);
 			}
 			break;
 		}
@@ -1611,7 +1637,7 @@
 		ParseControl(b);
 	else if (b>=0xA0) {
 		ParseMode=ModeFirst;
-		ParseFirst(b);
+		ParseFirst(charset_data, b);
 	}
 
 	JustAfterESC = FALSE;
@@ -1984,7 +2010,7 @@
 		else
 			MoveCursor(CursorX,Param[1]-1);
 	}
-	CharSetFallbackFinish();
+	CharSetFallbackFinish(charset_data);
 }
 
 static void CSMoveToXY()		// CUP / HVP
@@ -2015,7 +2041,7 @@
 	}
 
 	MoveCursor(NewX, NewY);
-	CharSetFallbackFinish();
+	CharSetFallbackFinish(charset_data);
 }
 
 static void CSDeleteTabStop()
@@ -2936,16 +2962,16 @@
 		  case 59:
 			if (ts.Language==IdJapanese) {
 				/* kanji terminal */
-				CharSet2022Designate(0, IdASCII);
-				CharSet2022Designate(1, IdKatakana);
-				CharSet2022Designate(2, IdKatakana);
-				CharSet2022Designate(3, IdKanji);
-				CharSet2022Invoke(CHARSET_LS0);
+				CharSet2022Designate(charset_data, 0, IdASCII);
+				CharSet2022Designate(charset_data, 1, IdKatakana);
+				CharSet2022Designate(charset_data, 2, IdKatakana);
+				CharSet2022Designate(charset_data, 3, IdKanji);
+				CharSet2022Invoke(charset_data, CHARSET_LS0);
 				if ((ts.KanjiCode==IdJIS) && (ts.JIS7Katakana==0))
 					// 8-bit katakana
-					CharSet2022Invoke(CHARSET_LS2R);
+					CharSet2022Invoke(charset_data, CHARSET_LS2R);
 				else
-					CharSet2022Invoke(CHARSET_LS3R);
+					CharSet2022Invoke(charset_data, CHARSET_LS3R);
 			}
 			break;
 		  case 66: AppliKeyMode = TRUE; break;		// DECNKM
@@ -3106,16 +3132,16 @@
 		  case 59:
 			if (ts.Language==IdJapanese) {
 				/* katakana terminal */
-				CharSet2022Designate(0, IdASCII);
-				CharSet2022Designate(1, IdKatakana);
-				CharSet2022Designate(2, IdKatakana);
-				CharSet2022Designate(3, IdKanji);
-				CharSet2022Invoke(CHARSET_LS0);
+				CharSet2022Designate(charset_data, 0, IdASCII);
+				CharSet2022Designate(charset_data, 1, IdKatakana);
+				CharSet2022Designate(charset_data, 2, IdKatakana);
+				CharSet2022Designate(charset_data, 3, IdKanji);
+				CharSet2022Invoke(charset_data, CHARSET_LS0);
 				if ((ts.KanjiCode==IdJIS) && (ts.JIS7Katakana==0))
 					// 8-bit katakana
-					CharSet2022Invoke(CHARSET_LS2R);
+					CharSet2022Invoke(charset_data, CHARSET_LS2R);
 				else
-					CharSet2022Invoke(CHARSET_LS3R);
+					CharSet2022Invoke(charset_data, CHARSET_LS3R);
 			}
 			break;
 		  case 66: AppliKeyMode = FALSE; break;		// DECNKM
@@ -4152,7 +4178,7 @@
 		}
 		else if (b>0xA0) {
 			ParseMode=ModeFirst;
-			ParseFirst(b);
+			ParseFirst(charset_data, b);
 		}
 	}
 	FirstPrm = FALSE;
@@ -5353,7 +5379,7 @@
 #endif
 		switch (ParseMode) {
 		case ModeFirst:
-			ParseFirst(b);
+			ParseFirst(charset_data, b);
 			break;
 		case ModeESC:
 			EscapeSequence(b);
@@ -5384,7 +5410,7 @@
 			break;
 		default:
 			ParseMode = ModeFirst;
-			ParseFirst(b);
+			ParseFirst(charset_data, b);
 		}
 
 		PrevCharacter = b;		// memorize previous character for AUTO CR/LF-receive mode
@@ -5756,6 +5782,8 @@
 		_free_locale(CLocale);
 	}
 	CLocale = NULL;
+	CharSetFinish(charset_data);
+	charset_data = NULL;
 }
 
 BOOL BracketedPasteMode() {
@@ -5858,3 +5886,13 @@
 {
 	AutoWrapMode = auto_wrap_mode;
 }
+
+void TermSetNextDebugMode(void)
+{
+	CharSetSetNextDebugMode(charset_data);
+}
+
+void TermSetDebugMode(BYTE mode)
+{
+	CharSetSetDebugMode(charset_data, mode);
+}

Modified: trunk/teraterm/teraterm/vtterm.h
===================================================================
--- trunk/teraterm/teraterm/vtterm.h	2023-06-27 13:28:58 UTC (rev 10781)
+++ trunk/teraterm/teraterm/vtterm.h	2023-06-27 13:36:25 UTC (rev 10782)
@@ -60,6 +60,8 @@
 void TermSetInsertMode(BOOL insert_mode);
 BOOL TermGetAutoWrapMode(void);
 void TermSetAutoWrapMode(BOOL auto_wrap_mode);
+void TermSetNextDebugMode(void);
+void TermSetDebugMode(BYTE mode);
 
 #ifdef __cplusplus
 }


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