OSDN Git Service

Add support for UTF-8 HFS+ filenames (Windows Vista or later only).
authors_kawamoto <s_kawamoto@users.sourceforge.jp>
Sat, 19 Oct 2013 16:21:40 +0000 (01:21 +0900)
committers_kawamoto <s_kawamoto@users.sourceforge.jp>
Sat, 19 Oct 2013 16:21:40 +0000 (01:21 +0900)
15 files changed:
FFFTP_Eng_Release/FFFTP.exe
Release/FFFTP.exe
Resource/FFFTP.rc
Resource/resource.h
Resource_eng/FFFTP-eng.rc
Resource_eng/resource.h
codecnv.c
common.h
connect.c
filelist.c
hostman.c
main.c
mbswrapper.c
mbswrapper.h
remote.c

index 29c7572..b95bfd7 100644 (file)
Binary files a/FFFTP_Eng_Release/FFFTP.exe and b/FFFTP_Eng_Release/FFFTP.exe differ
index 3c92c4e..0e65401 100644 (file)
Binary files a/Release/FFFTP.exe and b/Release/FFFTP.exe differ
index 9f051a2..ce30f88 100644 (file)
@@ -750,15 +750,16 @@ BEGIN
     CONTROL         "UTF-8",HSET_UTF8N_CNV,"Button",BS_AUTORADIOBUTTON,12,69,41,10\r
     CONTROL         "UTF-8 BOM",HSET_UTF8BOM_CNV,"Button",BS_AUTORADIOBUTTON,12,81,81,10\r
     CONTROL         "\94¼\8ap\83J\83i\82ð\91S\8ap\82É\95Ï\8a·",HSET_HANCNV,"Button",BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,12,98,87,10\r
-    GROUPBOX        "\83t\83@\83C\83\8b\96¼\82Ì\8a¿\8e\9a\83R\81[\83h(&N)",-1,110,7,90,115,WS_GROUP\r
+    GROUPBOX        "\83t\83@\83C\83\8b\96¼\82Ì\8a¿\8e\9a\83R\81[\83h(&N)",-1,110,7,90,127,WS_GROUP\r
     CONTROL         "\8e©\93®",HSET_FN_AUTO_CNV,"Button",BS_AUTORADIOBUTTON | WS_GROUP,114,21,65,10\r
-    CONTROL         "Shift_JIS",HSET_FN_SJIS_CNV,"Button",BS_AUTORADIOBUTTON,114,33,65,10\r
-    CONTROL         "JIS",HSET_FN_JIS_CNV,"Button",BS_AUTORADIOBUTTON,114,45,70,10\r
-    CONTROL         "EUC",HSET_FN_EUC_CNV,"Button",BS_AUTORADIOBUTTON,114,57,41,10\r
-    CONTROL         "Samba-HEX",HSET_FN_SMH_CNV,"Button",BS_AUTORADIOBUTTON,114,69,66,10\r
-    CONTROL         "Samba-CAP",HSET_FN_SMC_CNV,"Button",BS_AUTORADIOBUTTON,114,81,64,10\r
-    CONTROL         "UTF-8",HSET_FN_UTF8N_CNV,"Button",BS_AUTORADIOBUTTON,114,93,41,10\r
-    CONTROL         "\94¼\8ap\83J\83i\82ð\91S\8ap\82É\95Ï\8a·",HSET_FN_HANCNV,"Button",BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,114,107,81,10\r
+    CONTROL         "Shift_JIS",HSET_FN_SJIS_CNV,"Button",BS_AUTORADIOBUTTON,114,33,81,10\r
+    CONTROL         "JIS",HSET_FN_JIS_CNV,"Button",BS_AUTORADIOBUTTON,114,45,81,10\r
+    CONTROL         "EUC",HSET_FN_EUC_CNV,"Button",BS_AUTORADIOBUTTON,114,57,81,10\r
+    CONTROL         "Samba-HEX",HSET_FN_SMH_CNV,"Button",BS_AUTORADIOBUTTON,114,69,81,10\r
+    CONTROL         "Samba-CAP",HSET_FN_SMC_CNV,"Button",BS_AUTORADIOBUTTON,114,81,81,10\r
+    CONTROL         "UTF-8",HSET_FN_UTF8N_CNV,"Button",BS_AUTORADIOBUTTON,114,93,81,10\r
+    CONTROL         "UTF-8 HFS+",HSET_FN_UTF8HFSX_CNV,"Button",BS_AUTORADIOBUTTON,114,105,81,10\r
+    CONTROL         "\94¼\8ap\83J\83i\82ð\91S\8ap\82É\95Ï\8a·",HSET_FN_HANCNV,"Button",BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,114,119,81,10\r
 END\r
 \r
 opt_trmode1_dlg DIALOG  0, 0, 211, 155\r
index cd8e9bf..bcafa9f 100644 (file)
 #define TRMODE4_UTF8N_CNV               1218\r
 #define TRMODE4_UTF8BOM_CNV             1219\r
 #define HSET_ERROR_RECONNECT            1220\r
+#define HSET_FN_UTF8HFSX_CNV            1221\r
 #define MENU_END                        40001\r
 #define MENU_EXIT                       40001\r
 #define MENU_CONNECT                    40003\r
index 354d7f2..58345e7 100644 (file)
@@ -758,15 +758,16 @@ BEGIN
     CONTROL         "UTF-8",HSET_UTF8N_CNV,"Button",BS_AUTORADIOBUTTON,12,69,41,10\r
     CONTROL         "UTF-8 BOM",HSET_UTF8BOM_CNV,"Button",BS_AUTORADIOBUTTON,12,81,81,10\r
     CONTROL         "Hankaku to Zenkaku",HSET_HANCNV,"Button",BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,12,98,90,10\r
-    GROUPBOX        "&Filename Kanji Code",-1,107,7,97,116,WS_GROUP\r
+    GROUPBOX        "&Filename Kanji Code",-1,107,7,97,127,WS_GROUP\r
     CONTROL         "Automatic",HSET_FN_AUTO_CNV,"Button",BS_AUTORADIOBUTTON | WS_GROUP,111,21,65,10\r
-    CONTROL         "Shift_JIS",HSET_FN_SJIS_CNV,"Button",BS_AUTORADIOBUTTON,111,33,65,10\r
-    CONTROL         "JIS",HSET_FN_JIS_CNV,"Button",BS_AUTORADIOBUTTON,111,45,70,10\r
-    CONTROL         "EUC",HSET_FN_EUC_CNV,"Button",BS_AUTORADIOBUTTON,111,57,41,10\r
-    CONTROL         "Samba-HEX",HSET_FN_SMH_CNV,"Button",BS_AUTORADIOBUTTON,111,69,66,10\r
-    CONTROL         "Samba-CAP",HSET_FN_SMC_CNV,"Button",BS_AUTORADIOBUTTON,111,81,64,10\r
-    CONTROL         "UTF-8",HSET_FN_UTF8N_CNV,"Button",BS_AUTORADIOBUTTON,111,93,63,10\r
-    CONTROL         "Hankaku to Zenkaku",HSET_FN_HANCNV,"Button",BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,111,108,91,10\r
+    CONTROL         "Shift_JIS",HSET_FN_SJIS_CNV,"Button",BS_AUTORADIOBUTTON,111,33,81,10\r
+    CONTROL         "JIS",HSET_FN_JIS_CNV,"Button",BS_AUTORADIOBUTTON,111,45,81,10\r
+    CONTROL         "EUC",HSET_FN_EUC_CNV,"Button",BS_AUTORADIOBUTTON,111,57,81,10\r
+    CONTROL         "Samba-HEX",HSET_FN_SMH_CNV,"Button",BS_AUTORADIOBUTTON,111,69,81,10\r
+    CONTROL         "Samba-CAP",HSET_FN_SMC_CNV,"Button",BS_AUTORADIOBUTTON,111,81,81,10\r
+    CONTROL         "UTF-8",HSET_FN_UTF8N_CNV,"Button",BS_AUTORADIOBUTTON,111,93,81,10\r
+    CONTROL         "UTF-8 HFS+",HSET_FN_UTF8HFSX_CNV,"Button",BS_AUTORADIOBUTTON,111,105,81,10\r
+    CONTROL         "Hankaku to Zenkaku",HSET_FN_HANCNV,"Button",BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,111,119,81,10\r
 END\r
 \r
 opt_trmode1_dlg DIALOG  0, 0, 211, 155\r
index 8b87426..4b9a5b0 100644 (file)
 #define TRMODE4_UTF8N_CNV               1218\r
 #define TRMODE4_UTF8BOM_CNV             1219\r
 #define HSET_ERROR_RECONNECT            1220\r
+#define HSET_FN_UTF8HFSX_CNV            1221\r
 #define MENU_END                        40001\r
 #define MENU_EXIT                       40001\r
 #define MENU_CONNECT                    40003\r
index f9a9e37..6d7011a 100644 (file)
--- a/codecnv.c
+++ b/codecnv.c
@@ -36,6 +36,8 @@
 #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
@@ -61,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
@@ -1844,6 +1859,242 @@ 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
+       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
+       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
@@ -1873,3 +2124,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
index 18f94ef..102fd57 100644 (file)
--- a/common.h
+++ b/common.h
@@ -746,6 +746,8 @@ LIST_UNIX_70
 #define KANJI_UTF8N            5               /* UTF-8 */\r
 // UTF-8対応\r
 #define KANJI_UTF8BOM          6               /* UTF-8 BOM */\r
+// UTF-8 HFS+対応\r
+#define KANJI_UTF8HFSX         7               /* UTF-8 HFS+ */\r
 \r
 #define KANJI_NOCNV            -1              /* 漢字コード変換なし */\r
 \r
@@ -1735,8 +1737,15 @@ int ConvSJIStoJIS(CODECONVINFO *cInfo);
 int ConvSJIStoSMB_HEX(CODECONVINFO *cInfo);\r
 int ConvSJIStoSMB_CAP(CODECONVINFO *cInfo);\r
 int ConvSJIStoUTF8N(CODECONVINFO *cInfo); // UTF-8対応\r
+// UTF-8 HFS+対応\r
+int ConvUTF8NtoUTF8HFSX(CODECONVINFO *cInfo);\r
+int ConvUTF8HFSXtoUTF8N(CODECONVINFO *cInfo);\r
 void ConvAutoToSJIS(char *Text, int Pref);\r
 int CheckKanjiCode(char *Text, int Size, int Pref);\r
+// UTF-8対応\r
+int LoadUnicodeNormalizationDll();\r
+void FreeUnicodeNormalizationDll();\r
+int IsUnicodeNormalizationDllLoaded();\r
 \r
 /*===== option.c =====*/\r
 \r
index 434f0a4..08fbda1 100644 (file)
--- a/connect.c
+++ b/connect.c
@@ -1865,8 +1865,10 @@ static SOCKET DoConnectCrypt(int CryptMode, HOSTDATA* HostData, char *Host, char
                        // UTF-8対応\r
                        if(HostData->CurNameKanjiCode == KANJI_AUTO && (HostData->Feature & FEATURE_UTF8))\r
                        {\r
-                               if((Sts = command(ContSock, Reply, CancelCheckWork, "OPTS UTF8 ON")) == 200)\r
-                                       HostData->CurNameKanjiCode = KANJI_UTF8N;\r
+                               // UTF-8を指定した場合も自動判別を行う\r
+//                             if((Sts = command(ContSock, Reply, CancelCheckWork, "OPTS UTF8 ON")) == 200)\r
+//                                     HostData->CurNameKanjiCode = KANJI_UTF8N;\r
+                               command(ContSock, Reply, CancelCheckWork, "OPTS UTF8 ON");\r
                        }\r
                }\r
        }\r
index a7d493f..0cb190b 100755 (executable)
@@ -6144,7 +6144,7 @@ static int atoi_n(const char *Str, int Len)
 \r
 // UTF-8対応\r
 // ファイル一覧から漢字コードを推測\r
-// 優先度はUTF-8、Shift_JIS、EUC、JISの順\r
+// å\84ªå\85\88度ã\81¯UTF-8ã\80\81Shift_JISã\80\81EUCã\80\81JISã\80\81UTF-8 HFS+ã\81®é \86\r
 int AnalyzeNameKanjiCode(int Num)\r
 {\r
        char Str[FMAX_PATH+1];\r
@@ -6164,7 +6164,11 @@ int AnalyzeNameKanjiCode(int Num)
        int PointJIS;\r
        int PointEUC;\r
        int PointUTF8N;\r
+       int PointUTF8HFSX;\r
        char* p;\r
+       CODECONVINFO cInfo1;\r
+       CODECONVINFO cInfo2;\r
+       char Buf[FMAX_PATH+1];\r
 \r
        NameKanjiCode = KANJI_AUTO;\r
        Point = 0;\r
@@ -6172,6 +6176,7 @@ int AnalyzeNameKanjiCode(int Num)
        PointJIS = 0;\r
        PointEUC = 0;\r
        PointUTF8N = 0;\r
+       PointUTF8HFSX = 0;\r
        MakeCacheFileName(Num, Str);\r
        if((fd = fopen(Str, "rb")) != NULL)\r
        {\r
@@ -6194,7 +6199,25 @@ int AnalyzeNameKanjiCode(int Num)
                                if(!p)\r
                                {\r
                                        if(!CheckStringM(Name))\r
-                                               PointUTF8N++;\r
+                                       {\r
+                                               InitCodeConvInfo(&cInfo1);\r
+                                               cInfo1.KanaCnv = NO;\r
+                                               cInfo1.Str = Name;\r
+                                               cInfo1.StrLen = strlen(Name);\r
+                                               cInfo1.Buf = Buf;\r
+                                               cInfo1.BufSize = FMAX_PATH;\r
+                                               cInfo2 = cInfo1;\r
+                                               ConvUTF8NtoUTF8HFSX(&cInfo1);\r
+                                               ConvUTF8HFSXtoUTF8N(&cInfo2);\r
+                                               if(cInfo1.OutLen > strlen(Name))\r
+                                                       PointUTF8N++;\r
+                                               else\r
+                                                       PointUTF8HFSX++;\r
+                                               if(cInfo2.OutLen < strlen(Name))\r
+                                                       PointUTF8HFSX++;\r
+                                               else\r
+                                                       PointUTF8N++;\r
+                                       }\r
                                        else\r
                                        {\r
                                                switch(CheckKanjiCode(Name, strlen(Name), KANJI_SJIS))\r
@@ -6215,6 +6238,11 @@ int AnalyzeNameKanjiCode(int Num)
                }\r
                fclose(fd);\r
        }\r
+       if(PointUTF8HFSX >= Point)\r
+       {\r
+               NameKanjiCode = KANJI_UTF8HFSX;\r
+               Point = PointUTF8HFSX;\r
+       }\r
        if(PointJIS >= Point)\r
        {\r
                NameKanjiCode = KANJI_JIS;\r
index 31cfff1..88b58ec 100644 (file)
--- a/hostman.c
+++ b/hostman.c
@@ -1938,7 +1938,10 @@ static INT_PTR CALLBACK CodeSettingProc(HWND hDlg, UINT iMessage, WPARAM wParam,
                { HSET_FN_EUC_CNV, KANJI_EUC },\r
                { HSET_FN_SMH_CNV, KANJI_SMB_HEX },\r
                { HSET_FN_SMC_CNV, KANJI_SMB_CAP },\r
-               { HSET_FN_UTF8N_CNV, KANJI_UTF8N }              // UTF-8対応\r
+               // UTF-8 HFS+対応\r
+//             { HSET_FN_UTF8N_CNV, KANJI_UTF8N }              // UTF-8対応\r
+               { HSET_FN_UTF8N_CNV, KANJI_UTF8N },             // UTF-8対応\r
+               { HSET_FN_UTF8HFSX_CNV, KANJI_UTF8HFSX }\r
        };\r
        #define NAMEKANJIBUTTONS        (sizeof(NameKanjiButton)/sizeof(RADIOBUTTON))\r
 \r
@@ -1998,6 +2001,8 @@ static INT_PTR CALLBACK CodeSettingProc(HWND hDlg, UINT iMessage, WPARAM wParam,
                                case HSET_FN_SMH_CNV :\r
                                case HSET_FN_SMC_CNV :\r
                                case HSET_FN_UTF8N_CNV :        // UTF-8対応\r
+                               // UTF-8 HFS+対応\r
+                               case HSET_FN_UTF8HFSX_CNV :\r
                                        EnableWindow(GetDlgItem(hDlg, HSET_FN_HANCNV), FALSE);\r
                                        break;\r
                        }\r
diff --git a/main.c b/main.c
index 9e80f91..bb00b91 100644 (file)
--- a/main.c
+++ b/main.c
@@ -372,6 +372,9 @@ int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLi
        CoInitialize(NULL);\r
        LoadUPnP();\r
 \r
+       // UTF-8対応\r
+       LoadUnicodeNormalizationDll();\r
+\r
        // FTPS対応\r
 #ifdef USE_OPENSSL\r
        LoadOpenSSL();\r
index fa04fee..e4dc6d0 100644 (file)
@@ -578,6 +578,48 @@ int PutNextCharW(LPWSTR lpString, LPWSTR pLimit, LPWSTR* ppNext, DWORD Code)
        return Count;\r
 }\r
 \r
+// マルチバイト文字列のコードポイントの個数を取得\r
+int GetCodeCountM(LPCSTR lpString, int CharCount)\r
+{\r
+       int Count;\r
+       LPCSTR pLimit;\r
+       DWORD Code;\r
+       Count = 0;\r
+       if(CharCount == -1)\r
+               pLimit = lpString + strlen(lpString);\r
+       else\r
+               pLimit = lpString + CharCount;\r
+       while(lpString < pLimit)\r
+       {\r
+               Code = GetNextCharM(lpString, pLimit, &lpString);\r
+               if(Code == 0x80000000)\r
+                       continue;\r
+               Count++;\r
+       }\r
+       return Count;\r
+}\r
+\r
+// ワイド文字列のコードポイントの個数を取得\r
+int GetCodeCountW(LPCWSTR lpString, int CharCount)\r
+{\r
+       int Count;\r
+       LPCWSTR pLimit;\r
+       DWORD Code;\r
+       Count = 0;\r
+       if(CharCount == -1)\r
+               pLimit = lpString + wcslen(lpString);\r
+       else\r
+               pLimit = lpString + CharCount;\r
+       while(lpString < pLimit)\r
+       {\r
+               Code = GetNextCharW(lpString, pLimit, &lpString);\r
+               if(Code == 0x80000000)\r
+                       continue;\r
+               Count++;\r
+       }\r
+       return Count;\r
+}\r
+\r
 // マルチバイト文字列の冗長表現を修正\r
 // 修正があればTRUEを返す\r
 // 修正後の文字列の長さは元の文字列の長さ以下のためpDstとpSrcに同じ値を指定可能\r
index 14fe3a5..e6d3e15 100644 (file)
@@ -282,6 +282,8 @@ DWORD GetNextCharM(LPCSTR lpString, LPCSTR pLimit, LPCSTR* ppNext);
 int PutNextCharM(LPSTR lpString, LPSTR pLimit, LPSTR* ppNext, DWORD Code);\r
 DWORD GetNextCharW(LPCWSTR lpString, LPCWSTR pLimit, LPCWSTR* ppNext);\r
 int PutNextCharW(LPWSTR lpString, LPWSTR pLimit, LPWSTR* ppNext, DWORD Code);\r
+int GetCodeCountM(LPCSTR lpString, int CharCount);\r
+int GetCodeCountW(LPCWSTR lpString, int CharCount);\r
 BOOL FixStringM(LPSTR pDst, LPCSTR pSrc);\r
 BOOL FixMultiStringM(LPSTR pDst, LPCSTR pSrc);\r
 BOOL CheckStringM(LPCSTR lpString);\r
index bb8bc46..486c1d3 100644 (file)
--- a/remote.c
+++ b/remote.c
@@ -1655,6 +1655,20 @@ int ChangeFnameRemote2Local(char *Fname, int Max)
 //                             *(Buf + cInfo.OutLen) = NUL;\r
 //                             strcpy(Pos, Buf);\r
 //                             break;\r
+\r
+                       // UTF-8 HFS+対応\r
+                       case KANJI_UTF8HFSX :\r
+                               if(IsUnicodeNormalizationDllLoaded())\r
+                               {\r
+                                       ConvUTF8HFSXtoUTF8N(&cInfo);\r
+                                       *(Buf + cInfo.OutLen) = NUL;\r
+                                       strcpy(Fname, Buf);\r
+                                       Pos = strchr(Fname, NUL);\r
+                                       FlushRestData(&cInfo);\r
+                                       *(Buf + cInfo.OutLen) = NUL;\r
+                                       strcpy(Pos, Buf);\r
+                               }\r
+                               break;\r
                }\r
                // バッファ上書きバグ対策\r
                free(Buf2);\r
@@ -1823,6 +1837,20 @@ int ChangeFnameLocal2Remote(char *Fname, int Max)
 //                             *(Buf + cInfo.OutLen) = NUL;\r
 //                             strcpy(Pos, Buf);\r
 //                             break;\r
+\r
+                       // UTF-8 HFS+対応\r
+                       case KANJI_UTF8HFSX :\r
+                               if(IsUnicodeNormalizationDllLoaded())\r
+                               {\r
+                                       ConvUTF8NtoUTF8HFSX(&cInfo);\r
+                                       *(Buf + cInfo.OutLen) = NUL;\r
+                                       strcpy(Fname, Buf);\r
+                                       Pos = strchr(Fname, NUL);\r
+                                       FlushRestData(&cInfo);\r
+                                       *(Buf + cInfo.OutLen) = NUL;\r
+                                       strcpy(Pos, Buf);\r
+                               }\r
+                               break;\r
                }\r
                // バッファ上書きバグ対策\r
                free(Buf2);\r