From: Joe Souza jsouza@yahoo.com
--- programs/cmd/builtins.c | 64 +++++++++++++++++++++++++++++++++++++---- programs/cmd/wcmdmain.c | 4 +++ 2 files changed, 63 insertions(+), 5 deletions(-)
diff --git a/programs/cmd/builtins.c b/programs/cmd/builtins.c index b5ad78ab9c7..7e538dea745 100644 --- a/programs/cmd/builtins.c +++ b/programs/cmd/builtins.c @@ -36,6 +36,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(cmd);
extern int defaultColor; extern BOOL echo_mode; +extern HANDLE stdout_orig;
struct env_stack *pushd_directories; const WCHAR inbuilt[][10] = { @@ -3392,12 +3393,33 @@ RETURN_CODE WCMD_title(const WCHAR *args) return NO_ERROR; }
+/**************************************************************************** + * WCMD_convert_text + * + * Converts bytes to wide characters in the specified code page. + */ +static int WCMD_convert_text(UINT codepage, char *buffer, DWORD count, LPWSTR *outBuf) +{ + int numChars; + + numChars = MultiByteToWideChar(codepage, 0, buffer, count, NULL, 0); + if (numChars) { + *outBuf = xalloc(numChars * sizeof(WCHAR)); + if (*outBuf) { + numChars = MultiByteToWideChar(codepage, 0, buffer, count, *outBuf, numChars); + } else { + numChars = 0; + } + } + + return numChars; +} + /**************************************************************************** * WCMD_type * * Copy a file to standard output. */ - RETURN_CODE WCMD_type(WCHAR *args) { RETURN_CODE return_code; @@ -3417,9 +3439,12 @@ RETURN_CODE WCMD_type(WCHAR *args) while (argN) { WCHAR *thisArg = WCMD_parameter (args, argno++, &argN, FALSE, FALSE);
- HANDLE h; - WCHAR buffer[512]; + HANDLE h, hOut; + char buffer[1024]; DWORD count; + UINT output_CP; + BOOL input_is_console, output_is_console, output_redirected; + char *eof = NULL;
if (!argN) break;
@@ -3434,10 +3459,39 @@ RETURN_CODE WCMD_type(WCHAR *args) if (writeHeaders) { WCMD_output_stderr(L"\n%1\n\n\n", thisArg); } - while (WCMD_ReadFile(h, buffer, ARRAY_SIZE(buffer) - 1, &count)) { + + hOut = GetStdHandle(STD_OUTPUT_HANDLE); + output_redirected = (hOut != stdout_orig); + input_is_console = VerifyConsoleIoHandle(h); + output_is_console = VerifyConsoleIoHandle(hOut); + output_CP = GetConsoleOutputCP(); + + while (ReadFile(h, buffer, ARRAY_SIZE(buffer) - 1, &count, NULL)) { if (count == 0) break; /* ReadFile reports success on EOF! */ buffer[count] = 0; - WCMD_output_asis (buffer); + /* If input is console (i.e. TYPE con > foo) or output is not redirected + then TYPE terminates at the EOF character. */ + if (input_is_console || !output_redirected) { + eof = (char *)memchr((void *)buffer, '\x1A', count); + if (eof) { + count = (DWORD)(eof - buffer); + } + } + if (output_is_console && output_CP) { + /* Convert text for current output code page and write to the console. + We don't use WriteFile here because that writes raw bytes, not characters. */ + WCHAR *string; + count = WCMD_convert_text(output_CP, buffer, count, &string); + if (count) { + WriteConsoleW(hOut, string, count, &count, NULL); + free(string); + } + } else { + WriteFile(hOut, buffer, count, &count, NULL); + } + if (eof) { + break; + } } CloseHandle (h); } diff --git a/programs/cmd/wcmdmain.c b/programs/cmd/wcmdmain.c index 26c2be2e1c3..0218c60e7ee 100644 --- a/programs/cmd/wcmdmain.c +++ b/programs/cmd/wcmdmain.c @@ -61,6 +61,7 @@ BOOL delayedsubst = FALSE; /* The current delayed substitution setting */
int defaultColor = 7; BOOL echo_mode = TRUE; +HANDLE stdout_orig;
WCHAR anykey[100], version_string[100];
@@ -4302,6 +4303,9 @@ int __cdecl wmain (int argc, WCHAR *argvW[]) osv.dwOSVersionInfoSize = sizeof(osv); RtlGetVersion(&osv);
+ /* Remember the original STDOUT handle. */ + stdout_orig = GetStdHandle(STD_OUTPUT_HANDLE); + /* Pre initialize some messages */ lstrcpyW(anykey, WCMD_LoadMessage(WCMD_ANYKEY)); sprintf(osver, "%ld.%ld.%ld", osv.dwMajorVersion, osv.dwMinorVersion, osv.dwBuildNumber);