diff --git a/7.4.016 b/7.4.016 new file mode 100644 index 0000000..c58c605 --- /dev/null +++ b/7.4.016 @@ -0,0 +1,221 @@ +To: vim_dev@googlegroups.com +Subject: Patch 7.4.016 +Fcc: outbox +From: Bram Moolenaar +Mime-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +------------ + +Patch 7.4.016 +Problem: MS-Windows: File name completion doesn't work properly with + Chinese characters. (Yue Wu) +Solution: Add fname_casew(). (Ken Takata) +Files: src/os_win32.c + + +*** ../vim-7.4.015/src/os_win32.c 2013-08-30 17:11:29.000000000 +0200 +--- src/os_win32.c 2013-08-30 17:28:30.000000000 +0200 +*************** +*** 2500,2508 **** +--- 2500,2624 ---- + } + + ++ #ifdef FEAT_MBYTE ++ /* ++ * fname_casew(): Wide version of fname_case(). Set the case of the file name, ++ * if it already exists. When "len" is > 0, also expand short to long ++ * filenames. ++ * Return FAIL if wide functions are not available, OK otherwise. ++ * NOTE: much of this is identical to fname_case(), keep in sync! ++ */ ++ static int ++ fname_casew( ++ WCHAR *name, ++ int len) ++ { ++ WCHAR szTrueName[_MAX_PATH + 2]; ++ WCHAR szTrueNameTemp[_MAX_PATH + 2]; ++ WCHAR *ptrue, *ptruePrev; ++ WCHAR *porig, *porigPrev; ++ int flen; ++ WIN32_FIND_DATAW fb; ++ HANDLE hFind; ++ int c; ++ int slen; ++ ++ flen = (int)wcslen(name); ++ if (flen > _MAX_PATH) ++ return OK; ++ ++ /* slash_adjust(name) not needed, already adjusted by fname_case(). */ ++ ++ /* Build the new name in szTrueName[] one component at a time. */ ++ porig = name; ++ ptrue = szTrueName; ++ ++ if (iswalpha(porig[0]) && porig[1] == L':') ++ { ++ /* copy leading drive letter */ ++ *ptrue++ = *porig++; ++ *ptrue++ = *porig++; ++ *ptrue = NUL; /* in case nothing follows */ ++ } ++ ++ while (*porig != NUL) ++ { ++ /* copy \ characters */ ++ while (*porig == psepc) ++ *ptrue++ = *porig++; ++ ++ ptruePrev = ptrue; ++ porigPrev = porig; ++ while (*porig != NUL && *porig != psepc) ++ { ++ *ptrue++ = *porig++; ++ } ++ *ptrue = NUL; ++ ++ /* To avoid a slow failure append "\*" when searching a directory, ++ * server or network share. */ ++ wcscpy(szTrueNameTemp, szTrueName); ++ slen = (int)wcslen(szTrueNameTemp); ++ if (*porig == psepc && slen + 2 < _MAX_PATH) ++ wcscpy(szTrueNameTemp + slen, L"\\*"); ++ ++ /* Skip "", "." and "..". */ ++ if (ptrue > ptruePrev ++ && (ptruePrev[0] != L'.' ++ || (ptruePrev[1] != NUL ++ && (ptruePrev[1] != L'.' || ptruePrev[2] != NUL))) ++ && (hFind = FindFirstFileW(szTrueNameTemp, &fb)) ++ != INVALID_HANDLE_VALUE) ++ { ++ c = *porig; ++ *porig = NUL; ++ ++ /* Only use the match when it's the same name (ignoring case) or ++ * expansion is allowed and there is a match with the short name ++ * and there is enough room. */ ++ if (_wcsicoll(porigPrev, fb.cFileName) == 0 ++ || (len > 0 ++ && (_wcsicoll(porigPrev, fb.cAlternateFileName) == 0 ++ && (int)(ptruePrev - szTrueName) ++ + (int)wcslen(fb.cFileName) < len))) ++ { ++ wcscpy(ptruePrev, fb.cFileName); ++ ++ /* Look for exact match and prefer it if found. Must be a ++ * long name, otherwise there would be only one match. */ ++ while (FindNextFileW(hFind, &fb)) ++ { ++ if (*fb.cAlternateFileName != NUL ++ && (wcscoll(porigPrev, fb.cFileName) == 0 ++ || (len > 0 ++ && (_wcsicoll(porigPrev, ++ fb.cAlternateFileName) == 0 ++ && (int)(ptruePrev - szTrueName) ++ + (int)wcslen(fb.cFileName) < len)))) ++ { ++ wcscpy(ptruePrev, fb.cFileName); ++ break; ++ } ++ } ++ } ++ FindClose(hFind); ++ *porig = c; ++ ptrue = ptruePrev + wcslen(ptruePrev); ++ } ++ else if (hFind == INVALID_HANDLE_VALUE ++ && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) ++ return FAIL; ++ } ++ ++ wcscpy(name, szTrueName); ++ return OK; ++ } ++ #endif ++ + /* + * fname_case(): Set the case of the file name, if it already exists. + * When "len" is > 0, also expand short to long filenames. ++ * NOTE: much of this is identical to fname_casew(), keep in sync! + */ + void + fname_case( +*************** +*** 2520,2530 **** + int slen; + + flen = (int)STRLEN(name); +! if (flen == 0 || flen > _MAX_PATH) + return; + + slash_adjust(name); + + /* Build the new name in szTrueName[] one component at a time. */ + porig = name; + ptrue = szTrueName; +--- 2636,2679 ---- + int slen; + + flen = (int)STRLEN(name); +! if (flen == 0) + return; + + slash_adjust(name); + ++ #ifdef FEAT_MBYTE ++ if (enc_codepage >= 0 && (int)GetACP() != enc_codepage) ++ { ++ WCHAR *p = enc_to_utf16(name, NULL); ++ ++ if (p != NULL) ++ { ++ char_u *q; ++ WCHAR buf[_MAX_PATH + 2]; ++ ++ wcscpy(buf, p); ++ vim_free(p); ++ ++ if (fname_casew(buf, (len > 0) ? _MAX_PATH : 0) == OK) ++ { ++ q = utf16_to_enc(buf, NULL); ++ if (q != NULL) ++ { ++ vim_strncpy(name, q, (len > 0) ? len - 1 : flen); ++ vim_free(q); ++ return; ++ } ++ } ++ } ++ /* Retry with non-wide function (for Windows 98). */ ++ } ++ #endif ++ ++ /* If 'enc' is utf-8, flen can be larger than _MAX_PATH. ++ * So we should check this after calling wide function. */ ++ if (flen > _MAX_PATH) ++ return; ++ + /* Build the new name in szTrueName[] one component at a time. */ + porig = name; + ptrue = szTrueName; +*** ../vim-7.4.015/src/version.c 2013-08-30 17:11:29.000000000 +0200 +--- src/version.c 2013-08-30 17:15:06.000000000 +0200 +*************** +*** 740,741 **** +--- 740,743 ---- + { /* Add new patch number below this line */ ++ /**/ ++ 16, + /**/ + +-- +Fingers not found - Pound head on keyboard to continue. + + /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ +/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ +\\\ an exciting new programming language -- http://www.Zimbu.org /// + \\\ help me help AIDS victims -- http://ICCF-Holland.org ///