Revision: 8766 https://osdn.net/projects/ttssh2/scm/svn/commits/8766 Author: zmatsuo Date: 2020-05-06 23:52:04 +0900 (Wed, 06 May 2020) Log Message: ----------- CJK,2byte文字の入力をできるようにした - 2byte系 - KS5601, CP51949, ハングル - CP936, GB2312 - CP950, Big5 - KanjiCode2List(), List2KanjiCode() を ttlib.c から ttdlg.c へ移動 - IdChinese (tttype.h) 追加 - コードページやロケールの設定なしにメニューから設定できるようにする - struct tttset に UnicodeAmbiguousAsWide 追加 - UnicodeAmbiguousWide=ON/OFF を teraterm.ini に追加 Modified Paths: -------------- trunk/teraterm/common/ttlib.c trunk/teraterm/common/ttlib.h trunk/teraterm/common/tttypes.h trunk/teraterm/teraterm/buffer.c trunk/teraterm/teraterm/vtterm.c trunk/teraterm/ttpdlg/ttdlg.c trunk/teraterm/ttpset/ttset.c -------------- next part -------------- Modified: trunk/teraterm/common/ttlib.c =================================================================== --- trunk/teraterm/common/ttlib.c 2020-05-06 14:51:43 UTC (rev 8765) +++ trunk/teraterm/common/ttlib.c 2020-05-06 14:52:04 UTC (rev 8766) @@ -1529,53 +1529,28 @@ return CDSIZEOF_STRUCT(OPENFILENAMEW,lpTemplateName); } -// convert table for KanjiCodeID and ListID -// cf. KanjiList,KanjiListSend -// KoreanList,KoreanListSend -// Utf8List,Utf8ListSend -// IdSJIS, IdEUC, IdJIS, IdUTF8, IdUTF8m -// IdEnglish, IdJapanese, IdRussian, IdKorean, IdUtf8 -/* KanjiCode2List(Language,KanjiCodeID) returns ListID */ -int KanjiCode2List(int lang, int kcode) -{ - int Table[5][5] = { - {1, 2, 3, 4, 5}, /* English (dummy) */ - {1, 2, 3, 4, 5}, /* Japanese(dummy) */ - {1, 2, 3, 4, 5}, /* Russian (dummy) */ - {1, 1, 1, 2, 3}, /* Korean */ - {1, 1, 1, 1, 2}, /* Utf8 */ - }; - lang--; - kcode--; - return Table[lang][kcode]; -} -/* List2KanjiCode(Language,ListID) returns KanjiCodeID */ -int List2KanjiCode(int lang, int list) -{ - int Table[5][5] = { - {1, 2, 3, 4, 5}, /* English (dummy) */ - {1, 2, 3, 4, 5}, /* Japanese(dummy) */ - {1, 2, 3, 4, 5}, /* Russian (dummy) */ - {1, 4, 5, 1, 1}, /* Korean */ - {4, 5, 4, 4, 4}, /* Utf8 */ - }; - lang--; - list--; - if (list < 0) { - list = 0; - } - return Table[lang][list]; -} -/* KanjiCodeTranslate(Language(dest), KanjiCodeID(source)) returns KanjiCodeID */ +/** + * KanjiCodeTranslate(Language(dest), KanjiCodeID(source)) returns KanjiCodeID + * @param[in] lang (IdEnglish, IdJapanese, IdRussian, ...) + * @param[in] kcode (IdSJIS, IdEUC, ... IdKOI8 ... ) + * @return lang\x82ɑ\xB6\x8D݂\xB7\x82銿\x8E\x9A\x83R\x81[\x83h\x82\xF0\x95Ԃ\xB7 + * + * lang\x82ɑ\xB6\x8D݂\xB5\x82Ȃ\xA2\x8A\xBF\x8E\x9A\x83R\x81[\x83h\x82\xF0\x8Eg\x97p\x82\xB5\x82Ȃ\xA2\x82悤\x82\xB1\x82̊\x94\x82\xF0\x8Eg\x97p\x82\xB7\x82\xE9 + * - ini\x83t\x83@\x83C\x83\x8B\x82̓ǂݍ\x9E\x82ݎ\x9E + * - \x90ݒ\xE8\x82\xC5lang\x82\xF0\x90\xE8\x91ւ\xA6\x82\xBD\x8E\x9E + */ int KanjiCodeTranslate(int lang, int kcode) { - int Table[5][5] = { + static const int Table[][5] = { {1, 2, 3, 4, 5}, /* to English (dummy) */ {1, 2, 3, 4, 5}, /* to Japanese(dummy) */ {1, 2, 3, 4, 5}, /* to Russian (dummy) */ {1, 1, 1, 4, 5}, /* to Korean */ {4, 4, 4, 4, 5}, /* to Utf8 */ + {1, 2, 2, 2, 2}, /* to Chinese */ }; + if (lang < 1 || lang > IdLangMax) lang = 1; + if (kcode < 1 || kcode > 5) kcode = 1; lang--; kcode--; return Table[lang][kcode]; Modified: trunk/teraterm/common/ttlib.h =================================================================== --- trunk/teraterm/common/ttlib.h 2020-05-06 14:51:43 UTC (rev 8765) +++ trunk/teraterm/common/ttlib.h 2020-05-06 14:52:04 UTC (rev 8766) @@ -101,8 +101,6 @@ DllExport BOOL HasGetAdaptersAddresses(); DllExport BOOL HasDnsQuery(); DllExport BOOL HasBalloonTipSupport(); -int KanjiCode2List(int lang, int kcode); -int List2KanjiCode(int lang, int kcode); int KanjiCodeTranslate(int lang, int kcode); DllExport char *mctimelocal(char *format, BOOL utc_flag); char *strelapsed(DWORD start_time); Modified: trunk/teraterm/common/tttypes.h =================================================================== --- trunk/teraterm/common/tttypes.h 2020-05-06 14:51:43 UTC (rev 8765) +++ trunk/teraterm/common/tttypes.h 2020-05-06 14:52:04 UTC (rev 8766) @@ -189,7 +189,8 @@ #define IdRussian 3 #define IdKorean 4 //HKS #define IdUtf8 5 -#define IdLangMax IdUtf8 +#define IdChinese 6 +#define IdLangMax IdChinese // LogDialog Option #define LOGDLG_BINARY 1 @@ -678,6 +679,7 @@ int ConfigVersion; int RunningVersion; DWORD SelectStartDelay; + WORD UnicodeAmbiguousAsWide; }; typedef struct tttset TTTSet, *PTTSet; @@ -703,12 +705,19 @@ #define IdVT525 12 /* Kanji Code ID */ + /* ts.KanjiCode, ts.KanjiCodeSend \x82̒l */ + +// ts.Language == IdEnglish +#define IdCodeEnglish 1 + +// ts.Language == IdJapanese #define IdSJIS 1 #define IdEUC 2 #define IdJIS 3 -#define IdUTF8 4 +#define IdUTF8 4 // IdUtf8 (\x8F\xAC\x95\xB6\x8E\x9A)\x82\xCD ts.Language \x97p #define IdUTF8m 5 +// ts.Language == IdRussian // Russian code sets #define IdWindows 1 #define IdKOI8 2 @@ -715,6 +724,15 @@ #define Id866 3 #define IdISO 4 +// ts.Language == IdKorean +// Korean +#define IdKoreanCP51949 1 // CP51949, KS5601 + +// ts.Language == IdChinese +// China +#define IdCnGB2312 1 // 1 CP936, GB2312 +#define IdCnBig5 2 // 2 CP950, Big5 + /* KanjiIn modes */ #define IdKanjiInA 1 #define IdKanjiInB 2 Modified: trunk/teraterm/teraterm/buffer.c =================================================================== --- trunk/teraterm/teraterm/buffer.c 2020-05-06 14:51:43 UTC (rev 8765) +++ trunk/teraterm/teraterm/buffer.c 2020-05-06 14:52:04 UTC (rev 8766) @@ -57,7 +57,7 @@ typedef struct { char32_t u32; char32_t u32_last; - char WidthProperty; // 'W' or 'F' or 'H' or 'A' (\x95\xB6\x8E\x9A\x82̑\xAE\x90\xAB) + char WidthProperty; // 'W' or 'F' or 'H' or 'A' or 'n'(Narrow) or 'N'(Neutual) (\x95\xB6\x8E\x9A\x82̑\xAE\x90\xAB) char HalfWidth; // TRUE/FALSE = \x94\xBC\x8Ap/\x91S\x8Ap (\x95\\x8E\xA6\x82\xB7\x82\xE9\x82Ƃ\xAB\x82̕\xB6\x8E\x9A\x95\x9D) char Padding; // TRUE = \x91S\x8Ap\x82̎\x9F\x82̋l\x82ߕ\xA8 or \x8Ds\x96\x96\x82̋l\x82ߕ\xA8 char Emoji; // TRUE = \x8AG\x95\xB6\x8E\x9A @@ -2209,12 +2209,13 @@ } } -static BOOL BuffIsHalfWidthFromCode(TTTSet *ts_, unsigned int u32, char *width_property, char *emoji) +static BOOL BuffIsHalfWidthFromCode(const TTTSet *ts_, unsigned int u32, char *width_property, char *emoji) { *width_property = UnicodeGetWidthProperty(u32); *emoji = (char)UnicodeIsEmoji(u32); if (*emoji) { - if (ts_->Language == IdJapanese) { + //if (ts_->Language == IdJapanese) { + if (ts_->UnicodeAmbiguousAsWide) { // \x91S\x8Ap return FALSE; } else { @@ -2475,9 +2476,6 @@ // \x8C\xBB\x8D\xDDx\x82\xAA\x88\xEA\x94ԉE? if ((cur_y + 1) < NumOfLines) { if ((CodeLineW[x].attr & AttrLineContinued) != 0) { - if ((cur_y + 1) == 24) { - int a = 0; - } const LONG TmpPtr = GetLinePtr(PageStart + cur_y + 1); if ((CodeLineW[TmpPtr + NumOfColumns - 1].attr & AttrURL) != 0) { next = TRUE; @@ -3158,7 +3156,6 @@ bufW[lenW] = b->wc2[1]; bufWW[lenW] = '0'; lenW++; -// DrawFlag = TRUE; // \x82\xB7\x82\xAE\x82ɕ`\x89悷\x82\xE9 } if (b->CombinationCharCount16 != 0) { @@ -3183,6 +3180,10 @@ bufA[lenA] = ansi_char & 0xff; lenA++; } + + if (b->WidthProperty == 'A' || b->WidthProperty == 'N') { + DrawFlag = TRUE; + } } // \x8DŌ\xE3\x82܂ŃX\x83L\x83\x83\x83\x93\x82\xB5\x82\xBD? Modified: trunk/teraterm/teraterm/vtterm.c =================================================================== --- trunk/teraterm/teraterm/vtterm.c 2020-05-06 14:51:43 UTC (rev 8765) +++ trunk/teraterm/teraterm/vtterm.c 2020-05-06 14:52:04 UTC (rev 8766) @@ -63,7 +63,7 @@ #include "unicode_test.h" -void ParseFirst(BYTE b); +static void ParseFirst(BYTE b); #define Accept8BitCtrl ((VTlevel >= 2) && (ts.TermFlag & TF_ACCEPT8BITCTRL)) @@ -921,23 +921,40 @@ // codepage\x88ꗗ // https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-ucoderef/28fefe92-d66c-4b03-90a9-97b473223d43 unsigned long u32 = 0; - if (ts.Language == IdKorean && ts.CodePage == 51949) { -#if 0 - unsigned char buf[2]; - int ret; - wchar_t wchar; - buf[0] = Kanji >> 8; - buf[1] = Kanji & 0xff; - ret = MultiByteToWideChar(51949, MB_ERR_INVALID_CHARS, (char *)buf, 2, &wchar, 1); - u32 = wchar; -#endif - u32 = MBCP_UTF32(Kanji, ts.CodePage); - } else if (ts.Language == IdJapanese && ts.CodePage == 932) { + switch (ts.Language) { + case IdJapanese: // \x82\xB1\x82\xB1\x82ɗ\x88\x82\xBD\x8E\x9E\x93_\x82\xC5CP932\x82ɂȂ\xC1\x82Ă\xA2\x82\xE9 - //} else if (ts.KanjiCode == IdSJIS || ts.KanjiCode == IdEUC || ts.KanjiCode == IdJIS) { u32 = CP932ToUTF32(Kanji); - } else { + break; + case IdKorean: + if (ts.KanjiCode == IdKoreanCP51949) { + // CP51949 + u32 = MBCP_UTF32(Kanji, 51949); + } + else { + assert(FALSE); + goto default_; + } + 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); + goto default_; + } + break; + default: + default_: + assert(FALSE); u32 = MBCP_UTF32(Kanji, ts.CodePage); + break; } CharAttrTmp.AttrEx = CharAttrTmp.Attr; BuffPutUnicode(u32, CharAttrTmp, InsertMode); @@ -5391,27 +5408,109 @@ } /** - * dbcs\x82\xCC1byte\x96ڃ`\x83F\x83b\x83N? + * IsDBCSLeadByteEx() \x82Ƃقړ\xAF\x82\xB6 + * ismbblead() \x82̊g\x92\xA3 */ +int __ismbblead(BYTE b, int code_page) +{ + switch (code_page) { + case 932: + // \x93\xFA\x96{\x8C\xEA shift jis + if (((0x81 <= b) && (b <= 0x9f)) || ((0xe0 <= b) && (b <= 0xfc))) { + return TRUE; + } + return FALSE; + case 51949: + // Korean CP51949 + if ((0xA1 <= b) && (b <= 0xFE)) { + return TRUE; + } + return FALSE; + case 936: + // CP936 GB2312 + if ((0xA1 <= b) && (b <= 0xFE)) { + return TRUE; + } + return FALSE; + case 950: + // CP950 Big5 + if (((0xA1 <= b) && (b <= 0xc6)) || ((0xc9 <= b) && (b <= 0xf9))) { + return TRUE; + } + return FALSE; + default: + break; + } + return FALSE; +} + +/** + * ismbbtrail() \x82̊g\x92\xA3 + */ +int __ismbbtrail(BYTE b, int code_page) +{ + switch (code_page) { + case 932: + if (((0x40 <= b) && (b <= 0x7E)) || ((0x80 <= b) && (b <= 0xFC))) { + return TRUE; + } + return FALSE; + case 51949: + // Korean CP51949 + if ((0xA1 <= b) && (b <= 0xFE)) { + return TRUE; + } + return FALSE; + case 936: + // CP936 GB2312 + if ((0xA1 <= b) && (b <= 0xFE)) { + return TRUE; + } + return FALSE; + case 950: + // CP950 Big5 + if (((0x40 <= b) && (b <= 0x7e)) || ((0xa1 <= b) && (b <= 0xfe))) { + return TRUE; + } + return FALSE; + default: + break; + } + return 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) { BOOL Check; -#if UNICODE_INTERNAL_BUFF - if (ts.CodePage != 932) { - // TODO \x82\xBF\x82\xE1\x82\xF1\x82ƃ`\x83F\x83b\x83N\x82\xB7\x82\xE9 - // IsDBCSLeadByteEx() \x82\xAA\x91Ó\x96? - if (ts.CodePage == 936) { - // chs - return ((0x81 <= b) && (b <= 0xfe)); - } - if (ts.CodePage == 950) { - // cht - return ((0x88 <= b) && (b <= 0xfe)); - } - - } -#endif if (ts.Language!=IdJapanese) return FALSE; @@ -5449,24 +5548,6 @@ return Check; } -BOOL CheckKorean(BYTE b) -{ - BOOL Check; - if (ts.Language!=IdKorean) - return FALSE; - - if (ts.KanjiCode == IdSJIS) { - if ((0xA1<=b) && (b<=0xFE)) { - Check = TRUE; - } - else { - Check = FALSE; - } - } - - return Check; -} - static BOOL ParseFirstJP(BYTE b) // returns TRUE if b is processed // (actually allways returns TRUE) @@ -5617,7 +5698,7 @@ return TRUE; } -BOOL ParseFirstKR(BYTE b) +static BOOL ParseFirstKR(BYTE b) // returns TRUE if b is processed // (actually allways returns TRUE) { @@ -5640,7 +5721,7 @@ } } - if ((!KanjiIn) && CheckKorean(b)) { + if ((!KanjiIn) && CheckFirstByte(b, ts.Language, ts.KanjiCode)) { Kanji = b << 8; KanjiIn = TRUE; return TRUE; @@ -5680,6 +5761,69 @@ 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 !UNICODE_INTERNAL_BUFF @@ -6099,7 +6243,7 @@ return FALSE; } -void ParseFirst(BYTE b) +static void ParseFirst(BYTE b) { switch (ts.Language) { case IdUtf8: @@ -6144,12 +6288,17 @@ } break; - case IdRussian: if (ParseFirstRus(b)) { return; } break; + + case IdChinese: + if (ParseFirstCn(b)) { + return; + } + break; } if (SSflag) { Modified: trunk/teraterm/ttpdlg/ttdlg.c =================================================================== --- trunk/teraterm/ttpdlg/ttdlg.c 2020-05-06 14:51:43 UTC (rev 8765) +++ trunk/teraterm/ttpdlg/ttdlg.c 2020-05-06 14:52:04 UTC (rev 8766) @@ -122,6 +122,45 @@ "14400","19200","38400","57600","115200", "230400", "460800", "921600", NULL}; +// convert table for KanjiCodeID and ListID +// cf. KanjiList,KanjiListSend +// KoreanList,KoreanListSend +// Utf8List,Utf8ListSend +// IdSJIS, IdEUC, IdJIS, IdUTF8, IdUTF8m +// IdEnglish, IdJapanese, IdRussian, IdKorean, IdUtf8 +/* KanjiCode2List(Language,KanjiCodeID) returns ListID */ +static int KanjiCode2List(int lang, int kcode) +{ + int Table[5][5] = { + {1, 2, 3, 4, 5}, /* English (dummy) */ + {1, 2, 3, 4, 5}, /* Japanese(dummy) */ + {1, 2, 3, 4, 5}, /* Russian (dummy) */ + {1, 1, 1, 2, 3}, /* Korean */ + {1, 1, 1, 1, 2}, /* Utf8 */ + }; + lang--; + kcode--; + return Table[lang][kcode]; +} + +/* List2KanjiCode(Language,ListID) returns KanjiCodeID */ +static int List2KanjiCode(int lang, int list) +{ + int Table[5][5] = { + {1, 2, 3, 4, 5}, /* English (dummy) */ + {1, 2, 3, 4, 5}, /* Japanese(dummy) */ + {1, 2, 3, 4, 5}, /* Russian (dummy) */ + {1, 4, 5, 1, 1}, /* Korean */ + {4, 5, 4, 4, 4}, /* Utf8 */ + }; + lang--; + list--; + if (list < 0) { + list = 0; + } + return Table[lang][list]; +} + /* * COM\x83|\x81[\x83g\x82Ɋւ\xB7\x82\xE9\x8Fڍ\xEE\x95\xF1 */ Modified: trunk/teraterm/ttpset/ttset.c =================================================================== --- trunk/teraterm/ttpset/ttset.c 2020-05-06 14:51:43 UTC (rev 8765) +++ trunk/teraterm/ttpset/ttset.c 2020-05-06 14:52:04 UTC (rev 8766) @@ -2241,6 +2241,9 @@ ReadFont3("Tera Term", "DlgFont", NULL, FName, ts->DialogFontName, sizeof(ts->DialogFontName), &ts->DialogFontPoint, &ts->DialogFontCharSet); + + // Unicode\x90ݒ\xE8 + ts->UnicodeAmbiguousAsWide = GetOnOff(Section, "UnicodeAmbiguousWide", FName, TRUE); } void PASCAL WriteIniFile(PCHAR FName, PTTSet ts) @@ -3563,6 +3566,9 @@ ts->DialogFontPoint, ts->DialogFontCharSet); WritePrivateProfileStringA("Tera Term", "DlgFont", Temp, FName); + + // Unicode\x90ݒ\xE8 + WriteOnOff(Section, "UnicodeAmbiguousWide", FName, ts->UnicodeAmbiguousAsWide); } #define VTEditor "VT editor keypad"