FFFTPのソースコードです。
Revision | f3bb77eff8ad09c3a64851ad1b2790823afe02f2 (tree) |
---|---|
Zeit | 2013-10-20 01:21:40 |
Autor | s_kawamoto <s_kawamoto@user...> |
Commiter | s_kawamoto |
Add support for UTF-8 HFS+ filenames (Windows Vista or later only).
@@ -750,15 +750,16 @@ BEGIN | ||
750 | 750 | CONTROL "UTF-8",HSET_UTF8N_CNV,"Button",BS_AUTORADIOBUTTON,12,69,41,10 |
751 | 751 | CONTROL "UTF-8 BOM",HSET_UTF8BOM_CNV,"Button",BS_AUTORADIOBUTTON,12,81,81,10 |
752 | 752 | CONTROL "¼pJiðSpÉÏ·",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 | |
754 | 754 | 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 "¼pJiðSpÉÏ·",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 "¼pJiðSpÉÏ·",HSET_FN_HANCNV,"Button",BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,114,119,81,10 | |
762 | 763 | END |
763 | 764 | |
764 | 765 | opt_trmode1_dlg DIALOG 0, 0, 211, 155 |
@@ -460,6 +460,7 @@ | ||
460 | 460 | #define TRMODE4_UTF8N_CNV 1218 |
461 | 461 | #define TRMODE4_UTF8BOM_CNV 1219 |
462 | 462 | #define HSET_ERROR_RECONNECT 1220 |
463 | +#define HSET_FN_UTF8HFSX_CNV 1221 | |
463 | 464 | #define MENU_END 40001 |
464 | 465 | #define MENU_EXIT 40001 |
465 | 466 | #define MENU_CONNECT 40003 |
@@ -758,15 +758,16 @@ BEGIN | ||
758 | 758 | CONTROL "UTF-8",HSET_UTF8N_CNV,"Button",BS_AUTORADIOBUTTON,12,69,41,10 |
759 | 759 | CONTROL "UTF-8 BOM",HSET_UTF8BOM_CNV,"Button",BS_AUTORADIOBUTTON,12,81,81,10 |
760 | 760 | 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 | |
762 | 762 | 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 | |
770 | 771 | END |
771 | 772 | |
772 | 773 | opt_trmode1_dlg DIALOG 0, 0, 211, 155 |
@@ -460,6 +460,7 @@ | ||
460 | 460 | #define TRMODE4_UTF8N_CNV 1218 |
461 | 461 | #define TRMODE4_UTF8BOM_CNV 1219 |
462 | 462 | #define HSET_ERROR_RECONNECT 1220 |
463 | +#define HSET_FN_UTF8HFSX_CNV 1221 | |
463 | 464 | #define MENU_END 40001 |
464 | 465 | #define MENU_EXIT 40001 |
465 | 466 | #define MENU_CONNECT 40003 |
@@ -36,6 +36,8 @@ | ||
36 | 36 | #include <winsock2.h> |
37 | 37 | #include <mbstring.h> |
38 | 38 | #include <windowsx.h> |
39 | +// UTF-8対応 | |
40 | +#include <winnls.h> | |
39 | 41 | |
40 | 42 | #include "common.h" |
41 | 43 | #include "resource.h" |
@@ -61,6 +63,19 @@ static int CheckOnEUC(uchar *Pos, uchar *Btm); | ||
61 | 63 | static int ConvertIBMExtendedChar(int code); |
62 | 64 | |
63 | 65 | |
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; | |
64 | 79 | |
65 | 80 | #if 0 |
66 | 81 | /*----- 漢字コード変換のテストプログラム ------------------------------------*/ |
@@ -1844,6 +1859,242 @@ int ConvSJIStoUTF8N(CODECONVINFO *cInfo) | ||
1844 | 1859 | } |
1845 | 1860 | // UTF-8対応 ここまで↑ |
1846 | 1861 | |
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 | + | |
1847 | 2098 | |
1848 | 2099 | /*----- IBM拡張漢字をNEC選定IBM拡張漢字等に変換 ------------------------------- |
1849 | 2100 | * |
@@ -1873,3 +2124,45 @@ static int ConvertIBMExtendedChar(int code) | ||
1873 | 2124 | return code; |
1874 | 2125 | } |
1875 | 2126 | |
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 | + |
@@ -746,6 +746,8 @@ LIST_UNIX_70 | ||
746 | 746 | #define KANJI_UTF8N 5 /* UTF-8 */ |
747 | 747 | // UTF-8対応 |
748 | 748 | #define KANJI_UTF8BOM 6 /* UTF-8 BOM */ |
749 | +// UTF-8 HFS+対応 | |
750 | +#define KANJI_UTF8HFSX 7 /* UTF-8 HFS+ */ | |
749 | 751 | |
750 | 752 | #define KANJI_NOCNV -1 /* 漢字コード変換なし */ |
751 | 753 |
@@ -1735,8 +1737,15 @@ int ConvSJIStoJIS(CODECONVINFO *cInfo); | ||
1735 | 1737 | int ConvSJIStoSMB_HEX(CODECONVINFO *cInfo); |
1736 | 1738 | int ConvSJIStoSMB_CAP(CODECONVINFO *cInfo); |
1737 | 1739 | int ConvSJIStoUTF8N(CODECONVINFO *cInfo); // UTF-8対応 |
1740 | +// UTF-8 HFS+対応 | |
1741 | +int ConvUTF8NtoUTF8HFSX(CODECONVINFO *cInfo); | |
1742 | +int ConvUTF8HFSXtoUTF8N(CODECONVINFO *cInfo); | |
1738 | 1743 | void ConvAutoToSJIS(char *Text, int Pref); |
1739 | 1744 | int CheckKanjiCode(char *Text, int Size, int Pref); |
1745 | +// UTF-8対応 | |
1746 | +int LoadUnicodeNormalizationDll(); | |
1747 | +void FreeUnicodeNormalizationDll(); | |
1748 | +int IsUnicodeNormalizationDllLoaded(); | |
1740 | 1749 | |
1741 | 1750 | /*===== option.c =====*/ |
1742 | 1751 |
@@ -1865,8 +1865,10 @@ static SOCKET DoConnectCrypt(int CryptMode, HOSTDATA* HostData, char *Host, char | ||
1865 | 1865 | // UTF-8対応 |
1866 | 1866 | if(HostData->CurNameKanjiCode == KANJI_AUTO && (HostData->Feature & FEATURE_UTF8)) |
1867 | 1867 | { |
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"); | |
1870 | 1872 | } |
1871 | 1873 | } |
1872 | 1874 | } |
@@ -6144,7 +6144,7 @@ static int atoi_n(const char *Str, int Len) | ||
6144 | 6144 | |
6145 | 6145 | // UTF-8対応 |
6146 | 6146 | // ファイル一覧から漢字コードを推測 |
6147 | -// 優先度はUTF-8、Shift_JIS、EUC、JISの順 | |
6147 | +// 優先度はUTF-8、Shift_JIS、EUC、JIS、UTF-8 HFS+の順 | |
6148 | 6148 | int AnalyzeNameKanjiCode(int Num) |
6149 | 6149 | { |
6150 | 6150 | char Str[FMAX_PATH+1]; |
@@ -6164,7 +6164,11 @@ int AnalyzeNameKanjiCode(int Num) | ||
6164 | 6164 | int PointJIS; |
6165 | 6165 | int PointEUC; |
6166 | 6166 | int PointUTF8N; |
6167 | + int PointUTF8HFSX; | |
6167 | 6168 | char* p; |
6169 | + CODECONVINFO cInfo1; | |
6170 | + CODECONVINFO cInfo2; | |
6171 | + char Buf[FMAX_PATH+1]; | |
6168 | 6172 | |
6169 | 6173 | NameKanjiCode = KANJI_AUTO; |
6170 | 6174 | Point = 0; |
@@ -6172,6 +6176,7 @@ int AnalyzeNameKanjiCode(int Num) | ||
6172 | 6176 | PointJIS = 0; |
6173 | 6177 | PointEUC = 0; |
6174 | 6178 | PointUTF8N = 0; |
6179 | + PointUTF8HFSX = 0; | |
6175 | 6180 | MakeCacheFileName(Num, Str); |
6176 | 6181 | if((fd = fopen(Str, "rb")) != NULL) |
6177 | 6182 | { |
@@ -6194,7 +6199,25 @@ int AnalyzeNameKanjiCode(int Num) | ||
6194 | 6199 | if(!p) |
6195 | 6200 | { |
6196 | 6201 | 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 | + } | |
6198 | 6221 | else |
6199 | 6222 | { |
6200 | 6223 | switch(CheckKanjiCode(Name, strlen(Name), KANJI_SJIS)) |
@@ -6215,6 +6238,11 @@ int AnalyzeNameKanjiCode(int Num) | ||
6215 | 6238 | } |
6216 | 6239 | fclose(fd); |
6217 | 6240 | } |
6241 | + if(PointUTF8HFSX >= Point) | |
6242 | + { | |
6243 | + NameKanjiCode = KANJI_UTF8HFSX; | |
6244 | + Point = PointUTF8HFSX; | |
6245 | + } | |
6218 | 6246 | if(PointJIS >= Point) |
6219 | 6247 | { |
6220 | 6248 | NameKanjiCode = KANJI_JIS; |
@@ -1938,7 +1938,10 @@ static INT_PTR CALLBACK CodeSettingProc(HWND hDlg, UINT iMessage, WPARAM wParam, | ||
1938 | 1938 | { HSET_FN_EUC_CNV, KANJI_EUC }, |
1939 | 1939 | { HSET_FN_SMH_CNV, KANJI_SMB_HEX }, |
1940 | 1940 | { 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 } | |
1942 | 1945 | }; |
1943 | 1946 | #define NAMEKANJIBUTTONS (sizeof(NameKanjiButton)/sizeof(RADIOBUTTON)) |
1944 | 1947 |
@@ -1998,6 +2001,8 @@ static INT_PTR CALLBACK CodeSettingProc(HWND hDlg, UINT iMessage, WPARAM wParam, | ||
1998 | 2001 | case HSET_FN_SMH_CNV : |
1999 | 2002 | case HSET_FN_SMC_CNV : |
2000 | 2003 | case HSET_FN_UTF8N_CNV : // UTF-8対応 |
2004 | + // UTF-8 HFS+対応 | |
2005 | + case HSET_FN_UTF8HFSX_CNV : | |
2001 | 2006 | EnableWindow(GetDlgItem(hDlg, HSET_FN_HANCNV), FALSE); |
2002 | 2007 | break; |
2003 | 2008 | } |
@@ -372,6 +372,9 @@ int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLi | ||
372 | 372 | CoInitialize(NULL); |
373 | 373 | LoadUPnP(); |
374 | 374 | |
375 | + // UTF-8対応 | |
376 | + LoadUnicodeNormalizationDll(); | |
377 | + | |
375 | 378 | // FTPS対応 |
376 | 379 | #ifdef USE_OPENSSL |
377 | 380 | LoadOpenSSL(); |
@@ -578,6 +578,48 @@ int PutNextCharW(LPWSTR lpString, LPWSTR pLimit, LPWSTR* ppNext, DWORD Code) | ||
578 | 578 | return Count; |
579 | 579 | } |
580 | 580 | |
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 | + | |
581 | 623 | // マルチバイト文字列の冗長表現を修正 |
582 | 624 | // 修正があればTRUEを返す |
583 | 625 | // 修正後の文字列の長さは元の文字列の長さ以下のためpDstとpSrcに同じ値を指定可能 |
@@ -282,6 +282,8 @@ DWORD GetNextCharM(LPCSTR lpString, LPCSTR pLimit, LPCSTR* ppNext); | ||
282 | 282 | int PutNextCharM(LPSTR lpString, LPSTR pLimit, LPSTR* ppNext, DWORD Code); |
283 | 283 | DWORD GetNextCharW(LPCWSTR lpString, LPCWSTR pLimit, LPCWSTR* ppNext); |
284 | 284 | int PutNextCharW(LPWSTR lpString, LPWSTR pLimit, LPWSTR* ppNext, DWORD Code); |
285 | +int GetCodeCountM(LPCSTR lpString, int CharCount); | |
286 | +int GetCodeCountW(LPCWSTR lpString, int CharCount); | |
285 | 287 | BOOL FixStringM(LPSTR pDst, LPCSTR pSrc); |
286 | 288 | BOOL FixMultiStringM(LPSTR pDst, LPCSTR pSrc); |
287 | 289 | BOOL CheckStringM(LPCSTR lpString); |
@@ -1655,6 +1655,20 @@ int ChangeFnameRemote2Local(char *Fname, int Max) | ||
1655 | 1655 | // *(Buf + cInfo.OutLen) = NUL; |
1656 | 1656 | // strcpy(Pos, Buf); |
1657 | 1657 | // 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; | |
1658 | 1672 | } |
1659 | 1673 | // バッファ上書きバグ対策 |
1660 | 1674 | free(Buf2); |
@@ -1823,6 +1837,20 @@ int ChangeFnameLocal2Remote(char *Fname, int Max) | ||
1823 | 1837 | // *(Buf + cInfo.OutLen) = NUL; |
1824 | 1838 | // strcpy(Pos, Buf); |
1825 | 1839 | // 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; | |
1826 | 1854 | } |
1827 | 1855 | // バッファ上書きバグ対策 |
1828 | 1856 | free(Buf2); |