Created
February 13, 2019 11:25
-
-
Save k-takata/2d475c21afb1dae67ba2b86f2a8f1c66 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
commit 5897d165fab11f2fde07afe62cbc996895882bc3 | |
Author: K.Takata <[email protected]> | |
Date: Wed Feb 13 20:21:55 2019 +0900 | |
Simplify fname_case() | |
diff --git a/src/os_win32.c b/src/os_win32.c | |
index 10ca41881..ca4a22839 100644 | |
--- a/src/os_win32.c | |
+++ b/src/os_win32.c | |
@@ -2759,135 +2759,18 @@ mch_check_win( | |
} | |
-/* | |
- * 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 = INVALID_HANDLE_VALUE; | |
- 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); | |
- } | |
- } | |
- | |
- wcscpy(name, szTrueName); | |
- return OK; | |
-} | |
- | |
/* | |
* 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( | |
char_u *name, | |
int len) | |
{ | |
- char szTrueName[_MAX_PATH + 2]; | |
- char szTrueNameTemp[_MAX_PATH + 2]; | |
- char *ptrue, *ptruePrev; | |
- char *porig, *porigPrev; | |
- int flen; | |
- WIN32_FIND_DATA fb; | |
- HANDLE hFind; | |
- int c; | |
- int slen; | |
+ int flen; | |
+ WCHAR *p; | |
+ WCHAR buf[_MAX_PATH + 1]; | |
flen = (int)STRLEN(name); | |
if (flen == 0) | |
@@ -2895,126 +2778,21 @@ fname_case( | |
slash_adjust(name); | |
- 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 + 1]; | |
- | |
- wcsncpy(buf, p, _MAX_PATH); | |
- buf[_MAX_PATH] = L'\0'; | |
- 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; | |
- } | |
- } | |
- } | |
- return; | |
- } | |
- | |
- /* 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) | |
+ p = enc_to_utf16(name, NULL); | |
+ if (p == NULL) | |
return; | |
- /* Build the new name in szTrueName[] one component at a time. */ | |
- porig = (char *)name; | |
- ptrue = szTrueName; | |
- | |
- if (isalpha(porig[0]) && porig[1] == ':') | |
+ if (GetLongPathNameW(p, buf, _MAX_PATH)) | |
{ | |
- /* 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) | |
+ char_u *q = utf16_to_enc(buf, NULL); | |
+ if (q != NULL) | |
{ | |
- int l; | |
- | |
- if (enc_dbcs) | |
- { | |
- l = (*mb_ptr2len)((char_u *)porig); | |
- while (--l >= 0) | |
- *ptrue++ = *porig++; | |
- } | |
- else | |
- *ptrue++ = *porig++; | |
- } | |
- *ptrue = NUL; | |
- | |
- /* To avoid a slow failure append "\*" when searching a directory, | |
- * server or network share. */ | |
- STRCPY(szTrueNameTemp, szTrueName); | |
- slen = (int)strlen(szTrueNameTemp); | |
- if (*porig == psepc && slen + 2 < _MAX_PATH) | |
- STRCPY(szTrueNameTemp + slen, "\\*"); | |
- | |
- /* Skip "", "." and "..". */ | |
- if (ptrue > ptruePrev | |
- && (ptruePrev[0] != '.' | |
- || (ptruePrev[1] != NUL | |
- && (ptruePrev[1] != '.' || ptruePrev[2] != NUL))) | |
- && (hFind = FindFirstFile(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 (_stricoll(porigPrev, fb.cFileName) == 0 | |
- || (len > 0 | |
- && (_stricoll(porigPrev, fb.cAlternateFileName) == 0 | |
- && (int)(ptruePrev - szTrueName) | |
- + (int)strlen(fb.cFileName) < len))) | |
- { | |
- STRCPY(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 (FindNextFile(hFind, &fb)) | |
- { | |
- if (*fb.cAlternateFileName != NUL | |
- && (strcoll(porigPrev, fb.cFileName) == 0 | |
- || (len > 0 | |
- && (_stricoll(porigPrev, | |
- fb.cAlternateFileName) == 0 | |
- && (int)(ptruePrev - szTrueName) | |
- + (int)strlen(fb.cFileName) < len)))) | |
- { | |
- STRCPY(ptruePrev, fb.cFileName); | |
- break; | |
- } | |
- } | |
- } | |
- FindClose(hFind); | |
- *porig = c; | |
- ptrue = ptruePrev + strlen(ptruePrev); | |
+ if (len > 0 || flen >= (int)STRLEN(q)) | |
+ vim_strncpy(name, q, (len > 0) ? len - 1 : flen); | |
+ vim_free(q); | |
} | |
} | |
- | |
- STRCPY(name, szTrueName); | |
+ vim_free(p); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment