Made cmd unicode compatible.
[reactos.git] / reactos / subsys / system / cmd / console.c
index 1d9c4bb..df3de99 100644 (file)
@@ -1,5 +1,4 @@
-/* $Id: console.c,v 1.1 2003/03/20 19:19:22 rcampbell Exp $
- *
+/*
  *  CONSOLE.C - console input/output functions.
  *
  *
@@ -7,43 +6,25 @@
  *
  *    20-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
  *        started
+ *
+ *    03-Apr-2005 (Magnus Olsen) <magnus@greatlord.com>)
+ *        Remove all hardcode string to En.rc
+ *
+ *    01-Jul-2005 (Brandon Turner) <turnerb7@msu.edu>)
+ *        Added ConPrintfPaging and ConOutPrintfPaging
  */
 
-#include "config.h"
 
-#include <windows.h>
-#include <tchar.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include <string.h>
 
-#include "cmd.h"
+#include <precomp.h>
+#include "resource.h"
 
 
 #define OUTPUT_BUFFER_SIZE  4096
 
 
-#ifdef _DEBUG
-VOID DebugPrintf (LPTSTR szFormat, ...)
-{
-       TCHAR szOut[OUTPUT_BUFFER_SIZE];
-       va_list arg_ptr;
-       DWORD dwWritten;
-
-       va_start (arg_ptr, szFormat);
-       _vstprintf (szOut, szFormat, arg_ptr);
-       va_end (arg_ptr);
-
-       WriteFile (GetStdHandle (STD_ERROR_HANDLE),
-                  szOut,
-                  _tcslen(szOut) * sizeof(TCHAR),
-                  &dwWritten,
-                  NULL);
-#if 0
-       OutputDebugString (szOut);
-#endif
-}
-#endif /* _DEBUG */
+UINT InputCodePage;
+UINT OutputCodePage;
 
 
 VOID ConInDisable (VOID)
@@ -76,9 +57,8 @@ VOID ConInDummy (VOID)
 
 #ifdef _DEBUG
        if (hInput == INVALID_HANDLE_VALUE)
-               DebugPrintf ("Invalid input handle!!!\n");
+               DebugPrintf (_T("Invalid input handle!!!\n"));
 #endif /* _DEBUG */
-
        ReadConsoleInput (hInput, &dummy, 1, &dwRead);
 }
 
@@ -95,7 +75,7 @@ VOID ConInKey (PINPUT_RECORD lpBuffer)
 
 #ifdef _DEBUG
        if (hInput == INVALID_HANDLE_VALUE)
-               DebugPrintf ("Invalid input handle!!!\n");
+               DebugPrintf (_T("Invalid input handle!!!\n"));
 #endif /* _DEBUG */
 
        do
@@ -118,15 +98,24 @@ VOID ConInString (LPTSTR lpInput, DWORD dwLength)
 
        LPTSTR p;
        DWORD  i;
+       PCHAR pBuf;
 
+#ifdef _UNICODE
+       pBuf = (PCHAR)malloc(dwLength);
+#else
+       pBuf = lpInput;
+#endif
        ZeroMemory (lpInput, dwLength * sizeof(TCHAR));
        hFile = GetStdHandle (STD_INPUT_HANDLE);
        GetConsoleMode (hFile, &dwOldMode);
 
        SetConsoleMode (hFile, ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT);
 
-       ReadFile (hFile, lpInput, dwLength, &dwRead, NULL);
+       ReadFile (hFile, (PVOID)pBuf, dwLength, &dwRead, NULL);
 
+#ifdef _UNICODE
+       MultiByteToWideChar(  InputCodePage, 0, pBuf, dwLength + 1, lpInput, dwLength + 1);
+#endif
        p = lpInput;
        for (i = 0; i < dwRead; i++, p++)
        {
@@ -137,103 +126,336 @@ VOID ConInString (LPTSTR lpInput, DWORD dwLength)
                }
        }
 
+#ifdef _UNICODE
+       free(pBuf);
+#endif
+
        SetConsoleMode (hFile, dwOldMode);
 }
 
+static VOID ConChar(TCHAR c, DWORD nStdHandle)
+{
+       DWORD dwWritten;
+       CHAR cc;
+#ifdef _UNICODE
+       CHAR as[2];
+       WCHAR ws[2];
+       ws[0] = c;
+       ws[1] = 0;
+       WideCharToMultiByte( OutputCodePage, 0, ws, 2, as, 2, NULL, NULL);
+       cc = as[0];
+#else
+       cc = c;
+#endif
+       WriteFile (GetStdHandle (nStdHandle),
+                  &cc,
+                  1,
+                  &dwWritten,
+                  NULL);
+}
 
 VOID ConOutChar (TCHAR c)
 {
-       DWORD dwWritten;
+       ConChar(c, STD_OUTPUT_HANDLE);
+}
 
-       WriteFile (GetStdHandle (STD_OUTPUT_HANDLE),
-                  &c,
-                  sizeof(TCHAR),
+VOID ConPuts(LPTSTR szText, DWORD nStdHandle)
+{
+       DWORD dwWritten;
+       PCHAR pBuf;
+       INT len;
+
+       len = _tcslen(szText);
+#ifdef _UNICODE
+       pBuf = malloc(len + 1);
+       len = WideCharToMultiByte( OutputCodePage, 0, szText, len + 1, pBuf, len + 1, NULL, NULL) - 1;
+#else
+       pBuf = szText;
+#endif
+       WriteFile (GetStdHandle (nStdHandle),
+                  pBuf,
+                  len,
+                  &dwWritten,
+                  NULL);
+       WriteFile (GetStdHandle (nStdHandle),
+                  "\n",
+                  1,
                   &dwWritten,
                   NULL);
+#ifdef UNICODE
+       free(pBuf);
+#endif
 }
 
+VOID ConOutResPaging(BOOL NewPage, UINT resID)
+{
+  TCHAR szMsg[RC_STRING_MAX_SIZE];
+  LoadString(CMD_ModuleHandle, resID, szMsg, RC_STRING_MAX_SIZE);
+  ConOutPrintfPaging(NewPage, szMsg);
+}
+
+VOID ConOutResPuts (UINT resID)
+{
+  TCHAR szMsg[RC_STRING_MAX_SIZE];
+  LoadString(CMD_ModuleHandle, resID, szMsg, RC_STRING_MAX_SIZE);
+
+  ConPuts(szMsg, STD_OUTPUT_HANDLE);
+}
 
 VOID ConOutPuts (LPTSTR szText)
 {
+       ConPuts(szText, STD_OUTPUT_HANDLE);
+}
+
+
+VOID ConPrintf(LPTSTR szFormat, va_list arg_ptr, DWORD nStdHandle)
+{
+       INT len;
+       PCHAR pBuf;
+       TCHAR szOut[OUTPUT_BUFFER_SIZE];
        DWORD dwWritten;
 
-       WriteFile (GetStdHandle (STD_OUTPUT_HANDLE),
-                  szText,
-                  _tcslen(szText) * sizeof(TCHAR),
-                  &dwWritten,
-                  NULL);
-       WriteFile (GetStdHandle (STD_OUTPUT_HANDLE),
-                  _T("\n"),
-                  sizeof(TCHAR),
+       len = _vstprintf (szOut, szFormat, arg_ptr);
+#ifdef _UNICODE
+       pBuf = malloc(len + 1);
+       len = WideCharToMultiByte( OutputCodePage, 0, szOut, len + 1, pBuf, len + 1, NULL, NULL) - 1;
+#else
+       pBuf = szOut;
+#endif
+
+       WriteFile (GetStdHandle (nStdHandle),
+                  pBuf,
+                  len,
                   &dwWritten,
                   NULL);
-}
 
 
-VOID ConOutPrintf (LPTSTR szFormat, ...)
+#ifdef UNICODE
+       free(pBuf);
+#endif
+}
+
+VOID ConPrintfPaging(BOOL NewPage, LPTSTR szFormat, va_list arg_ptr, DWORD nStdHandle)
 {
+       INT len;
+       PCHAR pBuf;
+       CONSOLE_SCREEN_BUFFER_INFO csbi;
        TCHAR szOut[OUTPUT_BUFFER_SIZE];
        DWORD dwWritten;
+  
+  /* used to count number of lines since last pause */
+       static int LineCount = 0;
+
+  /* used to see how big the screen is */
+       int ScreenLines = 0;  
+
+  /* the number of chars in a roow */
+       int ScreenCol = 0;  
+
+  /* chars since end of line */
+       int CharEL = 0; 
+  
+       int i = 0;
+
+       if(NewPage == TRUE)
+               LineCount = 0;
+
+  /* rest LineCount and return if no string have been given */
+        if (szFormat == NULL)
+                return;
+
+
+       //get the size of the visual screen that can be printed too
+       if (!GetConsoleScreenBufferInfo(hConsole, &csbi))
+        {
+                // we assuming its a file handle
+                ConPrintf(szFormat, arg_ptr, nStdHandle);
+                return;
+        }
+       //subtract 2 to account for "press any key..." and for the blank line at the end of PagePrompt()
+       ScreenLines = (csbi.srWindow.Bottom  - csbi.srWindow.Top) - 4;
+       ScreenCol = (csbi.srWindow.Right - csbi.srWindow.Left) + 1;
+
+       //make sure they didnt make the screen to small 
+       if(ScreenLines<4)
+        {
+               ConPrintf(szFormat, arg_ptr, nStdHandle);
+                return ;
+        }
+          
+       len = _vstprintf (szOut, szFormat, arg_ptr);
+#ifdef _UNICODE
+       pBuf = malloc(len + 1);
+       len = WideCharToMultiByte( OutputCodePage, 0, szOut, len + 1, pBuf, len + 1, NULL, NULL) - 1;
+#else
+       pBuf = szOut;
+#endif
+             
+       for(i = 0; i < len; i++)
+       { 
+      
+                if(pBuf[i] == '\n')
+               {                               
+                       LineCount++; 
+                        CharEL=0;
+               }      
+                else
+                {      
+                        CharEL++;           
+                        if (CharEL>=ScreenCol)
+                        {        
+                                if (i+1<len)
+                                {
+                                        if(pBuf[i+1] != '\n') LineCount++;          
+                                }
+                                CharEL=0;
+                        }
+                }
+
+                /* FIXME : write more that one char at time */
+                WriteFile (GetStdHandle (nStdHandle),&pBuf[i],sizeof(CHAR),&dwWritten,NULL);
+               if(LineCount >= ScreenLines)
+               {
+                        if(strnicmp(&pBuf[i], "\n", 2)!=0)
+                        WriteFile (GetStdHandle (nStdHandle),"\n",sizeof(CHAR),&dwWritten,NULL); 
+
+                       if(PagePrompt() != PROMPT_YES)
+                       {
+                               return;
+                       }
+                       //reset the number of lines being printed         
+                       LineCount = 0;
+                        CharEL=0;
+               }
+      
+       }
+
+#ifdef UNICODE
+       free(pBuf);
+#endif
+}
+
+VOID ConErrFormatMessage (DWORD MessageId, ...)
+{
+       TCHAR szMsg[RC_STRING_MAX_SIZE];
+       DWORD ret;
+       LPTSTR text;
        va_list arg_ptr;
 
-       va_start (arg_ptr, szFormat);
-       _vstprintf (szOut, szFormat, arg_ptr);
+       va_start (arg_ptr, MessageId);
+       ret = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+              NULL,
+              MessageId,
+              MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+              (LPTSTR) &text,
+              0,
+              &arg_ptr);
+
        va_end (arg_ptr);
+       if(ret > 0)
+       {
+               ConErrPuts (text);
+               LocalFree(text);
+       }
+       else
+       {
+               LoadString(CMD_ModuleHandle, STRING_CONSOLE_ERROR, szMsg, RC_STRING_MAX_SIZE);
+               ConErrPrintf(szMsg);
+       }
+}
 
-       WriteFile (GetStdHandle (STD_OUTPUT_HANDLE),
-                  szOut,
-                  _tcslen(szOut) * sizeof(TCHAR),
-                  &dwWritten,
-                  NULL);
+VOID ConOutFormatMessage (DWORD MessageId, ...)
+{
+       TCHAR szMsg[RC_STRING_MAX_SIZE];
+       DWORD ret;
+       LPTSTR text;
+       va_list arg_ptr;
+
+       va_start (arg_ptr, MessageId);
+       ret = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+              NULL,
+              MessageId,
+              MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+              (LPTSTR) &text,
+              0,
+              &arg_ptr);
+
+       va_end (arg_ptr);
+       if(ret > 0)
+       {
+               ConErrPuts (text);
+               LocalFree(text);
+       }
+       else
+       {
+               LoadString(CMD_ModuleHandle, STRING_CONSOLE_ERROR, szMsg, RC_STRING_MAX_SIZE);
+               ConErrPrintf(szMsg);
+       }
 }
 
+VOID ConOutPrintf (LPTSTR szFormat, ...)
+{
+       va_list arg_ptr;
 
-VOID ConErrChar (TCHAR c)
+       va_start (arg_ptr, szFormat);
+       ConPrintf(szFormat, arg_ptr, STD_OUTPUT_HANDLE);
+       va_end (arg_ptr);
+}
+
+VOID ConOutPrintfPaging (BOOL NewPage, LPTSTR szFormat, ...)
 {
-       DWORD dwWritten;
+       va_list arg_ptr;
 
-       WriteFile (GetStdHandle (STD_ERROR_HANDLE),
-                  &c,
-                  sizeof(TCHAR),
-                  &dwWritten,
-                  NULL);
+       va_start (arg_ptr, szFormat);
+       ConPrintfPaging(NewPage, szFormat, arg_ptr, STD_OUTPUT_HANDLE);
+       va_end (arg_ptr);
+}
+
+VOID ConErrChar (TCHAR c)
+{
+       ConChar(c, STD_ERROR_HANDLE);
 }
 
 
-VOID ConErrPuts (LPTSTR szText)
+VOID ConErrResPuts (UINT resID)
 {
-       DWORD dwWritten;
+       TCHAR szMsg[RC_STRING_MAX_SIZE];
+    LoadString(CMD_ModuleHandle, resID, szMsg, RC_STRING_MAX_SIZE);
+       ConPuts(szMsg, STD_ERROR_HANDLE);
+}
 
-       WriteFile (GetStdHandle (STD_ERROR_HANDLE),
-                  szText,
-                  _tcslen(szText) * sizeof(TCHAR),
-                  &dwWritten,
-                  NULL);
-       WriteFile (GetStdHandle (STD_ERROR_HANDLE),
-                  _T ("\n"),
-                  sizeof(TCHAR),
-                  &dwWritten,
-                  NULL);
+VOID ConErrPuts (LPTSTR szText)
+{
+       ConPuts(szText, STD_ERROR_HANDLE);
 }
 
 
 VOID ConErrPrintf (LPTSTR szFormat, ...)
 {
-       TCHAR szOut[OUTPUT_BUFFER_SIZE];
-       DWORD dwWritten;
        va_list arg_ptr;
 
        va_start (arg_ptr, szFormat);
-       _vstprintf (szOut, szFormat, arg_ptr);
+       ConPrintf(szFormat, arg_ptr, STD_ERROR_HANDLE);
        va_end (arg_ptr);
-
-       WriteFile (GetStdHandle (STD_ERROR_HANDLE),
-                  szOut,
-                  _tcslen(szOut) * sizeof(TCHAR),
-                  &dwWritten,
-                  NULL);
 }
 
+#ifdef _DEBUG
+VOID DebugPrintf (LPTSTR szFormat, ...)
+{
+       va_list arg_ptr;
+
+       va_start (arg_ptr, szFormat);
+       ConPrintf(szFormat, arg_ptr, STD_ERROR_HANDLE);
+       va_end (arg_ptr);
+#if 0
+       TCHAR szOut[OUTPUT_BUFFER_SIZE];
+       va_start (arg_ptr, szFormat);
+       _vstprintf (szOut, szFormat, arg_ptr);
+       OutputDebugString (szOut);
+       va_end (arg_ptr);
+#endif
+}
+#endif /* _DEBUG */
 
 VOID SetCursorXY (SHORT x, SHORT y)
 {
@@ -249,7 +471,7 @@ VOID GetCursorXY (PSHORT x, PSHORT y)
 {
        CONSOLE_SCREEN_BUFFER_INFO csbi;
 
-       GetConsoleScreenBufferInfo (GetStdHandle (STD_OUTPUT_HANDLE), &csbi);
+       GetConsoleScreenBufferInfo (hConsole, &csbi);
 
        *x = csbi.dwCursorPosition.X;
        *y = csbi.dwCursorPosition.Y;
@@ -260,7 +482,7 @@ SHORT GetCursorX (VOID)
 {
        CONSOLE_SCREEN_BUFFER_INFO csbi;
 
-       GetConsoleScreenBufferInfo (GetStdHandle (STD_OUTPUT_HANDLE), &csbi);
+       GetConsoleScreenBufferInfo (hConsole, &csbi);
 
        return csbi.dwCursorPosition.X;
 }
@@ -270,7 +492,7 @@ SHORT GetCursorY (VOID)
 {
        CONSOLE_SCREEN_BUFFER_INFO csbi;
 
-       GetConsoleScreenBufferInfo (GetStdHandle (STD_OUTPUT_HANDLE), &csbi);
+       GetConsoleScreenBufferInfo (hConsole, &csbi);
 
        return csbi.dwCursorPosition.Y;
 }
@@ -280,7 +502,7 @@ VOID GetScreenSize (PSHORT maxx, PSHORT maxy)
 {
        CONSOLE_SCREEN_BUFFER_INFO csbi;
 
-       GetConsoleScreenBufferInfo (GetStdHandle (STD_OUTPUT_HANDLE), &csbi);
+       GetConsoleScreenBufferInfo (hConsole, &csbi);
 
        if (maxx)
                *maxx = csbi.dwSize.X;