• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
Keine Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

FFFTPのソースコードです。


Commit MetaInfo

Revisionf3bb77eff8ad09c3a64851ad1b2790823afe02f2 (tree)
Zeit2013-10-20 01:21:40
Autors_kawamoto <s_kawamoto@user...>
Commiters_kawamoto

Log Message

Add support for UTF-8 HFS+ filenames (Windows Vista or later only).

Ändern Zusammenfassung

Diff

Binary files a/FFFTP_Eng_Release/FFFTP.exe and b/FFFTP_Eng_Release/FFFTP.exe differ
Binary files a/Release/FFFTP.exe and b/Release/FFFTP.exe differ
--- a/Resource/FFFTP.rc
+++ b/Resource/FFFTP.rc
@@ -750,15 +750,16 @@ BEGIN
750750 CONTROL "UTF-8",HSET_UTF8N_CNV,"Button",BS_AUTORADIOBUTTON,12,69,41,10
751751 CONTROL "UTF-8 BOM",HSET_UTF8BOM_CNV,"Button",BS_AUTORADIOBUTTON,12,81,81,10
752752 CONTROL "”¼ŠpƒJƒi‚ð‘SŠp‚É•ÏŠ·",HSET_HANCNV,"Button",BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,12,98,87,10
753- GROUPBOX "ƒtƒ@ƒCƒ‹–¼‚ÌŠ¿ŽšƒR[ƒh(&N)",-1,110,7,90,115,WS_GROUP
753+ GROUPBOX "ƒtƒ@ƒCƒ‹–¼‚ÌŠ¿ŽšƒR[ƒh(&N)",-1,110,7,90,127,WS_GROUP
754754 CONTROL "Ž©“®",HSET_FN_AUTO_CNV,"Button",BS_AUTORADIOBUTTON | WS_GROUP,114,21,65,10
755- CONTROL "Shift_JIS",HSET_FN_SJIS_CNV,"Button",BS_AUTORADIOBUTTON,114,33,65,10
756- CONTROL "JIS",HSET_FN_JIS_CNV,"Button",BS_AUTORADIOBUTTON,114,45,70,10
757- CONTROL "EUC",HSET_FN_EUC_CNV,"Button",BS_AUTORADIOBUTTON,114,57,41,10
758- CONTROL "Samba-HEX",HSET_FN_SMH_CNV,"Button",BS_AUTORADIOBUTTON,114,69,66,10
759- CONTROL "Samba-CAP",HSET_FN_SMC_CNV,"Button",BS_AUTORADIOBUTTON,114,81,64,10
760- CONTROL "UTF-8",HSET_FN_UTF8N_CNV,"Button",BS_AUTORADIOBUTTON,114,93,41,10
761- CONTROL "”¼ŠpƒJƒi‚ð‘SŠp‚É•ÏŠ·",HSET_FN_HANCNV,"Button",BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,114,107,81,10
755+ CONTROL "Shift_JIS",HSET_FN_SJIS_CNV,"Button",BS_AUTORADIOBUTTON,114,33,81,10
756+ CONTROL "JIS",HSET_FN_JIS_CNV,"Button",BS_AUTORADIOBUTTON,114,45,81,10
757+ CONTROL "EUC",HSET_FN_EUC_CNV,"Button",BS_AUTORADIOBUTTON,114,57,81,10
758+ CONTROL "Samba-HEX",HSET_FN_SMH_CNV,"Button",BS_AUTORADIOBUTTON,114,69,81,10
759+ CONTROL "Samba-CAP",HSET_FN_SMC_CNV,"Button",BS_AUTORADIOBUTTON,114,81,81,10
760+ CONTROL "UTF-8",HSET_FN_UTF8N_CNV,"Button",BS_AUTORADIOBUTTON,114,93,81,10
761+ CONTROL "UTF-8 HFS+",HSET_FN_UTF8HFSX_CNV,"Button",BS_AUTORADIOBUTTON,114,105,81,10
762+ CONTROL "”¼ŠpƒJƒi‚ð‘SŠp‚É•ÏŠ·",HSET_FN_HANCNV,"Button",BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,114,119,81,10
762763 END
763764
764765 opt_trmode1_dlg DIALOG 0, 0, 211, 155
--- a/Resource/resource.h
+++ b/Resource/resource.h
@@ -460,6 +460,7 @@
460460 #define TRMODE4_UTF8N_CNV 1218
461461 #define TRMODE4_UTF8BOM_CNV 1219
462462 #define HSET_ERROR_RECONNECT 1220
463+#define HSET_FN_UTF8HFSX_CNV 1221
463464 #define MENU_END 40001
464465 #define MENU_EXIT 40001
465466 #define MENU_CONNECT 40003
--- a/Resource_eng/FFFTP-eng.rc
+++ b/Resource_eng/FFFTP-eng.rc
@@ -758,15 +758,16 @@ BEGIN
758758 CONTROL "UTF-8",HSET_UTF8N_CNV,"Button",BS_AUTORADIOBUTTON,12,69,41,10
759759 CONTROL "UTF-8 BOM",HSET_UTF8BOM_CNV,"Button",BS_AUTORADIOBUTTON,12,81,81,10
760760 CONTROL "Hankaku to Zenkaku",HSET_HANCNV,"Button",BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,12,98,90,10
761- GROUPBOX "&Filename Kanji Code",-1,107,7,97,116,WS_GROUP
761+ GROUPBOX "&Filename Kanji Code",-1,107,7,97,127,WS_GROUP
762762 CONTROL "Automatic",HSET_FN_AUTO_CNV,"Button",BS_AUTORADIOBUTTON | WS_GROUP,111,21,65,10
763- CONTROL "Shift_JIS",HSET_FN_SJIS_CNV,"Button",BS_AUTORADIOBUTTON,111,33,65,10
764- CONTROL "JIS",HSET_FN_JIS_CNV,"Button",BS_AUTORADIOBUTTON,111,45,70,10
765- CONTROL "EUC",HSET_FN_EUC_CNV,"Button",BS_AUTORADIOBUTTON,111,57,41,10
766- CONTROL "Samba-HEX",HSET_FN_SMH_CNV,"Button",BS_AUTORADIOBUTTON,111,69,66,10
767- CONTROL "Samba-CAP",HSET_FN_SMC_CNV,"Button",BS_AUTORADIOBUTTON,111,81,64,10
768- CONTROL "UTF-8",HSET_FN_UTF8N_CNV,"Button",BS_AUTORADIOBUTTON,111,93,63,10
769- CONTROL "Hankaku to Zenkaku",HSET_FN_HANCNV,"Button",BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,111,108,91,10
763+ CONTROL "Shift_JIS",HSET_FN_SJIS_CNV,"Button",BS_AUTORADIOBUTTON,111,33,81,10
764+ CONTROL "JIS",HSET_FN_JIS_CNV,"Button",BS_AUTORADIOBUTTON,111,45,81,10
765+ CONTROL "EUC",HSET_FN_EUC_CNV,"Button",BS_AUTORADIOBUTTON,111,57,81,10
766+ CONTROL "Samba-HEX",HSET_FN_SMH_CNV,"Button",BS_AUTORADIOBUTTON,111,69,81,10
767+ CONTROL "Samba-CAP",HSET_FN_SMC_CNV,"Button",BS_AUTORADIOBUTTON,111,81,81,10
768+ CONTROL "UTF-8",HSET_FN_UTF8N_CNV,"Button",BS_AUTORADIOBUTTON,111,93,81,10
769+ CONTROL "UTF-8 HFS+",HSET_FN_UTF8HFSX_CNV,"Button",BS_AUTORADIOBUTTON,111,105,81,10
770+ CONTROL "Hankaku to Zenkaku",HSET_FN_HANCNV,"Button",BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,111,119,81,10
770771 END
771772
772773 opt_trmode1_dlg DIALOG 0, 0, 211, 155
--- a/Resource_eng/resource.h
+++ b/Resource_eng/resource.h
@@ -460,6 +460,7 @@
460460 #define TRMODE4_UTF8N_CNV 1218
461461 #define TRMODE4_UTF8BOM_CNV 1219
462462 #define HSET_ERROR_RECONNECT 1220
463+#define HSET_FN_UTF8HFSX_CNV 1221
463464 #define MENU_END 40001
464465 #define MENU_EXIT 40001
465466 #define MENU_CONNECT 40003
--- a/codecnv.c
+++ b/codecnv.c
@@ -36,6 +36,8 @@
3636 #include <winsock2.h>
3737 #include <mbstring.h>
3838 #include <windowsx.h>
39+// UTF-8対応
40+#include <winnls.h>
3941
4042 #include "common.h"
4143 #include "resource.h"
@@ -61,6 +63,19 @@ static int CheckOnEUC(uchar *Pos, uchar *Btm);
6163 static int ConvertIBMExtendedChar(int code);
6264
6365
66+typedef enum _NORM_FORM
67+{
68+ NormalizationOther = 0,
69+ NormalizationC = 0x1,
70+ NormalizationD = 0x2,
71+ NormalizationKC = 0x5,
72+ NormalizationKD = 0x6
73+} NORM_FORM;
74+
75+typedef int (WINAPI* _NormalizeString)(NORM_FORM, LPCWSTR, int, LPWSTR, int);
76+
77+HMODULE hUnicodeNormalizationDll;
78+_NormalizeString p_NormalizeString;
6479
6580 #if 0
6681 /*----- 漢字コード変換のテストプログラム ------------------------------------*/
@@ -1844,6 +1859,242 @@ int ConvSJIStoUTF8N(CODECONVINFO *cInfo)
18441859 }
18451860 // UTF-8対応 ここまで↑
18461861
1862+// UTF-8 HFS+対応
1863+int ConvUTF8NtoUTF8HFSX(CODECONVINFO *cInfo)
1864+{
1865+ int Continue;
1866+ int SrcLength;
1867+ char* pSrc;
1868+ char* pSrcCur;
1869+ char* pSrcEnd;
1870+ char* pSrcNext;
1871+ char* pDstCur;
1872+ char* pDstEnd;
1873+ DWORD Code;
1874+ int Count;
1875+ wchar_t Temp1[4];
1876+ wchar_t Temp2[4];
1877+ char Temp3[16];
1878+ char* Temp3Cur;
1879+ char* Temp3End;
1880+ int TempCount;
1881+ Continue = NO;
1882+ SrcLength = cInfo->StrLen + cInfo->EscUTF8Len;
1883+ if(!(pSrc = (char*)malloc(sizeof(char) * (SrcLength + 1))))
1884+ {
1885+ *(cInfo->Buf) = '\0';
1886+ cInfo->BufSize = 0;
1887+ return Continue;
1888+ }
1889+ memcpy(pSrc, cInfo->EscUTF8, sizeof(char) * cInfo->EscUTF8Len);
1890+ memcpy(pSrc + cInfo->EscUTF8Len, cInfo->Str, sizeof(char) * cInfo->StrLen);
1891+ *(pSrc + SrcLength) = '\0';
1892+ cInfo->OutLen = 0;
1893+ pSrcCur = pSrc;
1894+ pSrcEnd = pSrc + SrcLength;
1895+ pSrcNext = pSrc;
1896+ pDstCur = cInfo->Buf;
1897+ pDstEnd = cInfo->Buf + cInfo->BufSize;
1898+ while(pSrcCur < pSrcEnd)
1899+ {
1900+ Code = GetNextCharM(pSrcCur, pSrcEnd, (LPCSTR*)&pSrcNext);
1901+ if(Code == 0x80000000)
1902+ {
1903+ if(pSrcNext == pSrcEnd)
1904+ // 入力の末尾が不完全
1905+ break;
1906+ }
1907+ else if((Code >= 0x00002000 && Code <= 0x00002fff)
1908+ || (Code >= 0x0000f900 && Code <= 0x0000faff)
1909+ || (Code >= 0x0002f800 && Code <= 0x0002faff))
1910+ {
1911+ // HFS+特有の例外
1912+ Count = PutNextCharM(pDstCur, pDstEnd, &pDstCur, Code);
1913+ if(Count > 0)
1914+ cInfo->OutLen += Count;
1915+ else
1916+ {
1917+ // 出力バッファが不足
1918+ Continue = YES;
1919+ break;
1920+ }
1921+ }
1922+ else
1923+ {
1924+ // Normalization Form Dに変換
1925+ Count = MultiByteToWideChar(CP_UTF8, 0, pSrcCur, (int)(pSrcNext - pSrcCur), Temp1, 4);
1926+ Count = p_NormalizeString(NormalizationD, Temp1, Count, Temp2, 4);
1927+ Count = WideCharToMultiByte(CP_UTF8, 0, Temp2, Count, Temp3, 16, NULL, NULL);
1928+ Temp3Cur = Temp3;
1929+ Temp3End = Temp3 + Count;
1930+ TempCount = 0;
1931+ while(Temp3Cur < Temp3End)
1932+ {
1933+ Code = GetNextCharM(Temp3Cur, Temp3End, (LPCSTR*)&Temp3Cur);
1934+ Count = PutNextCharM(pDstCur, pDstEnd, &pDstCur, Code);
1935+ if(Count > 0)
1936+ TempCount += Count;
1937+ else
1938+ {
1939+ // 出力バッファが不足
1940+ Continue = YES;
1941+ break;
1942+ }
1943+ }
1944+ cInfo->OutLen += TempCount;
1945+ }
1946+ pSrcCur = pSrcNext;
1947+ }
1948+ cInfo->Str += (int)(pSrcCur - pSrc) - cInfo->EscUTF8Len;
1949+ cInfo->StrLen -= (int)(pSrcCur - pSrc) - cInfo->EscUTF8Len;
1950+ cInfo->EscUTF8Len = 0;
1951+ free(pSrc);
1952+ if(Continue == NO)
1953+ {
1954+ memcpy(cInfo->EscUTF8, cInfo->Str, sizeof(char) * cInfo->StrLen);
1955+ cInfo->EscUTF8Len = cInfo->StrLen;
1956+ cInfo->Str += cInfo->StrLen;
1957+ cInfo->StrLen = 0;
1958+ cInfo->FlushProc = ConvUTF8NtoUTF8HFSX;
1959+ }
1960+ return YES;
1961+}
1962+
1963+// バグの可能性あり
1964+// 確認するまで複数個のバッファを用いた変換には用いないこと
1965+// UTF-8 Nomalization Form DからCへの変換後のバイト列が確定可能な長さを変換後のコードポイントの個数で返す
1966+// バイナリ UTF-8 戻り値
1967+// E3 81 82 E3 81 84 あい -> 1 あ+結合文字の先頭バイトの可能性(い゛等)
1968+// E3 81 82 E3 81 あ+E3 81 -> 0 結合文字の先頭バイトの可能性
1969+// E3 81 82 E3 あ+E3 -> 0 結合文字の先頭バイトの可能性
1970+// E3 81 82 あ -> 0 結合文字の先頭バイトの可能性
1971+int ConvUTF8HFSXtoUTF8N_TruncateToDelimiter(char* pUTF8, int UTF8Length, int* pNewUTF8Length)
1972+{
1973+ int UTF16Length;
1974+ wchar_t* pUTF16;
1975+ int UTF16HFSXLength;
1976+ wchar_t* pUTF16HFSX;
1977+ int CodeCount;
1978+ int NewCodeCount;
1979+ int NewUTF16Length;
1980+ UTF16Length = MultiByteToWideChar(CP_UTF8, 0, pUTF8, UTF8Length, NULL, 0);
1981+ if(!(pUTF16 = (wchar_t*)malloc(sizeof(wchar_t) * UTF16Length)))
1982+ return -1;
1983+ UTF16Length = MultiByteToWideChar(CP_UTF8, 0, pUTF8, UTF8Length, pUTF16, UTF16Length);
1984+ UTF16HFSXLength = p_NormalizeString(NormalizationC, pUTF16, UTF16Length, NULL, 0);
1985+ if(!(pUTF16HFSX = (wchar_t*)malloc(sizeof(wchar_t) * UTF16HFSXLength)))
1986+ {
1987+ free(pUTF16);
1988+ return -1;
1989+ }
1990+ UTF16HFSXLength = p_NormalizeString(NormalizationC, pUTF16, UTF16Length, pUTF16HFSX, UTF16HFSXLength);
1991+ // 変換した時にコードポイントの個数が増減する位置がUnicode結合文字の区切り
1992+ CodeCount = GetCodeCountW(pUTF16HFSX, UTF16HFSXLength);
1993+ NewCodeCount = CodeCount;
1994+ while(UTF8Length > 0 && NewCodeCount >= CodeCount)
1995+ {
1996+ UTF8Length--;
1997+ UTF16Length = MultiByteToWideChar(CP_UTF8, 0, pUTF8, UTF8Length, pUTF16, UTF16Length);
1998+ UTF16HFSXLength = p_NormalizeString(NormalizationC, pUTF16, UTF16Length, pUTF16HFSX, UTF16HFSXLength);
1999+ NewCodeCount = GetCodeCountW(pUTF16HFSX, UTF16HFSXLength);
2000+ }
2001+ free(pUTF16);
2002+ free(pUTF16HFSX);
2003+ // UTF-16 LE変換した時に文字数が増減する位置がUTF-8の区切り
2004+ if(pNewUTF8Length)
2005+ {
2006+ NewUTF16Length = UTF16Length;
2007+ while(UTF8Length > 0 && NewUTF16Length >= UTF16Length)
2008+ {
2009+ UTF8Length--;
2010+ NewUTF16Length = MultiByteToWideChar(CP_UTF8, 0, pUTF8, UTF8Length, NULL, 0);
2011+ }
2012+ if(UTF16Length > 0)
2013+ UTF8Length++;
2014+ *pNewUTF8Length = UTF8Length;
2015+ }
2016+ return NewCodeCount;
2017+}
2018+
2019+int ConvUTF8HFSXtoUTF8N(CODECONVINFO *cInfo)
2020+{
2021+ int Continue;
2022+ int SrcLength;
2023+ char* pSrc;
2024+ int UTF16Length;
2025+ wchar_t* pUTF16;
2026+ int UTF16HFSXLength;
2027+ wchar_t* pUTF16HFSX;
2028+ CODECONVINFO Temp;
2029+ int Count;
2030+ Continue = NO;
2031+ // 前回の変換不能な残りの文字列を入力の先頭に結合
2032+ SrcLength = cInfo->StrLen + cInfo->EscUTF8Len;
2033+ if(!(pSrc = (char*)malloc(sizeof(char) * (SrcLength + 1))))
2034+ {
2035+ *(cInfo->Buf) = '\0';
2036+ cInfo->BufSize = 0;
2037+ return Continue;
2038+ }
2039+ memcpy(pSrc, cInfo->EscUTF8, sizeof(char) * cInfo->EscUTF8Len);
2040+ memcpy(pSrc + cInfo->EscUTF8Len, cInfo->Str, sizeof(char) * cInfo->StrLen);
2041+ *(pSrc + SrcLength) = '\0';
2042+ UTF16Length = MultiByteToWideChar(CP_UTF8, 0, pSrc, SrcLength, NULL, 0);
2043+ if(!(pUTF16 = (wchar_t*)malloc(sizeof(wchar_t) * UTF16Length)))
2044+ {
2045+ free(pSrc);
2046+ *(cInfo->Buf) = '\0';
2047+ cInfo->BufSize = 0;
2048+ return Continue;
2049+ }
2050+ MultiByteToWideChar(CP_UTF8, 0, pSrc, SrcLength, pUTF16, UTF16Length);
2051+ UTF16HFSXLength = p_NormalizeString(NormalizationC, pUTF16, UTF16Length, NULL, 0);
2052+ if(!(pUTF16HFSX = (wchar_t*)malloc(sizeof(wchar_t) * UTF16HFSXLength)))
2053+ {
2054+ free(pSrc);
2055+ free(pUTF16);
2056+ *(cInfo->Buf) = '\0';
2057+ cInfo->BufSize = 0;
2058+ return Continue;
2059+ }
2060+ UTF16HFSXLength = p_NormalizeString(NormalizationC, pUTF16, UTF16Length, pUTF16HFSX, UTF16HFSXLength);
2061+ cInfo->OutLen = WideCharToMultiByte(CP_UTF8, 0, pUTF16HFSX, UTF16HFSXLength, cInfo->Buf, cInfo->BufSize, NULL, NULL);
2062+ if(cInfo->OutLen == 0 && UTF16HFSXLength > 0)
2063+ {
2064+ // バッファに収まらないため変換文字数を半減
2065+ Temp = *cInfo;
2066+ Temp.StrLen = cInfo->StrLen / 2;
2067+ ConvUTF8HFSXtoUTF8N(&Temp);
2068+ cInfo->OutLen = Temp.OutLen;
2069+ Count = cInfo->StrLen / 2 + cInfo->EscUTF8Len - Temp.StrLen - Temp.EscUTF8Len;
2070+ cInfo->Str += Count - cInfo->EscUTF8Len;
2071+ cInfo->StrLen -= Count - cInfo->EscUTF8Len;
2072+ cInfo->EscUTF8Len = 0;
2073+ }
2074+ else
2075+ {
2076+ cInfo->Str += SrcLength - cInfo->EscUTF8Len;
2077+ cInfo->StrLen -= SrcLength - cInfo->EscUTF8Len;
2078+ cInfo->EscUTF8Len = 0;
2079+ }
2080+ if(ConvUTF8HFSXtoUTF8N_TruncateToDelimiter(cInfo->Str, cInfo->StrLen, NULL) > 0)
2081+ Continue = YES;
2082+ else
2083+ {
2084+ // 変換不能なため次の入力の先頭に結合
2085+ memcpy(cInfo->EscUTF8, cInfo->Str, sizeof(char) * cInfo->StrLen);
2086+ cInfo->EscUTF8Len = cInfo->StrLen;
2087+ cInfo->Str += cInfo->StrLen;
2088+ cInfo->StrLen = 0;
2089+ cInfo->FlushProc = ConvUTF8HFSXtoUTF8N;
2090+ Continue = NO;
2091+ }
2092+ free(pSrc);
2093+ free(pUTF16);
2094+ free(pUTF16HFSX);
2095+ return Continue;
2096+}
2097+
18472098
18482099 /*----- IBM拡張漢字をNEC選定IBM拡張漢字等に変換 -------------------------------
18492100 *
@@ -1873,3 +2124,45 @@ static int ConvertIBMExtendedChar(int code)
18732124 return code;
18742125 }
18752126
2127+// UTF-8対応
2128+int LoadUnicodeNormalizationDll()
2129+{
2130+ int Sts;
2131+ char CurDir[FMAX_PATH+1];
2132+ char SysDir[FMAX_PATH+1];
2133+ Sts = FFFTP_FAIL;
2134+ if(GetCurrentDirectory(FMAX_PATH, CurDir) > 0)
2135+ {
2136+ if(GetSystemDirectory(SysDir, FMAX_PATH) > 0)
2137+ {
2138+ if(SetCurrentDirectory(SysDir))
2139+ {
2140+ if((hUnicodeNormalizationDll = LoadLibrary("normaliz.dll")) != NULL)
2141+ {
2142+ if((p_NormalizeString = (_NormalizeString)GetProcAddress(hUnicodeNormalizationDll, "NormalizeString")) != NULL)
2143+ Sts = FFFTP_SUCCESS;
2144+ }
2145+ SetCurrentDirectory(CurDir);
2146+ }
2147+ }
2148+ }
2149+ return Sts;
2150+}
2151+
2152+void FreeUnicodeNormalizationDll()
2153+{
2154+ if(hUnicodeNormalizationDll != NULL)
2155+ FreeLibrary(hUnicodeNormalizationDll);
2156+ hUnicodeNormalizationDll = NULL;
2157+ p_NormalizeString = NULL;
2158+}
2159+
2160+int IsUnicodeNormalizationDllLoaded()
2161+{
2162+ int Sts;
2163+ Sts = FFFTP_FAIL;
2164+ if(hUnicodeNormalizationDll != NULL && p_NormalizeString != NULL)
2165+ Sts = FFFTP_SUCCESS;
2166+ return Sts;
2167+}
2168+
--- a/common.h
+++ b/common.h
@@ -746,6 +746,8 @@ LIST_UNIX_70
746746 #define KANJI_UTF8N 5 /* UTF-8 */
747747 // UTF-8対応
748748 #define KANJI_UTF8BOM 6 /* UTF-8 BOM */
749+// UTF-8 HFS+対応
750+#define KANJI_UTF8HFSX 7 /* UTF-8 HFS+ */
749751
750752 #define KANJI_NOCNV -1 /* 漢字コード変換なし */
751753
@@ -1735,8 +1737,15 @@ int ConvSJIStoJIS(CODECONVINFO *cInfo);
17351737 int ConvSJIStoSMB_HEX(CODECONVINFO *cInfo);
17361738 int ConvSJIStoSMB_CAP(CODECONVINFO *cInfo);
17371739 int ConvSJIStoUTF8N(CODECONVINFO *cInfo); // UTF-8対応
1740+// UTF-8 HFS+対応
1741+int ConvUTF8NtoUTF8HFSX(CODECONVINFO *cInfo);
1742+int ConvUTF8HFSXtoUTF8N(CODECONVINFO *cInfo);
17381743 void ConvAutoToSJIS(char *Text, int Pref);
17391744 int CheckKanjiCode(char *Text, int Size, int Pref);
1745+// UTF-8対応
1746+int LoadUnicodeNormalizationDll();
1747+void FreeUnicodeNormalizationDll();
1748+int IsUnicodeNormalizationDllLoaded();
17401749
17411750 /*===== option.c =====*/
17421751
--- a/connect.c
+++ b/connect.c
@@ -1865,8 +1865,10 @@ static SOCKET DoConnectCrypt(int CryptMode, HOSTDATA* HostData, char *Host, char
18651865 // UTF-8対応
18661866 if(HostData->CurNameKanjiCode == KANJI_AUTO && (HostData->Feature & FEATURE_UTF8))
18671867 {
1868- if((Sts = command(ContSock, Reply, CancelCheckWork, "OPTS UTF8 ON")) == 200)
1869- HostData->CurNameKanjiCode = KANJI_UTF8N;
1868+ // UTF-8を指定した場合も自動判別を行う
1869+// if((Sts = command(ContSock, Reply, CancelCheckWork, "OPTS UTF8 ON")) == 200)
1870+// HostData->CurNameKanjiCode = KANJI_UTF8N;
1871+ command(ContSock, Reply, CancelCheckWork, "OPTS UTF8 ON");
18701872 }
18711873 }
18721874 }
--- a/filelist.c
+++ b/filelist.c
@@ -6144,7 +6144,7 @@ static int atoi_n(const char *Str, int Len)
61446144
61456145 // UTF-8対応
61466146 // ファイル一覧から漢字コードを推測
6147-// 優先度はUTF-8、Shift_JIS、EUC、JISの順
6147+// 優先度はUTF-8、Shift_JIS、EUC、JIS、UTF-8 HFS+の順
61486148 int AnalyzeNameKanjiCode(int Num)
61496149 {
61506150 char Str[FMAX_PATH+1];
@@ -6164,7 +6164,11 @@ int AnalyzeNameKanjiCode(int Num)
61646164 int PointJIS;
61656165 int PointEUC;
61666166 int PointUTF8N;
6167+ int PointUTF8HFSX;
61676168 char* p;
6169+ CODECONVINFO cInfo1;
6170+ CODECONVINFO cInfo2;
6171+ char Buf[FMAX_PATH+1];
61686172
61696173 NameKanjiCode = KANJI_AUTO;
61706174 Point = 0;
@@ -6172,6 +6176,7 @@ int AnalyzeNameKanjiCode(int Num)
61726176 PointJIS = 0;
61736177 PointEUC = 0;
61746178 PointUTF8N = 0;
6179+ PointUTF8HFSX = 0;
61756180 MakeCacheFileName(Num, Str);
61766181 if((fd = fopen(Str, "rb")) != NULL)
61776182 {
@@ -6194,7 +6199,25 @@ int AnalyzeNameKanjiCode(int Num)
61946199 if(!p)
61956200 {
61966201 if(!CheckStringM(Name))
6197- PointUTF8N++;
6202+ {
6203+ InitCodeConvInfo(&cInfo1);
6204+ cInfo1.KanaCnv = NO;
6205+ cInfo1.Str = Name;
6206+ cInfo1.StrLen = strlen(Name);
6207+ cInfo1.Buf = Buf;
6208+ cInfo1.BufSize = FMAX_PATH;
6209+ cInfo2 = cInfo1;
6210+ ConvUTF8NtoUTF8HFSX(&cInfo1);
6211+ ConvUTF8HFSXtoUTF8N(&cInfo2);
6212+ if(cInfo1.OutLen > strlen(Name))
6213+ PointUTF8N++;
6214+ else
6215+ PointUTF8HFSX++;
6216+ if(cInfo2.OutLen < strlen(Name))
6217+ PointUTF8HFSX++;
6218+ else
6219+ PointUTF8N++;
6220+ }
61986221 else
61996222 {
62006223 switch(CheckKanjiCode(Name, strlen(Name), KANJI_SJIS))
@@ -6215,6 +6238,11 @@ int AnalyzeNameKanjiCode(int Num)
62156238 }
62166239 fclose(fd);
62176240 }
6241+ if(PointUTF8HFSX >= Point)
6242+ {
6243+ NameKanjiCode = KANJI_UTF8HFSX;
6244+ Point = PointUTF8HFSX;
6245+ }
62186246 if(PointJIS >= Point)
62196247 {
62206248 NameKanjiCode = KANJI_JIS;
--- a/hostman.c
+++ b/hostman.c
@@ -1938,7 +1938,10 @@ static INT_PTR CALLBACK CodeSettingProc(HWND hDlg, UINT iMessage, WPARAM wParam,
19381938 { HSET_FN_EUC_CNV, KANJI_EUC },
19391939 { HSET_FN_SMH_CNV, KANJI_SMB_HEX },
19401940 { HSET_FN_SMC_CNV, KANJI_SMB_CAP },
1941- { HSET_FN_UTF8N_CNV, KANJI_UTF8N } // UTF-8対応
1941+ // UTF-8 HFS+対応
1942+// { HSET_FN_UTF8N_CNV, KANJI_UTF8N } // UTF-8対応
1943+ { HSET_FN_UTF8N_CNV, KANJI_UTF8N }, // UTF-8対応
1944+ { HSET_FN_UTF8HFSX_CNV, KANJI_UTF8HFSX }
19421945 };
19431946 #define NAMEKANJIBUTTONS (sizeof(NameKanjiButton)/sizeof(RADIOBUTTON))
19441947
@@ -1998,6 +2001,8 @@ static INT_PTR CALLBACK CodeSettingProc(HWND hDlg, UINT iMessage, WPARAM wParam,
19982001 case HSET_FN_SMH_CNV :
19992002 case HSET_FN_SMC_CNV :
20002003 case HSET_FN_UTF8N_CNV : // UTF-8対応
2004+ // UTF-8 HFS+対応
2005+ case HSET_FN_UTF8HFSX_CNV :
20012006 EnableWindow(GetDlgItem(hDlg, HSET_FN_HANCNV), FALSE);
20022007 break;
20032008 }
--- a/main.c
+++ b/main.c
@@ -372,6 +372,9 @@ int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLi
372372 CoInitialize(NULL);
373373 LoadUPnP();
374374
375+ // UTF-8対応
376+ LoadUnicodeNormalizationDll();
377+
375378 // FTPS対応
376379 #ifdef USE_OPENSSL
377380 LoadOpenSSL();
--- a/mbswrapper.c
+++ b/mbswrapper.c
@@ -578,6 +578,48 @@ int PutNextCharW(LPWSTR lpString, LPWSTR pLimit, LPWSTR* ppNext, DWORD Code)
578578 return Count;
579579 }
580580
581+// マルチバイト文字列のコードポイントの個数を取得
582+int GetCodeCountM(LPCSTR lpString, int CharCount)
583+{
584+ int Count;
585+ LPCSTR pLimit;
586+ DWORD Code;
587+ Count = 0;
588+ if(CharCount == -1)
589+ pLimit = lpString + strlen(lpString);
590+ else
591+ pLimit = lpString + CharCount;
592+ while(lpString < pLimit)
593+ {
594+ Code = GetNextCharM(lpString, pLimit, &lpString);
595+ if(Code == 0x80000000)
596+ continue;
597+ Count++;
598+ }
599+ return Count;
600+}
601+
602+// ワイド文字列のコードポイントの個数を取得
603+int GetCodeCountW(LPCWSTR lpString, int CharCount)
604+{
605+ int Count;
606+ LPCWSTR pLimit;
607+ DWORD Code;
608+ Count = 0;
609+ if(CharCount == -1)
610+ pLimit = lpString + wcslen(lpString);
611+ else
612+ pLimit = lpString + CharCount;
613+ while(lpString < pLimit)
614+ {
615+ Code = GetNextCharW(lpString, pLimit, &lpString);
616+ if(Code == 0x80000000)
617+ continue;
618+ Count++;
619+ }
620+ return Count;
621+}
622+
581623 // マルチバイト文字列の冗長表現を修正
582624 // 修正があればTRUEを返す
583625 // 修正後の文字列の長さは元の文字列の長さ以下のためpDstとpSrcに同じ値を指定可能
--- a/mbswrapper.h
+++ b/mbswrapper.h
@@ -282,6 +282,8 @@ DWORD GetNextCharM(LPCSTR lpString, LPCSTR pLimit, LPCSTR* ppNext);
282282 int PutNextCharM(LPSTR lpString, LPSTR pLimit, LPSTR* ppNext, DWORD Code);
283283 DWORD GetNextCharW(LPCWSTR lpString, LPCWSTR pLimit, LPCWSTR* ppNext);
284284 int PutNextCharW(LPWSTR lpString, LPWSTR pLimit, LPWSTR* ppNext, DWORD Code);
285+int GetCodeCountM(LPCSTR lpString, int CharCount);
286+int GetCodeCountW(LPCWSTR lpString, int CharCount);
285287 BOOL FixStringM(LPSTR pDst, LPCSTR pSrc);
286288 BOOL FixMultiStringM(LPSTR pDst, LPCSTR pSrc);
287289 BOOL CheckStringM(LPCSTR lpString);
--- a/remote.c
+++ b/remote.c
@@ -1655,6 +1655,20 @@ int ChangeFnameRemote2Local(char *Fname, int Max)
16551655 // *(Buf + cInfo.OutLen) = NUL;
16561656 // strcpy(Pos, Buf);
16571657 // break;
1658+
1659+ // UTF-8 HFS+対応
1660+ case KANJI_UTF8HFSX :
1661+ if(IsUnicodeNormalizationDllLoaded())
1662+ {
1663+ ConvUTF8HFSXtoUTF8N(&cInfo);
1664+ *(Buf + cInfo.OutLen) = NUL;
1665+ strcpy(Fname, Buf);
1666+ Pos = strchr(Fname, NUL);
1667+ FlushRestData(&cInfo);
1668+ *(Buf + cInfo.OutLen) = NUL;
1669+ strcpy(Pos, Buf);
1670+ }
1671+ break;
16581672 }
16591673 // バッファ上書きバグ対策
16601674 free(Buf2);
@@ -1823,6 +1837,20 @@ int ChangeFnameLocal2Remote(char *Fname, int Max)
18231837 // *(Buf + cInfo.OutLen) = NUL;
18241838 // strcpy(Pos, Buf);
18251839 // break;
1840+
1841+ // UTF-8 HFS+対応
1842+ case KANJI_UTF8HFSX :
1843+ if(IsUnicodeNormalizationDllLoaded())
1844+ {
1845+ ConvUTF8NtoUTF8HFSX(&cInfo);
1846+ *(Buf + cInfo.OutLen) = NUL;
1847+ strcpy(Fname, Buf);
1848+ Pos = strchr(Fname, NUL);
1849+ FlushRestData(&cInfo);
1850+ *(Buf + cInfo.OutLen) = NUL;
1851+ strcpy(Pos, Buf);
1852+ }
1853+ break;
18261854 }
18271855 // バッファ上書きバグ対策
18281856 free(Buf2);