OSDN Git Service

Update to b2ca3cbfefb9f644d74e81b6dbb28c759def7249 (1.99a-20171104).
[ffftp/ffftp.git] / codecnv.c
index 2ac55e7..078b605 100644 (file)
--- a/codecnv.c
+++ b/codecnv.c
 #include <stdio.h>\r
 #include <stdlib.h>\r
 #include <string.h>\r
-#include <winsock.h>\r
+// IPv6対応\r
+//#include <winsock.h>\r
+#include <winsock2.h>\r
 #include <mbstring.h>\r
 #include <windowsx.h>\r
+// UTF-8対応\r
+#include <winnls.h>\r
 \r
 #include "common.h"\r
 #include "resource.h"\r
@@ -59,6 +63,19 @@ static int CheckOnEUC(uchar *Pos, uchar *Btm);
 static int ConvertIBMExtendedChar(int code);\r
 \r
 \r
+typedef enum _NORM_FORM\r
+{\r
+       NormalizationOther = 0,\r
+       NormalizationC = 0x1,\r
+       NormalizationD = 0x2,\r
+       NormalizationKC = 0x5,\r
+       NormalizationKD = 0x6\r
+} NORM_FORM;\r
+\r
+typedef int (WINAPI* _NormalizeString)(NORM_FORM, LPCWSTR, int, LPWSTR, int);\r
+\r
+HMODULE hUnicodeNormalizationDll;\r
+_NormalizeString p_NormalizeString;\r
 \r
 #if 0\r
 /*----- 漢字コード変換のテストプログラム ------------------------------------*/\r
@@ -368,6 +385,8 @@ void InitCodeConvInfo(CODECONVINFO *cInfo)
        cInfo->KanaProc = NULL;\r
        // UTF-8対応\r
        cInfo->EscUTF8Len = 0;\r
+       cInfo->EscFlush = NO;\r
+       cInfo->FlushProc = NULL;\r
        return;\r
 }\r
 \r
@@ -388,6 +407,13 @@ int FlushRestData(CODECONVINFO *cInfo)
 {\r
        char *Put;\r
 \r
+       // UTF-8対応\r
+       if(cInfo->FlushProc != NULL)\r
+       {\r
+               cInfo->EscFlush = YES;\r
+               return cInfo->FlushProc(cInfo);\r
+       }\r
+\r
        Put = cInfo->Buf;\r
 \r
        if(cInfo->KanaProc != NULL)\r
@@ -399,9 +425,6 @@ int FlushRestData(CODECONVINFO *cInfo)
                *Put++ = cInfo->EscCode[0];\r
        if(cInfo->EscProc == 2)\r
                *Put++ = cInfo->EscCode[1];\r
-       // UTF-8対応\r
-       memcpy(Put, cInfo->EscUTF8, sizeof(char) * cInfo->EscUTF8Len);\r
-       Put += cInfo->EscUTF8Len;\r
 \r
        cInfo->OutLen = Put - cInfo->Buf;\r
 \r
@@ -409,6 +432,24 @@ int FlushRestData(CODECONVINFO *cInfo)
 }\r
 \r
 \r
+// UTF-8対応\r
+int ConvNoConv(CODECONVINFO *cInfo)\r
+{\r
+       int Continue;\r
+       Continue = NO;\r
+       if(cInfo->BufSize >= cInfo->StrLen)\r
+               cInfo->OutLen = cInfo->StrLen;\r
+       else\r
+       {\r
+               cInfo->OutLen = cInfo->BufSize;\r
+               Continue = YES;\r
+       }\r
+       memcpy(cInfo->Buf, cInfo->Str, sizeof(char) * cInfo->OutLen);\r
+       cInfo->Str += cInfo->OutLen;\r
+       cInfo->StrLen -= cInfo->OutLen;\r
+       return Continue;\r
+}\r
+\r
 /*----- EUC漢字コードをSHIFT-JIS漢字コードに変換 ------------------------------\r
 *\r
 *      Parameter\r
@@ -1102,7 +1143,7 @@ int ConvSJIStoSMB_HEX(CODECONVINFO *cInfo)
 \r
                if((cInfo->StrLen >= 2) &&\r
                   ((((uchar)*Str >= (uchar)0x81) && ((uchar)*Str <= (uchar)0x9F)) ||\r
-                   ((uchar)*Str >= (uchar)0xE0)))\r
+                       ((uchar)*Str >= (uchar)0xE0)))\r
                {\r
                        sprintf(Put, "%c%02x%c%02x", SAMBA_HEX_TAG, (uchar)*Str, SAMBA_HEX_TAG, (uchar)*(Str+1));\r
                        Str += 2;\r
@@ -1479,12 +1520,61 @@ static int CheckOnEUC(uchar *Pos, uchar *Btm)
 *              くり返しフラグがYESの時は、cInfoの内容を変えずにもう一度呼ぶこと\r
 *----------------------------------------------------------------------------*/\r
 \r
+// UTF-8対応\r
+// UTF-8からShift_JISへの変換後のバイト列が確定可能な長さを変換後の長さで返す\r
+// バイナリ            UTF-8       戻り値 Shift_JIS\r
+// E3 81 82 E3 81 84   あい     -> 2      82 A0   あ+結合文字の先頭バイトの可能性(い゛等)\r
+// E3 81 82 E3 81      あ+E3 81 -> 0              結合文字の先頭バイトの可能性\r
+// E3 81 82 E3         あ+E3    -> 0              結合文字の先頭バイトの可能性\r
+// E3 81 82            あ       -> 0              結合文字の先頭バイトの可能性\r
+int ConvUTF8NtoSJIS_TruncateToDelimiter(char* pUTF8, int UTF8Length, int* pNewUTF8Length)\r
+{\r
+       int UTF16Length;\r
+       wchar_t* pUTF16;\r
+       int SJISLength;\r
+       int NewSJISLength;\r
+       int NewUTF16Length;\r
+       // UTF-8の場合、不完全な文字は常に変換されない\r
+       // バイナリ            UTF-8       バイナリ      UTF-16 LE\r
+       // E3 81 82 E3 81 84   あい     -> 42 30 44 30   あい\r
+       // E3 81 82 E3 81      あ+E3 81 -> 42 30         あ\r
+       // E3 81 82 E3         あ+E3    -> 42 30         あ\r
+       UTF16Length = MultiByteToWideChar(CP_UTF8, 0, pUTF8, UTF8Length, NULL, 0);\r
+       if(!(pUTF16 = (wchar_t*)malloc(sizeof(wchar_t) * UTF16Length)))\r
+               return -1;\r
+       // Shift_JISへ変換した時に文字数が増減する位置がUnicode結合文字の区切り\r
+       UTF16Length = MultiByteToWideChar(CP_UTF8, 0, pUTF8, UTF8Length, pUTF16, UTF16Length);\r
+       SJISLength = WideCharToMultiByte(CP_ACP, 0, pUTF16, UTF16Length, NULL, 0, NULL, NULL);\r
+       NewSJISLength = SJISLength;\r
+       while(UTF8Length > 0 && NewSJISLength >= SJISLength)\r
+       {\r
+               UTF8Length--;\r
+               UTF16Length = MultiByteToWideChar(CP_UTF8, 0, pUTF8, UTF8Length, pUTF16, UTF16Length);\r
+               NewSJISLength = WideCharToMultiByte(CP_ACP, 0, pUTF16, UTF16Length, NULL, 0, NULL, NULL);\r
+       }\r
+       free(pUTF16);\r
+       // UTF-16 LE変換した時に文字数が増減する位置がUTF-8の区切り\r
+       if(pNewUTF8Length)\r
+       {\r
+               NewUTF16Length = UTF16Length;\r
+               while(UTF8Length > 0 && NewUTF16Length >= UTF16Length)\r
+               {\r
+                       UTF8Length--;\r
+                       NewUTF16Length = MultiByteToWideChar(CP_UTF8, 0, pUTF8, UTF8Length, NULL, 0);\r
+               }\r
+               if(UTF16Length > 0)\r
+                       UTF8Length++;\r
+               *pNewUTF8Length = UTF8Length;\r
+       }\r
+       return NewSJISLength;\r
+}\r
+\r
 int ConvUTF8NtoSJIS(CODECONVINFO *cInfo)\r
 {\r
        int Continue;\r
 \r
 //     char temp_string[2048];\r
-       int string_length;\r
+//     int string_length;\r
 \r
        // 大きいサイズに対応\r
        // 終端のNULLを含むバグを修正\r
@@ -1492,7 +1582,6 @@ int ConvUTF8NtoSJIS(CODECONVINFO *cInfo)
        char* pSrc;\r
        wchar_t* pUTF16;\r
        int UTF16Length;\r
-       int Count;\r
 \r
        Continue = NO;\r
 \r
@@ -1516,7 +1605,14 @@ int ConvUTF8NtoSJIS(CODECONVINFO *cInfo)
        memcpy(pSrc, cInfo->EscUTF8, sizeof(char) * cInfo->EscUTF8Len);\r
        memcpy(pSrc + cInfo->EscUTF8Len, cInfo->Str, sizeof(char) * cInfo->StrLen);\r
        *(pSrc + SrcLength) = '\0';\r
-       // UTF-8の場合、不完全な文字は常に変換されない\r
+       if(cInfo->EscFlush == NO)\r
+       {\r
+               // バッファに収まらないため変換文字数を半減\r
+               while(SrcLength > 0 && ConvUTF8NtoSJIS_TruncateToDelimiter(pSrc, SrcLength, &SrcLength) > cInfo->BufSize)\r
+               {\r
+                       SrcLength = SrcLength / 2;\r
+               }\r
+       }\r
        UTF16Length = MultiByteToWideChar(CP_UTF8, 0, pSrc, SrcLength, NULL, 0);\r
 \r
        // サイズ0 or バッファサイズより大きい場合は\r
@@ -1557,7 +1653,6 @@ int ConvUTF8NtoSJIS(CODECONVINFO *cInfo)
 //                                             0,                              // 格納先サイズ\r
 //                                             NULL,NULL\r
 //                                     );\r
-       string_length = WideCharToMultiByte(CP_ACP, 0, pUTF16, UTF16Length, NULL, 0, NULL, NULL);\r
 \r
        // サイズ0 or 出力バッファサイズより大きい場合は、\r
        // cInfo->Bufの最初に'\0'を入れて、\r
@@ -1583,20 +1678,10 @@ int ConvUTF8NtoSJIS(CODECONVINFO *cInfo)
 //             NULL,NULL\r
 //     );\r
        cInfo->OutLen = WideCharToMultiByte(CP_ACP, 0, pUTF16, UTF16Length, cInfo->Buf, cInfo->BufSize, NULL, NULL);\r
-       // バッファに収まらないため変換文字数を半減\r
-       while(cInfo->OutLen == 0 && UTF16Length > 0)\r
-       {\r
-               UTF16Length = UTF16Length / 2;\r
-               cInfo->OutLen = WideCharToMultiByte(CP_ACP, 0, pUTF16, UTF16Length, cInfo->Buf, cInfo->BufSize, NULL, NULL);\r
-       }\r
-       // 変換された元の文字列での文字数を取得\r
-       Count = WideCharToMultiByte(CP_UTF8, 0, pUTF16, UTF16Length, NULL, 0, NULL, NULL);\r
-       // 変換可能な残りの文字数を取得\r
-       UTF16Length = MultiByteToWideChar(CP_UTF8, 0, pSrc + Count, SrcLength - Count, NULL, 0);\r
-       cInfo->Str += Count - cInfo->EscUTF8Len;\r
-       cInfo->StrLen -= Count - cInfo->EscUTF8Len;\r
+       cInfo->Str += SrcLength - cInfo->EscUTF8Len;\r
+       cInfo->StrLen -= SrcLength - cInfo->EscUTF8Len;\r
        cInfo->EscUTF8Len = 0;\r
-       if(UTF16Length > 0)\r
+       if(ConvUTF8NtoSJIS_TruncateToDelimiter(cInfo->Str, cInfo->StrLen, NULL) > 0)\r
                Continue = YES;\r
        else\r
        {\r
@@ -1605,6 +1690,7 @@ int ConvUTF8NtoSJIS(CODECONVINFO *cInfo)
                cInfo->EscUTF8Len = cInfo->StrLen;\r
                cInfo->Str += cInfo->StrLen;\r
                cInfo->StrLen = 0;\r
+               cInfo->FlushProc = ConvUTF8NtoSJIS;\r
                Continue = NO;\r
        }\r
 \r
@@ -1662,25 +1748,28 @@ int ConvSJIStoUTF8N(CODECONVINFO *cInfo)
        memcpy(pSrc, cInfo->EscUTF8, sizeof(char) * cInfo->EscUTF8Len);\r
        memcpy(pSrc + cInfo->EscUTF8Len, cInfo->Str, sizeof(char) * cInfo->StrLen);\r
        *(pSrc + SrcLength) = '\0';\r
-       // Shift_JISの場合、不完全な文字でも変換されることがあるため、末尾の不完全な部分を削る\r
-       Count = 0;\r
-       while(Count < SrcLength)\r
+       if(cInfo->EscFlush == NO)\r
        {\r
-               if(((unsigned char)*(pSrc + Count) >= 0x81 && (unsigned char)*(pSrc + Count) <= 0x9f) || (unsigned char)*(pSrc + Count) >= 0xe0)\r
+               // Shift_JISの場合、不完全な文字でも変換されることがあるため、末尾の不完全な部分を削る\r
+               Count = 0;\r
+               while(Count < SrcLength)\r
                {\r
-                       if((unsigned char)*(pSrc + Count + 1) >= 0x40)\r
-                               Count += 2;\r
-                       else\r
+                       if(((unsigned char)*(pSrc + Count) >= 0x81 && (unsigned char)*(pSrc + Count) <= 0x9f) || (unsigned char)*(pSrc + Count) >= 0xe0)\r
                        {\r
-                               if(Count + 2 > SrcLength)\r
-                                       break;\r
-                               Count += 1;\r
+                               if((unsigned char)*(pSrc + Count + 1) >= 0x40)\r
+                                       Count += 2;\r
+                               else\r
+                               {\r
+                                       if(Count + 2 > SrcLength)\r
+                                               break;\r
+                                       Count += 1;\r
+                               }\r
                        }\r
+                       else\r
+                               Count += 1;\r
                }\r
-               else\r
-                       Count += 1;\r
+               SrcLength = Count;\r
        }\r
-       SrcLength = Count;\r
        UTF16Length = MultiByteToWideChar(CP_ACP, 0, pSrc, SrcLength, NULL, 0);\r
 \r
        // サイズ0 or バッファサイズより大きい場合は、\r
@@ -1777,6 +1866,7 @@ int ConvSJIStoUTF8N(CODECONVINFO *cInfo)
                cInfo->EscUTF8Len = cInfo->StrLen;\r
                cInfo->Str += cInfo->StrLen;\r
                cInfo->StrLen = 0;\r
+               cInfo->FlushProc = ConvSJIStoUTF8N;\r
                Continue = NO;\r
        }\r
 \r
@@ -1787,6 +1877,246 @@ int ConvSJIStoUTF8N(CODECONVINFO *cInfo)
 }\r
 // UTF-8対応 ここまで↑\r
 \r
+// UTF-8 HFS+対応\r
+int ConvUTF8NtoUTF8HFSX(CODECONVINFO *cInfo)\r
+{\r
+       int Continue;\r
+       int SrcLength;\r
+       char* pSrc;\r
+       char* pSrcCur;\r
+       char* pSrcEnd;\r
+       char* pSrcNext;\r
+       char* pDstCur;\r
+       char* pDstEnd;\r
+       DWORD Code;\r
+       int Count;\r
+       wchar_t Temp1[4];\r
+       wchar_t Temp2[4];\r
+       char Temp3[16];\r
+       char* Temp3Cur;\r
+       char* Temp3End;\r
+       int TempCount;\r
+       if(IsUnicodeNormalizationDllLoaded() == NO)\r
+               return ConvNoConv(cInfo);\r
+       Continue = NO;\r
+       SrcLength = cInfo->StrLen + cInfo->EscUTF8Len;\r
+       if(!(pSrc = (char*)malloc(sizeof(char) * (SrcLength + 1))))\r
+       {\r
+               *(cInfo->Buf) = '\0';\r
+               cInfo->BufSize = 0;\r
+               return Continue;\r
+       }\r
+       memcpy(pSrc, cInfo->EscUTF8, sizeof(char) * cInfo->EscUTF8Len);\r
+       memcpy(pSrc + cInfo->EscUTF8Len, cInfo->Str, sizeof(char) * cInfo->StrLen);\r
+       *(pSrc + SrcLength) = '\0';\r
+       cInfo->OutLen = 0;\r
+       pSrcCur = pSrc;\r
+       pSrcEnd = pSrc + SrcLength;\r
+       pSrcNext = pSrc;\r
+       pDstCur = cInfo->Buf;\r
+       pDstEnd = cInfo->Buf + cInfo->BufSize;\r
+       while(pSrcCur < pSrcEnd)\r
+       {\r
+               Code = GetNextCharM(pSrcCur, pSrcEnd, (LPCSTR*)&pSrcNext);\r
+               if(Code == 0x80000000)\r
+               {\r
+                       if(pSrcNext == pSrcEnd)\r
+                               // 入力の末尾が不完全\r
+                               break;\r
+               }\r
+               else if((Code >= 0x00002000 && Code <= 0x00002fff)\r
+                       || (Code >= 0x0000f900 && Code <= 0x0000faff)\r
+                       || (Code >= 0x0002f800 && Code <= 0x0002faff))\r
+               {\r
+                       // HFS+特有の例外\r
+                       Count = PutNextCharM(pDstCur, pDstEnd, &pDstCur, Code);\r
+                       if(Count > 0)\r
+                               cInfo->OutLen += Count;\r
+                       else\r
+                       {\r
+                               // 出力バッファが不足\r
+                               Continue = YES;\r
+                               break;\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       // Normalization Form Dに変換\r
+                       Count = MultiByteToWideChar(CP_UTF8, 0, pSrcCur, (int)(pSrcNext - pSrcCur), Temp1, 4);\r
+                       Count = p_NormalizeString(NormalizationD, Temp1, Count, Temp2, 4);\r
+                       Count = WideCharToMultiByte(CP_UTF8, 0, Temp2, Count, Temp3, 16, NULL, NULL);\r
+                       Temp3Cur = Temp3;\r
+                       Temp3End = Temp3 + Count;\r
+                       TempCount = 0;\r
+                       while(Temp3Cur < Temp3End)\r
+                       {\r
+                               Code = GetNextCharM(Temp3Cur, Temp3End, (LPCSTR*)&Temp3Cur);\r
+                               Count = PutNextCharM(pDstCur, pDstEnd, &pDstCur, Code);\r
+                               if(Count > 0)\r
+                                       TempCount += Count;\r
+                               else\r
+                               {\r
+                                       // 出力バッファが不足\r
+                                       Continue = YES;\r
+                                       break;\r
+                               }\r
+                       }\r
+                       cInfo->OutLen += TempCount;\r
+               }\r
+               pSrcCur = pSrcNext;\r
+       }\r
+       cInfo->Str += (int)(pSrcCur - pSrc) - cInfo->EscUTF8Len;\r
+       cInfo->StrLen -= (int)(pSrcCur - pSrc) - cInfo->EscUTF8Len;\r
+       cInfo->EscUTF8Len = 0;\r
+       free(pSrc);\r
+       if(Continue == NO)\r
+       {\r
+               memcpy(cInfo->EscUTF8, cInfo->Str, sizeof(char) * cInfo->StrLen);\r
+               cInfo->EscUTF8Len = cInfo->StrLen;\r
+               cInfo->Str += cInfo->StrLen;\r
+               cInfo->StrLen = 0;\r
+               cInfo->FlushProc = ConvUTF8NtoUTF8HFSX;\r
+       }\r
+       return YES;\r
+}\r
+\r
+// バグの可能性あり\r
+// 確認するまで複数個のバッファを用いた変換には用いないこと\r
+// UTF-8 Nomalization Form DからCへの変換後のバイト列が確定可能な長さを変換後のコードポイントの個数で返す\r
+// バイナリ            UTF-8       戻り値\r
+// E3 81 82 E3 81 84   あい     -> 1   あ+結合文字の先頭バイトの可能性(い゛等)\r
+// E3 81 82 E3 81      あ+E3 81 -> 0   結合文字の先頭バイトの可能性\r
+// E3 81 82 E3         あ+E3    -> 0   結合文字の先頭バイトの可能性\r
+// E3 81 82            あ       -> 0   結合文字の先頭バイトの可能性\r
+int ConvUTF8HFSXtoUTF8N_TruncateToDelimiter(char* pUTF8, int UTF8Length, int* pNewUTF8Length)\r
+{\r
+       int UTF16Length;\r
+       wchar_t* pUTF16;\r
+       int UTF16HFSXLength;\r
+       wchar_t* pUTF16HFSX;\r
+       int CodeCount;\r
+       int NewCodeCount;\r
+       int NewUTF16Length;\r
+       UTF16Length = MultiByteToWideChar(CP_UTF8, 0, pUTF8, UTF8Length, NULL, 0);\r
+       if(!(pUTF16 = (wchar_t*)malloc(sizeof(wchar_t) * UTF16Length)))\r
+               return -1;\r
+       UTF16Length = MultiByteToWideChar(CP_UTF8, 0, pUTF8, UTF8Length, pUTF16, UTF16Length);\r
+       UTF16HFSXLength = p_NormalizeString(NormalizationC, pUTF16, UTF16Length, NULL, 0);\r
+       if(!(pUTF16HFSX = (wchar_t*)malloc(sizeof(wchar_t) * UTF16HFSXLength)))\r
+       {\r
+               free(pUTF16);\r
+               return -1;\r
+       }\r
+       UTF16HFSXLength = p_NormalizeString(NormalizationC, pUTF16, UTF16Length, pUTF16HFSX, UTF16HFSXLength);\r
+       // 変換した時にコードポイントの個数が増減する位置がUnicode結合文字の区切り\r
+       CodeCount = GetCodeCountW(pUTF16HFSX, UTF16HFSXLength);\r
+       NewCodeCount = CodeCount;\r
+       while(UTF8Length > 0 && NewCodeCount >= CodeCount)\r
+       {\r
+               UTF8Length--;\r
+               UTF16Length = MultiByteToWideChar(CP_UTF8, 0, pUTF8, UTF8Length, pUTF16, UTF16Length);\r
+               UTF16HFSXLength = p_NormalizeString(NormalizationC, pUTF16, UTF16Length, pUTF16HFSX, UTF16HFSXLength);\r
+               NewCodeCount = GetCodeCountW(pUTF16HFSX, UTF16HFSXLength);\r
+       }\r
+       free(pUTF16);\r
+       free(pUTF16HFSX);\r
+       // UTF-16 LE変換した時に文字数が増減する位置がUTF-8の区切り\r
+       if(pNewUTF8Length)\r
+       {\r
+               NewUTF16Length = UTF16Length;\r
+               while(UTF8Length > 0 && NewUTF16Length >= UTF16Length)\r
+               {\r
+                       UTF8Length--;\r
+                       NewUTF16Length = MultiByteToWideChar(CP_UTF8, 0, pUTF8, UTF8Length, NULL, 0);\r
+               }\r
+               if(UTF16Length > 0)\r
+                       UTF8Length++;\r
+               *pNewUTF8Length = UTF8Length;\r
+       }\r
+       return NewCodeCount;\r
+}\r
+\r
+int ConvUTF8HFSXtoUTF8N(CODECONVINFO *cInfo)\r
+{\r
+       int Continue;\r
+       int SrcLength;\r
+       char* pSrc;\r
+       int UTF16Length;\r
+       wchar_t* pUTF16;\r
+       int UTF16HFSXLength;\r
+       wchar_t* pUTF16HFSX;\r
+       CODECONVINFO Temp;\r
+       int Count;\r
+       if(IsUnicodeNormalizationDllLoaded() == NO)\r
+               return ConvNoConv(cInfo);\r
+       Continue = NO;\r
+       // 前回の変換不能な残りの文字列を入力の先頭に結合\r
+       SrcLength = cInfo->StrLen + cInfo->EscUTF8Len;\r
+       if(!(pSrc = (char*)malloc(sizeof(char) * (SrcLength + 1))))\r
+       {\r
+               *(cInfo->Buf) = '\0';\r
+               cInfo->BufSize = 0;\r
+               return Continue;\r
+       }\r
+       memcpy(pSrc, cInfo->EscUTF8, sizeof(char) * cInfo->EscUTF8Len);\r
+       memcpy(pSrc + cInfo->EscUTF8Len, cInfo->Str, sizeof(char) * cInfo->StrLen);\r
+       *(pSrc + SrcLength) = '\0';\r
+       UTF16Length = MultiByteToWideChar(CP_UTF8, 0, pSrc, SrcLength, NULL, 0);\r
+       if(!(pUTF16 = (wchar_t*)malloc(sizeof(wchar_t) * UTF16Length)))\r
+       {\r
+               free(pSrc);\r
+               *(cInfo->Buf) = '\0';\r
+               cInfo->BufSize = 0;\r
+               return Continue;\r
+       }\r
+       MultiByteToWideChar(CP_UTF8, 0, pSrc, SrcLength, pUTF16, UTF16Length);\r
+       UTF16HFSXLength = p_NormalizeString(NormalizationC, pUTF16, UTF16Length, NULL, 0);\r
+       if(!(pUTF16HFSX = (wchar_t*)malloc(sizeof(wchar_t) * UTF16HFSXLength)))\r
+       {\r
+               free(pSrc);\r
+               free(pUTF16);\r
+               *(cInfo->Buf) = '\0';\r
+               cInfo->BufSize = 0;\r
+               return Continue;\r
+       }\r
+       UTF16HFSXLength = p_NormalizeString(NormalizationC, pUTF16, UTF16Length, pUTF16HFSX, UTF16HFSXLength);\r
+       cInfo->OutLen = WideCharToMultiByte(CP_UTF8, 0, pUTF16HFSX, UTF16HFSXLength, cInfo->Buf, cInfo->BufSize, NULL, NULL);\r
+       if(cInfo->OutLen == 0 && UTF16HFSXLength > 0)\r
+       {\r
+               // バッファに収まらないため変換文字数を半減\r
+               Temp = *cInfo;\r
+               Temp.StrLen = cInfo->StrLen / 2;\r
+               ConvUTF8HFSXtoUTF8N(&Temp);\r
+               cInfo->OutLen = Temp.OutLen;\r
+               Count = cInfo->StrLen / 2 + cInfo->EscUTF8Len - Temp.StrLen - Temp.EscUTF8Len;\r
+               cInfo->Str += Count - cInfo->EscUTF8Len;\r
+               cInfo->StrLen -= Count - cInfo->EscUTF8Len;\r
+               cInfo->EscUTF8Len = 0;\r
+       }\r
+       else\r
+       {\r
+               cInfo->Str += SrcLength - cInfo->EscUTF8Len;\r
+               cInfo->StrLen -= SrcLength - cInfo->EscUTF8Len;\r
+               cInfo->EscUTF8Len = 0;\r
+       }\r
+       if(ConvUTF8HFSXtoUTF8N_TruncateToDelimiter(cInfo->Str, cInfo->StrLen, NULL) > 0)\r
+               Continue = YES;\r
+       else\r
+       {\r
+               // 変換不能なため次の入力の先頭に結合\r
+               memcpy(cInfo->EscUTF8, cInfo->Str, sizeof(char) * cInfo->StrLen);\r
+               cInfo->EscUTF8Len = cInfo->StrLen;\r
+               cInfo->Str += cInfo->StrLen;\r
+               cInfo->StrLen = 0;\r
+               cInfo->FlushProc = ConvUTF8HFSXtoUTF8N;\r
+               Continue = NO;\r
+       }\r
+       free(pSrc);\r
+       free(pUTF16);\r
+       free(pUTF16HFSX);\r
+       return Continue;\r
+}\r
+\r
 \r
 /*----- IBM拡張漢字をNEC選定IBM拡張漢字等に変換 -------------------------------\r
 *\r
@@ -1816,3 +2146,45 @@ static int ConvertIBMExtendedChar(int code)
        return code;\r
 }\r
 \r
+// UTF-8対応\r
+int LoadUnicodeNormalizationDll()\r
+{\r
+       int Sts;\r
+       char CurDir[FMAX_PATH+1];\r
+       char SysDir[FMAX_PATH+1];\r
+       Sts = FFFTP_FAIL;\r
+       if(GetCurrentDirectory(FMAX_PATH, CurDir) > 0)\r
+       {\r
+               if(GetSystemDirectory(SysDir, FMAX_PATH) > 0)\r
+               {\r
+                       if(SetCurrentDirectory(SysDir))\r
+                       {\r
+                               if((hUnicodeNormalizationDll = LoadLibrary("normaliz.dll")) != NULL)\r
+                               {\r
+                                       if((p_NormalizeString = (_NormalizeString)GetProcAddress(hUnicodeNormalizationDll, "NormalizeString")) != NULL)\r
+                                               Sts = FFFTP_SUCCESS;\r
+                               }\r
+                               SetCurrentDirectory(CurDir);\r
+                       }\r
+               }\r
+       }\r
+       return Sts;\r
+}\r
+\r
+void FreeUnicodeNormalizationDll()\r
+{\r
+       if(hUnicodeNormalizationDll != NULL)\r
+               FreeLibrary(hUnicodeNormalizationDll);\r
+       hUnicodeNormalizationDll = NULL;\r
+       p_NormalizeString = NULL;\r
+}\r
+\r
+int IsUnicodeNormalizationDllLoaded()\r
+{\r
+       int Sts;\r
+       Sts = FFFTP_FAIL;\r
+       if(hUnicodeNormalizationDll != NULL && p_NormalizeString != NULL)\r
+               Sts = FFFTP_SUCCESS;\r
+       return Sts;\r
+}\r
+\r