Module: wine Branch: master Commit: 8daef1649b242e26236df9c9cb1810750113bed2 URL: http://source.winehq.org/git/wine.git/?a=commit;h=8daef1649b242e26236df9c9cb...
Author: Akihiro Sagawa sagawa.aki@gmail.com Date: Sat Oct 20 01:02:24 2012 +0900
cmd: Properly handle multibyte characters in batch files.
---
programs/cmd/batch.c | 58 ++++++++++++++++++++++++++++++++++--------------- 1 files changed, 40 insertions(+), 18 deletions(-)
diff --git a/programs/cmd/batch.c b/programs/cmd/batch.c index bacb6cd..02d1fcf 100644 --- a/programs/cmd/batch.c +++ b/programs/cmd/batch.c @@ -234,31 +234,53 @@ WCHAR *WCMD_fgets(WCHAR *buf, DWORD noChars, HANDLE h) { DWORD charsRead; BOOL status; - LARGE_INTEGER filepos; DWORD i;
/* We can't use the native f* functions because of the filename syntax differences between DOS and Unix. Also need to lose the LF (or CRLF) from the line. */
if (!WCMD_is_console_handle(h)) { - /* Save current file position */ - filepos.QuadPart = 0; - SetFilePointerEx(h, filepos, &filepos, FILE_CURRENT); - } + LARGE_INTEGER filepos; + char *bufA; + UINT cp; + const char *p; + + cp = GetConsoleCP(); + bufA = HeapAlloc(GetProcessHeap(), 0, noChars); + if (!bufA) return NULL; + + /* Save current file position */ + filepos.QuadPart = 0; + SetFilePointerEx(h, filepos, &filepos, FILE_CURRENT); + + status = ReadFile(h, bufA, noChars, &charsRead, NULL); + if (!status || charsRead == 0) { + HeapFree(GetProcessHeap(), 0, bufA); + return NULL; + }
- status = WCMD_ReadFile(h, buf, noChars, &charsRead); - if (!status || charsRead == 0) return NULL; + /* Find first EOL */ + for (p = bufA; p < (bufA + charsRead); p = CharNextExA(cp, p, 0)) { + if (*p == '\n' || *p == '\r') + break; + }
- /* Find first EOL */ - for (i = 0; i < charsRead; i++) { - if (buf[i] == '\n' || buf[i] == '\r') - break; - } + /* Sets file pointer to the start of the next line, if any */ + filepos.QuadPart += p - bufA + 1 + (*p == '\r' ? 1 : 0); + SetFilePointerEx(h, filepos, NULL, FILE_BEGIN);
- if (!WCMD_is_console_handle(h) && i != charsRead) { - /* Sets file pointer to the start of the next line, if any */ - filepos.QuadPart += i + 1 + (buf[i] == '\r' ? 1 : 0); - SetFilePointerEx(h, filepos, NULL, FILE_BEGIN); + i = MultiByteToWideChar(cp, 0, bufA, p - bufA, buf, noChars); + HeapFree(GetProcessHeap(), 0, bufA); + } + else { + status = WCMD_ReadFile(h, buf, noChars, &charsRead); + if (!status || charsRead == 0) return NULL; + + /* Find first EOL */ + for (i = 0; i < charsRead; i++) { + if (buf[i] == '\n' || buf[i] == '\r') + break; + } }
/* Truncate at EOL (or end of buffer) */