[CMD]: Use the CONUTILS library (Part 1/x) for an uniform and consistent experience...
authorHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Sun, 1 Oct 2017 16:30:39 +0000 (16:30 +0000)
committerHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Sun, 1 Oct 2017 16:30:39 +0000 (16:30 +0000)
- Make most of CMD use the conutils library. This means that
  now we explicitely use the CON_STREAM objects. In particular code
  handling STDIN/OUT/ERR redirection should be handled with care.
- Factor out much of console-related support code into console.c.
  Code for console input is however not "CON_STREAM-enabled" yet.
- Change ConOutPrintfPaging prototype to make it return TRUE/FALSE
  when it can continue paged-printing or not, respectively.
CORE-13860

svn path=/trunk/; revision=76023

14 files changed:
reactos/base/shell/cmd/CMakeLists.txt
reactos/base/shell/cmd/beep.c
reactos/base/shell/cmd/cls.c
reactos/base/shell/cmd/cmd.c
reactos/base/shell/cmd/cmd.h
reactos/base/shell/cmd/color.c
reactos/base/shell/cmd/console.c
reactos/base/shell/cmd/console.h
reactos/base/shell/cmd/dir.c
reactos/base/shell/cmd/history.c
reactos/base/shell/cmd/misc.c
reactos/base/shell/cmd/precomp.h
reactos/base/shell/cmd/redir.c
reactos/base/shell/cmd/start.c

index 553099d..64b25fa 100644 (file)
@@ -4,6 +4,7 @@ add_definitions(
     -D_DEBUG_MEM)
 
 include_directories(${REACTOS_SOURCE_DIR}/sdk/include/reactos/wine)
+include_directories(${REACTOS_SOURCE_DIR}/sdk/lib/conutils)
 
 list(APPEND SOURCE
     alias.c
@@ -68,8 +69,9 @@ list(APPEND SOURCE
 
 add_rc_deps(cmd.rc ${CMAKE_CURRENT_SOURCE_DIR}/res/terminal.ico)
 add_executable(cmd ${SOURCE} cmd.rc)
-target_link_libraries(cmd wine)
+add_pch(cmd precomp.h SOURCE)
 set_module_type(cmd win32cui UNICODE)
+target_link_libraries(cmd wine)
+target_link_libraries(cmd conutils ${PSEH_LIB})
 add_importlibs(cmd advapi32 user32 msvcrt kernel32 ntdll)
-add_pch(cmd precomp.h SOURCE)
 add_cd_file(TARGET cmd DESTINATION reactos/system32 FOR all)
index dc65bde..04959f5 100644 (file)
@@ -42,7 +42,7 @@ INT cmd_beep(LPTSTR param)
         return 1;
 #endif
 
-    ConRingBell(GetStdHandle(STD_OUTPUT_HANDLE));
+    ConRingBell(ConStreamGetOSHandle(StdOut));
     return 0;
 }
 
index 1e0f2c1..b21f4c2 100644 (file)
@@ -38,7 +38,7 @@ INT cmd_cls(LPTSTR param)
         return 0;
     }
 
-    ConClearScreen(GetStdHandle(STD_OUTPUT_HANDLE));
+    ConClearScreen(&StdOutScreen);
     return 0;
 }
 
index 13e3391..e6c9bec 100644 (file)
@@ -156,19 +156,23 @@ BOOL bIgnoreEcho = FALSE; /* Set this to TRUE to prevent a newline, when executi
 static BOOL bWaitForCommand = FALSE; /* When we are executing something passed on the commandline after /c or /k */
 INT  nErrorLevel = 0;     /* Errorlevel of last launched external program */
 CRITICAL_SECTION ChildProcessRunningLock;
-BOOL bUnicodeOutput = FALSE;
 BOOL bDisableBatchEcho = FALSE;
 BOOL bEnableExtensions = TRUE;
 BOOL bDelayedExpansion = FALSE;
 BOOL bTitleSet = FALSE;
 DWORD dwChildProcessId = 0;
-HANDLE hIn;
 LPTSTR lpOriginalEnvironment;
 HANDLE CMD_ModuleHandle;
 
 static NtQueryInformationProcessProc NtQueryInformationProcessPtr = NULL;
 static NtReadVirtualMemoryProc       NtReadVirtualMemoryPtr = NULL;
 
+/*
+ * Default output file stream translation mode is UTF8, but CMD switches
+ * allow to change it to either UTF16 (/U) or ANSI (/A).
+ */
+CON_STREAM_MODE OutputStreamMode = UTF8Text; // AnsiText;
+
 #ifdef INCLUDE_CMD_COLOR
 WORD wDefColor = 0;     /* Default color */
 #endif
@@ -417,7 +421,7 @@ Execute(LPTSTR Full, LPTSTR First, LPTSTR Rest, PARSED_COMMAND *Cmd)
         stui.wShowWindow = SW_SHOWDEFAULT;
 
         /* Set the console to standard mode */
-        SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE),
+        SetConsoleMode(ConStreamGetOSHandle(StdIn),
                        ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT);
 
         if (CreateProcess(szFullName,
@@ -468,15 +472,32 @@ Execute(LPTSTR Full, LPTSTR First, LPTSTR Rest, PARSED_COMMAND *Cmd)
         }
 
         /* Restore our default console mode */
-        SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE),
+        SetConsoleMode(ConStreamGetOSHandle(StdIn),
                        ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT);
-        SetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE),
+        SetConsoleMode(ConStreamGetOSHandle(StdOut),
                        ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT);
     }
 
-    /* Get code page if it has been changed */
-    InputCodePage= GetConsoleCP();
-    OutputCodePage = GetConsoleOutputCP();
+    /* Update our local codepage cache */
+    {
+        UINT uNewInputCodePage  = GetConsoleCP();
+        UINT uNewOutputCodePage = GetConsoleOutputCP();
+
+        if ((InputCodePage  != uNewInputCodePage) ||
+            (OutputCodePage != uNewOutputCodePage))
+        {
+            /* Update the locale as well */
+            InitLocale();
+        }
+
+        InputCodePage  = uNewInputCodePage;
+        OutputCodePage = uNewOutputCodePage;
+
+        /* Update the streams codepage cache as well */
+        ConStreamSetCacheCodePage(StdIn , InputCodePage );
+        ConStreamSetCacheCodePage(StdOut, OutputCodePage);
+        ConStreamSetCacheCodePage(StdErr, OutputCodePage);
+    }
 
     /* Restore the original console title */
     if (!bTitleSet)
@@ -1472,7 +1493,7 @@ BOOL WINAPI BreakHandler(DWORD dwCtrlType)
     rec.Event.KeyEvent.uChar.UnicodeChar = _T('C');
     rec.Event.KeyEvent.dwControlKeyState = RIGHT_CTRL_PRESSED;
 
-    WriteConsoleInput(hIn,
+    WriteConsoleInput(ConStreamGetOSHandle(StdIn),
                       &rec,
                       1,
                       &dwWritten);
@@ -1779,7 +1800,7 @@ Initialize(VOID)
     TCHAR ModuleName[_MAX_PATH + 1];
     INT nExitCode;
 
-    HANDLE hOut;
+    HANDLE hIn, hOut;
 
     TCHAR *ptr, *cmdLine, option = 0;
     BOOL AlwaysStrip = FALSE;
@@ -1805,10 +1826,6 @@ Initialize(VOID)
     /* Initialize our locale */
     InitLocale();
 
-    /* Get default input and output console handles */
-    hOut = GetStdHandle(STD_OUTPUT_HANDLE);
-    hIn  = GetStdHandle(STD_INPUT_HANDLE);
-
     /* Initialize prompt support */
     InitPrompt();
 
@@ -1833,6 +1850,8 @@ Initialize(VOID)
     AddBreakHandler();
 
     /* Set our default console mode */
+    hOut = ConStreamGetOSHandle(StdOut);
+    hIn  = ConStreamGetOSHandle(StdIn);
     SetConsoleMode(hOut, 0); // Reinitialize the console output mode
     SetConsoleMode(hOut, ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT);
     SetConsoleMode(hIn , ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT);
@@ -1871,7 +1890,7 @@ Initialize(VOID)
             }
             else if (option == _T('A'))
             {
-                bUnicodeOutput = FALSE;
+                OutputStreamMode = AnsiText;
             }
             else if (option == _T('C') || option == _T('K') || option == _T('R'))
             {
@@ -1899,7 +1918,7 @@ Initialize(VOID)
 #endif
             else if (option == _T('U'))
             {
-                bUnicodeOutput = TRUE;
+                OutputStreamMode = UTF16Text;
             }
             else if (option == _T('V'))
             {
@@ -1935,9 +1954,14 @@ Initialize(VOID)
     }
 
     if (wDefColor != 0)
-        ConSetScreenColor(GetStdHandle(STD_OUTPUT_HANDLE), wDefColor, TRUE);
+        ConSetScreenColor(ConStreamGetOSHandle(StdOut), wDefColor, TRUE);
 #endif
 
+    /* Reset the output Standard Streams translation modes and codepage caches */
+    // ConStreamSetMode(StdIn , OutputStreamMode, InputCodePage );
+    ConStreamSetMode(StdOut, OutputStreamMode, OutputCodePage);
+    ConStreamSetMode(StdErr, OutputStreamMode, OutputCodePage);
+
     if (!*ptr)
     {
         /* If neither /C or /K was given, display a simple version string */
@@ -2000,9 +2024,9 @@ static VOID Cleanup(VOID)
     RemoveBreakHandler();
 
     /* Restore the default console mode */
-    SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE),
+    SetConsoleMode(ConStreamGetOSHandle(StdIn),
                    ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT);
-    SetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE),
+    SetConsoleMode(ConStreamGetOSHandle(StdOut),
                    ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT);
 
     DeleteCriticalSection(&ChildProcessRunningLock);
@@ -2022,9 +2046,14 @@ int _tmain(int argc, const TCHAR *argv[])
     _tchdir(startPath);
 
     SetFileApisToOEM();
-    InputCodePage = GetConsoleCP();
+    InputCodePage  = GetConsoleCP();
     OutputCodePage = GetConsoleOutputCP();
 
+    /* Initialize the Console Standard Streams */
+    ConStreamInit(StdIn , GetStdHandle(STD_INPUT_HANDLE) , /*OutputStreamMode*/ AnsiText, InputCodePage);
+    ConStreamInit(StdOut, GetStdHandle(STD_OUTPUT_HANDLE), OutputStreamMode, OutputCodePage);
+    ConStreamInit(StdErr, GetStdHandle(STD_ERROR_HANDLE) , OutputStreamMode, OutputCodePage);
+
     CMD_ModuleHandle = GetModuleHandle(NULL);
 
     /* Perform general initialization, parse switches on command-line */
index 8dab4a7..80e13c3 100644 (file)
@@ -54,7 +54,6 @@ extern BOOL   bDisableBatchEcho;
 extern BOOL   bEnableExtensions;
 extern BOOL   bDelayedExpansion;
 extern INT    nErrorLevel;
-extern BOOL bUnicodeOutput;
 
 
 /* Prototypes for ALIAS.C */
@@ -282,7 +281,7 @@ VOID   GetPathCase(TCHAR *, TCHAR *);
 #define PROMPT_ALL   2
 #define PROMPT_BREAK 3
 
-INT PagePrompt (VOID);
+BOOL __stdcall PagePrompt(PCON_PAGER Pager, DWORD Done, DWORD Total);
 INT FilePromptYN (UINT);
 INT FilePromptYNA (UINT);
 
index 5ac01c2..12d9e7e 100644 (file)
@@ -46,7 +46,7 @@ INT CommandColor(LPTSTR rest)
     /* No parameter: Set the default colors */
     if (rest[0] == _T('\0'))
     {
-        ConSetScreenColor(GetStdHandle(STD_OUTPUT_HANDLE), wDefColor, TRUE);
+        ConSetScreenColor(ConStreamGetOSHandle(StdOut), wDefColor, TRUE);
         return 0;
     }
 
@@ -87,7 +87,7 @@ INT CommandColor(LPTSTR rest)
      * Set the chosen color. Use also the following advanced flag:
      * /-F to avoid changing already buffered foreground/background.
      */
-    if (ConSetScreenColor(GetStdHandle(STD_OUTPUT_HANDLE), wColor,
+    if (ConSetScreenColor(ConStreamGetOSHandle(StdOut), wColor,
                           !_tcsstr(rest, _T("/-F")) && !_tcsstr(rest, _T("/-f"))) == FALSE)
     {
         /* Failed because foreground and background colors were the same */
index 2514f03..45e6257 100644 (file)
 UINT InputCodePage;
 UINT OutputCodePage;
 
-
-BOOL IsConsoleHandle(HANDLE hHandle)
-{
-    DWORD dwMode;
-
-    /* Check whether the handle may be that of a console... */
-    if ((GetFileType(hHandle) & ~FILE_TYPE_REMOTE) != FILE_TYPE_CHAR)
-        return FALSE;
-
-    /*
-     * It may be. Perform another test... The idea comes from the
-     * MSDN description of the WriteConsole API:
-     *
-     * "WriteConsole fails if it is used with a standard handle
-     *  that is redirected to a file. If an application processes
-     *  multilingual output that can be redirected, determine whether
-     *  the output handle is a console handle (one method is to call
-     *  the GetConsoleMode function and check whether it succeeds).
-     *  If the handle is a console handle, call WriteConsole. If the
-     *  handle is not a console handle, the output is redirected and
-     *  you should call WriteFile to perform the I/O."
-     */
-    return GetConsoleMode(hHandle, &dwMode);
-}
+/* Global console Screen and Pager */
+CON_SCREEN StdOutScreen = INIT_CON_SCREEN(StdOut);
+CON_PAGER  StdOutPager  = INIT_CON_PAGER(&StdOutScreen);
 
 
 
@@ -90,9 +69,11 @@ VOID ConInKey(PINPUT_RECORD lpBuffer)
     do
     {
         ReadConsoleInput(hInput, lpBuffer, 1, &dwRead);
-        if ((lpBuffer->EventType == KEY_EVENT) &&
-            (lpBuffer->Event.KeyEvent.bKeyDown != FALSE))
+        if (lpBuffer->EventType == KEY_EVENT &&
+            lpBuffer->Event.KeyEvent.bKeyDown)
+        {
             break;
+        }
     }
     while (TRUE);
 }
@@ -139,306 +120,68 @@ VOID ConInString(LPTSTR lpInput, DWORD dwLength)
 
 /******************** Console STREAM OUT utility functions ********************/
 
-static VOID ConWrite(DWORD nStdHandle, TCHAR *str, DWORD len)
-{
-    DWORD dwNumBytes = 0;
-    HANDLE hOutput = GetStdHandle(nStdHandle);
-    PVOID p;
-
-    /* If we don't write anything, just return */
-    if (!str || len == 0)
-        return;
-
-    /* Check whether we are writing to a console and if so, write to it */
-    if (IsConsoleHandle(hOutput))
-    {
-        WriteConsole(hOutput, str, len, &dwNumBytes, NULL);
-        return;
-    }
-
-    /* We're writing to a file or pipe instead of the console. Convert the
-     * string from TCHARs to the desired output format, if the two differ */
-    if (bUnicodeOutput)
-    {
-#ifndef _UNICODE
-        WCHAR *buffer = cmd_alloc(len * sizeof(WCHAR));
-        if (!buffer)
-        {
-            error_out_of_memory();
-            return;
-        }
-        len = (DWORD)MultiByteToWideChar(OutputCodePage, 0, str, (INT)len, buffer, (INT)len);
-        str = (PVOID)buffer;
-#endif
-        /*
-         * Find any newline character in the buffer,
-         * write the part BEFORE the newline, then write
-         * a carriage-return + newline, and then write
-         * the remaining part of the buffer.
-         *
-         * This fixes output in files and serial console.
-         */
-        while (len > 0)
-        {
-            /* Loop until we find a \r or \n character */
-            // FIXME: What about the pair \r\n ?
-            p = str;
-            while (len > 0 && *(PWCHAR)p != L'\r' && *(PWCHAR)p != L'\n')
-            {
-                /* Advance one character */
-                p = (PVOID)((PWCHAR)p + 1);
-                len--;
-            }
-
-            /* Write everything up to \r or \n */
-            dwNumBytes = ((PWCHAR)p - (PWCHAR)str) * sizeof(WCHAR);
-            WriteFile(hOutput, str, dwNumBytes, &dwNumBytes, NULL);
-
-            /* If we hit \r or \n ... */
-            if (len > 0 && (*(PWCHAR)p == L'\r' || *(PWCHAR)p == L'\n'))
-            {
-                /* ... send a carriage-return + newline sequence and skip \r or \n */
-                WriteFile(hOutput, L"\r\n", 2 * sizeof(WCHAR), &dwNumBytes, NULL);
-                str = (PVOID)((PWCHAR)p + 1);
-                len--;
-            }
-        }
-
-#ifndef _UNICODE
-        cmd_free(buffer);
-#endif
-    }
-    else
-    {
-#ifdef _UNICODE
-        CHAR *buffer = cmd_alloc(len * MB_LEN_MAX * sizeof(CHAR));
-        if (!buffer)
-        {
-            error_out_of_memory();
-            return;
-        }
-        len = WideCharToMultiByte(OutputCodePage, 0, str, len, buffer, len * MB_LEN_MAX, NULL, NULL);
-        str = (PVOID)buffer;
-#endif
-        /*
-         * Find any newline character in the buffer,
-         * write the part BEFORE the newline, then write
-         * a carriage-return + newline, and then write
-         * the remaining part of the buffer.
-         *
-         * This fixes output in files and serial console.
-         */
-        while (len > 0)
-        {
-            /* Loop until we find a \r or \n character */
-            // FIXME: What about the pair \r\n ?
-            p = str;
-            while (len > 0 && *(PCHAR)p != '\r' && *(PCHAR)p != '\n')
-            {
-                /* Advance one character */
-                p = (PVOID)((PCHAR)p + 1);
-                len--;
-            }
-
-            /* Write everything up to \r or \n */
-            dwNumBytes = ((PCHAR)p - (PCHAR)str) * sizeof(CHAR);
-            WriteFile(hOutput, str, dwNumBytes, &dwNumBytes, NULL);
-
-            /* If we hit \r or \n ... */
-            if (len > 0 && (*(PCHAR)p == '\r' || *(PCHAR)p == '\n'))
-            {
-                /* ... send a carriage-return + newline sequence and skip \r or \n */
-                WriteFile(hOutput, "\r\n", 2, &dwNumBytes, NULL);
-                str = (PVOID)((PCHAR)p + 1);
-                len--;
-            }
-        }
-
-#ifdef _UNICODE
-        cmd_free(buffer);
-#endif
-    }
-}
-
-VOID ConPuts(DWORD nStdHandle, LPTSTR szText)
-{
-    ConWrite(nStdHandle, szText, (DWORD)_tcslen(szText));
-}
-
-VOID ConResPuts(DWORD nStdHandle, UINT resID)
-{
-    TCHAR szMsg[RC_STRING_MAX_SIZE];
-    LoadString(CMD_ModuleHandle, resID, szMsg, ARRAYSIZE(szMsg));
-    ConPuts(nStdHandle, szMsg);
-}
-
 VOID ConOutChar(TCHAR c)
 {
-    ConWrite(STD_OUTPUT_HANDLE, &c, 1);
+    ConWrite(StdOut, &c, 1);
 }
 
 VOID ConErrChar(TCHAR c)
 {
-    ConWrite(STD_ERROR_HANDLE, &c, 1);
-}
-
-VOID ConPrintfV(DWORD nStdHandle, LPTSTR szFormat, va_list arg_ptr)
-{
-    TCHAR szOut[OUTPUT_BUFFER_SIZE];
-    DWORD len;
-
-    len = (DWORD)_vstprintf(szOut, szFormat, arg_ptr);
-    ConWrite(nStdHandle, szOut, len);
-}
-
-VOID ConPrintf(DWORD nStdHandle, LPTSTR szFormat, ...)
-{
-    va_list arg_ptr;
-
-    va_start(arg_ptr, szFormat);
-    ConPrintfV(nStdHandle, szFormat, arg_ptr);
-    va_end(arg_ptr);
+    ConWrite(StdErr, &c, 1);
 }
 
-VOID ConResPrintf(DWORD nStdHandle, UINT resID, ...)
+VOID __cdecl ConFormatMessage(PCON_STREAM Stream, DWORD MessageId, ...)
 {
-    TCHAR szMsg[RC_STRING_MAX_SIZE];
-    va_list arg_ptr;
-
-    va_start(arg_ptr, resID);
-    LoadString(CMD_ModuleHandle, resID, szMsg, ARRAYSIZE(szMsg));
-    ConPrintfV(nStdHandle, szMsg, arg_ptr);
-    va_end(arg_ptr);
-}
-
-VOID ConFormatMessage(DWORD nStdHandle, DWORD MessageId, ...)
-{
-    DWORD ret;
-    LPTSTR text;
+    INT Len;
     va_list arg_ptr;
 
     va_start(arg_ptr, MessageId);
-    ret = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+    Len = ConMsgPrintfV(Stream,
+                        FORMAT_MESSAGE_FROM_SYSTEM,
                         NULL,
                         MessageId,
-                        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
-                        (LPTSTR)&text,
-                        0,
-                        &arg_ptr);
+                        LANG_USER_DEFAULT,
+                        arg_ptr);
     va_end(arg_ptr);
 
-    if (ret > 0)
-    {
-        ConPuts(nStdHandle, text);
-        LocalFree(text);
-    }
-    else
-    {
-        ConResPrintf(nStdHandle, STRING_CONSOLE_ERROR, MessageId);
-    }
+    if (Len <= 0)
+        ConResPrintf(Stream, STRING_CONSOLE_ERROR, MessageId);
 }
 
 
 
 /************************** Console PAGER functions ***************************/
 
-BOOL ConPrintfVPaging(DWORD nStdHandle, BOOL NewPage, LPTSTR szFormat, va_list arg_ptr)
+BOOL ConPrintfVPaging(PCON_PAGER Pager, BOOL StartPaging, LPTSTR szFormat, va_list arg_ptr)
 {
-    INT len;
-    CONSOLE_SCREEN_BUFFER_INFO csbi;
+    // INT len;
     TCHAR szOut[OUTPUT_BUFFER_SIZE];
-    DWORD dwWritten;
-    HANDLE hOutput = GetStdHandle(nStdHandle);
-
-    /* Used to count number of lines since last pause */
-    static int LineCount = 0;
 
-    /* Used to see how big the screen is */
-    int ScreenLines = 0;
-
-    /* Chars since start of line */
-    int CharSL;
-
-    int from = 0, i = 0;
-
-    if (NewPage != FALSE)
-        LineCount = 0;
-
-    /* Reset LineCount and return if no string has been given */
+    /* Return if no string has been given */
     if (szFormat == NULL)
         return TRUE;
 
-    /* Get the size of the visual screen that can be printed to */
-    if (!IsConsoleHandle(hOutput) || !GetConsoleScreenBufferInfo(hOutput, &csbi))
-    {
-        /* We assume it's a file handle */
-        ConPrintfV(nStdHandle, szFormat, arg_ptr);
-        return TRUE;
-    }
-
-    /*
-     * Get the number of lines currently displayed on screen, minus 1
-     * to account for the "press any key..." prompt from PagePrompt().
-     */
-    ScreenLines = (csbi.srWindow.Bottom - csbi.srWindow.Top);
-    CharSL = csbi.dwCursorPosition.X;
-
-    /* Make sure the user doesn't have the screen too small */
-    if (ScreenLines < 4)
-    {
-        ConPrintfV(nStdHandle, szFormat, arg_ptr);
-        return TRUE;
-    }
-
-    len = _vstprintf(szOut, szFormat, arg_ptr);
-
-    while (i < len)
-    {
-        /* Search until the end of a line is reached */
-        if (szOut[i++] != _T('\n') && ++CharSL < csbi.dwSize.X)
-            continue;
-
-        LineCount++;
-        CharSL=0;
-
-        if (LineCount >= ScreenLines)
-        {
-            WriteConsole(hOutput, &szOut[from], i-from, &dwWritten, NULL);
-            from = i;
-
-            /* Prompt the user */
-            if (PagePrompt() != PROMPT_YES)
-                return FALSE;
-
-            // TODO: Recalculate 'ScreenLines' in case the user redimensions
-            // the window during the prompt.
-
-            /* Reset the number of lines being printed */
-            LineCount = 0;
-        }
-    }
+    /*len =*/ _vstprintf(szOut, szFormat, arg_ptr);
 
-    WriteConsole(hOutput, &szOut[from], i-from, &dwWritten, NULL);
-
-    return TRUE;
+    // return ConPutsPaging(Pager, PagePrompt, StartPaging, szOut);
+    return ConWritePaging(Pager, PagePrompt, StartPaging,
+                          szOut, wcslen(szOut));
 }
 
-BOOL ConOutPrintfPaging(BOOL NewPage, LPTSTR szFormat, ...)
+BOOL __cdecl ConOutPrintfPaging(BOOL StartPaging, LPTSTR szFormat, ...)
 {
     BOOL bRet;
     va_list arg_ptr;
 
     va_start(arg_ptr, szFormat);
-    bRet = ConPrintfVPaging(STD_OUTPUT_HANDLE, NewPage, szFormat, arg_ptr);
+    bRet = ConPrintfVPaging(&StdOutPager, StartPaging, szFormat, arg_ptr);
     va_end(arg_ptr);
     return bRet;
 }
 
-VOID ConOutResPaging(BOOL NewPage, UINT resID)
+VOID ConOutResPaging(BOOL StartPaging, UINT resID)
 {
-    TCHAR szMsg[RC_STRING_MAX_SIZE];
-    LoadString(CMD_ModuleHandle, resID, szMsg, ARRAYSIZE(szMsg));
-    ConOutPrintfPaging(NewPage, szMsg);
+    ConResPaging(&StdOutPager, PagePrompt, StartPaging, resID);
 }
 
 
@@ -451,7 +194,7 @@ VOID SetCursorXY(SHORT x, SHORT y)
 
     coPos.X = x;
     coPos.Y = y;
-    SetConsoleCursorPosition(GetStdHandle (STD_OUTPUT_HANDLE), coPos);
+    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coPos);
 }
 
 VOID GetCursorXY(PSHORT x, PSHORT y)
@@ -487,7 +230,7 @@ VOID SetCursorType(BOOL bInsert, BOOL bVisible)
     cci.dwSize = bInsert ? 10 : 99;
     cci.bVisible = bVisible;
 
-    SetConsoleCursorInfo(GetStdHandle (STD_OUTPUT_HANDLE), &cci);
+    SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cci);
 }
 
 VOID GetScreenSize(PSHORT maxx, PSHORT maxy)
@@ -555,32 +298,6 @@ VOID ConRingBell(HANDLE hOutput)
 }
 #endif
 
-#ifdef INCLUDE_CMD_CLS
-VOID ConClearScreen(HANDLE hOutput)
-{
-    CONSOLE_SCREEN_BUFFER_INFO csbi;
-    COORD coPos;
-    DWORD dwWritten;
-
-    if (GetConsoleScreenBufferInfo(hOutput, &csbi))
-    {
-        coPos.X = 0;
-        coPos.Y = 0;
-        FillConsoleOutputAttribute(hOutput, csbi.wAttributes,
-                                   csbi.dwSize.X * csbi.dwSize.Y,
-                                   coPos, &dwWritten);
-        FillConsoleOutputCharacter(hOutput, _T(' '),
-                                   csbi.dwSize.X * csbi.dwSize.Y,
-                                   coPos, &dwWritten);
-        SetConsoleCursorPosition(hOutput, coPos);
-    }
-    else
-    {
-        ConOutChar(_T('\f'));
-    }
-}
-#endif
-
 #ifdef INCLUDE_CMD_COLOR
 BOOL ConSetScreenColor(HANDLE hOutput, WORD wColor, BOOL bFill)
 {
index 74a8e96..4452256 100644 (file)
@@ -1,10 +1,14 @@
 
 #pragma once
 
-/* Cache codepage */
+/* Cache codepage for text streams */
 extern UINT InputCodePage;
 extern UINT OutputCodePage;
 
+/* Global console Screen and Pager */
+extern CON_SCREEN StdOutScreen;
+extern CON_PAGER  StdOutPager;
+
 // /* Global variables */
 // extern BOOL   bCtrlBreak;
 // extern BOOL   bIgnoreEcho;
@@ -18,50 +22,45 @@ VOID ConInKey (PINPUT_RECORD);
 VOID ConInString (LPTSTR, DWORD);
 
 
-VOID ConOutChar (TCHAR);
-VOID ConErrChar (TCHAR);
-VOID ConPrintfV(DWORD, LPTSTR, va_list);
+VOID ConOutChar(TCHAR);
+VOID ConErrChar(TCHAR);
 
-VOID ConPuts(DWORD nStdHandle, LPTSTR szText);
-VOID ConPrintf(DWORD nStdHandle, LPTSTR szFormat, ...);
-VOID ConResPuts(DWORD nStdHandle, UINT resID);
-VOID ConResPrintf(DWORD nStdHandle, UINT resID, ...);
-VOID ConFormatMessage(DWORD nStdHandle, DWORD MessageId, ...);
+VOID __cdecl ConFormatMessage(PCON_STREAM Stream, DWORD MessageId, ...);
 
 #define ConOutPuts(szStr) \
-    ConPuts(STD_OUTPUT_HANDLE, (szStr))
+    ConPuts(StdOut, (szStr))
 
 #define ConErrPuts(szStr) \
-    ConPuts(STD_ERROR_HANDLE, (szStr))
+    ConPuts(StdErr, (szStr))
 
 #define ConOutResPuts(uID) \
-    ConResPuts(STD_OUTPUT_HANDLE, (uID))
+    ConResPuts(StdOut, (uID))
 
 #define ConErrResPuts(uID) \
-    ConResPuts(STD_ERROR_HANDLE, (uID))
+    ConResPuts(StdErr, (uID))
 
 #define ConOutPrintf(szStr, ...) \
-    ConPrintf(STD_OUTPUT_HANDLE, (szStr), ##__VA_ARGS__)
+    ConPrintf(StdOut, (szStr), ##__VA_ARGS__)
 
 #define ConErrPrintf(szStr, ...) \
-    ConPrintf(STD_ERROR_HANDLE, (szStr), ##__VA_ARGS__)
+    ConPrintf(StdErr, (szStr), ##__VA_ARGS__)
 
 #define ConOutResPrintf(uID, ...) \
-    ConResPrintf(STD_OUTPUT_HANDLE, (uID), ##__VA_ARGS__)
+    ConResPrintf(StdOut, (uID), ##__VA_ARGS__)
 
 #define ConErrResPrintf(uID, ...) \
-    ConResPrintf(STD_ERROR_HANDLE, (uID), ##__VA_ARGS__)
+    ConResPrintf(StdErr, (uID), ##__VA_ARGS__)
 
 #define ConOutFormatMessage(MessageId, ...) \
-    ConFormatMessage(STD_OUTPUT_HANDLE, (MessageId), ##__VA_ARGS__)
+    ConFormatMessage(StdOut, (MessageId), ##__VA_ARGS__)
 
 #define ConErrFormatMessage(MessageId, ...) \
-    ConFormatMessage(STD_ERROR_HANDLE, (MessageId), ##__VA_ARGS__)
+    ConFormatMessage(StdErr, (MessageId), ##__VA_ARGS__)
 
 
-BOOL ConPrintfVPaging(DWORD nStdHandle, BOOL, LPTSTR, va_list);
-BOOL ConOutPrintfPaging (BOOL NewPage, LPTSTR, ...);
-VOID ConOutResPaging(BOOL NewPage, UINT resID);
+BOOL ConPrintfVPaging(PCON_PAGER Pager, BOOL StartPaging, LPTSTR szFormat, va_list arg_ptr);
+BOOL __cdecl ConOutPrintfPaging(BOOL StartPaging, LPTSTR szFormat, ...);
+VOID ConOutResPaging(BOOL StartPaging, UINT resID);
 
 SHORT GetCursorX  (VOID);
 SHORT GetCursorY  (VOID);
@@ -83,10 +82,6 @@ BOOL ConSetTitle(IN LPCTSTR lpConsoleTitle);
 VOID ConRingBell(HANDLE hOutput);
 #endif
 
-#ifdef INCLUDE_CMD_CLS
-VOID ConClearScreen(HANDLE hOutput);
-#endif
-
 #ifdef INCLUDE_CMD_COLOR
 BOOL ConSetScreenColor(HANDLE hOutput, WORD wColor, BOOL bFill);
 #endif
@@ -99,6 +94,5 @@ BOOL ConSetScreenColor(HANDLE hOutput, WORD wColor, BOOL bFill);
 // #define PROMPT_ALL   2
 // #define PROMPT_BREAK 3
 
-// INT PagePrompt (VOID);
 // INT FilePromptYN (UINT);
 // INT FilePromptYNA (UINT);
index 2669a01..1d2cb35 100644 (file)
@@ -557,9 +557,9 @@ DirPrintf(LPDIRSWITCHFLAGS lpFlags, LPTSTR szFormat, ...)
     va_list arg_ptr;
     va_start(arg_ptr, szFormat);
     if (lpFlags->bPause)
-        Done = ConPrintfVPaging(STD_OUTPUT_HANDLE, FALSE, szFormat, arg_ptr);
+        Done = ConPrintfVPaging(&StdOutPager, FALSE, szFormat, arg_ptr);
     else
-        ConPrintfV(STD_OUTPUT_HANDLE, szFormat, arg_ptr);
+        ConPrintfV(StdOut, szFormat, arg_ptr);
     va_end(arg_ptr);
     return Done;
 }
index 347a7e1..f9354c2 100644 (file)
@@ -87,8 +87,6 @@ INT CommandHistory (LPTSTR param)
                 break;
 
             case _T('R'):/*read history from standard in*/
-                //hIn=GetStdHandle (STD_INPUT_HANDLE);
-
                 for(;;)
                 {
                     ConInString(szBuffer,sizeof(szBuffer)/sizeof(TCHAR));
index 6fe9dbc..d7d7af3 100644 (file)
@@ -534,7 +534,8 @@ BOOL FileGetString (HANDLE hFile, LPTSTR lpBuffer, INT nBufferLength)
     return TRUE;
 }
 
-INT PagePrompt(VOID)
+// See r874
+BOOL __stdcall PagePrompt(PCON_PAGER Pager, DWORD Done, DWORD Total)
 {
     SHORT iScreenWidth, iCursorY;
     INPUT_RECORD ir;
@@ -574,10 +575,10 @@ INT PagePrompt(VOID)
         ConOutChar(_T('\n'));
 
         bCtrlBreak = TRUE;
-        return PROMPT_BREAK;
+        return FALSE;
     }
 
-    return PROMPT_YES;
+    return TRUE;
 }
 
 
index 8f2af74..e73ecf3 100644 (file)
@@ -22,6 +22,8 @@
 #include <wincon.h>
 #include <shellapi.h>
 
+#include <conutils.h>
+
 #define NTOS_MODE_USER
 #include <ndk/rtlfuncs.h>
 
index f315a4f..50f573a 100644 (file)
 
 #ifdef FEATURE_REDIRECTION
 
-
-/* cmd allows redirection of handles numbered 3-9 even though these don't
- * correspond to any STD_ constant. */
-static HANDLE ExtraHandles[10 - 3];
+/*
+ * CMD allows redirection of handles numbered 3-9 even though
+ * these don't correspond to any STD_ constant.
+ */
+static const PCON_STREAM StdStreams[] = { StdIn, StdOut, StdErr };
+static HANDLE ExtraHandles[10 - 3]; // 3 == ARRAYSIZE(StdStreams)
 
 static HANDLE GetHandle(UINT Number)
 {
     if (Number < 3)
-        return GetStdHandle(STD_INPUT_HANDLE - Number);
+        return ConStreamGetOSHandle(StdStreams[Number]);
+        // return GetStdHandle(STD_INPUT_HANDLE - Number);
     else
         return ExtraHandles[Number - 3];
 }
@@ -45,9 +48,15 @@ static HANDLE GetHandle(UINT Number)
 static VOID SetHandle(UINT Number, HANDLE Handle)
 {
     if (Number < 3)
+    {
+        ConStreamSetOSHandle(StdStreams[Number], Handle);
+        /* Synchronize the associated Win32 handle */
         SetStdHandle(STD_INPUT_HANDLE - Number, Handle);
+    }
     else
+    {
         ExtraHandles[Number - 3] = Handle;
+    }
 }
 
 BOOL
index f13bd8e..5fe8307 100644 (file)
@@ -304,9 +304,26 @@ INT cmd_start (LPTSTR Rest)
         }
         CloseHandle (prci.hProcess);
 
-        /* Get New code page if it has change */
-        InputCodePage= GetConsoleCP();
-        OutputCodePage = GetConsoleOutputCP();
+        /* Update our local codepage cache */
+        {
+            UINT uNewInputCodePage  = GetConsoleCP();
+            UINT uNewOutputCodePage = GetConsoleOutputCP();
+
+            if ((InputCodePage  != uNewInputCodePage) ||
+                (OutputCodePage != uNewOutputCodePage))
+            {
+                /* Update the locale as well */
+                InitLocale();
+            }
+
+            InputCodePage  = uNewInputCodePage;
+            OutputCodePage = uNewOutputCodePage;
+
+            /* Update the streams codepage cache as well */
+            ConStreamSetCacheCodePage(StdIn , InputCodePage );
+            ConStreamSetCacheCodePage(StdOut, OutputCodePage);
+            ConStreamSetCacheCodePage(StdErr, OutputCodePage);
+        }
     }
     else
     {