#define OUTPUT_BUFFER_SIZE 4096
-
+/* Cache codepage for text streams */
UINT InputCodePage;
UINT OutputCodePage;
return GetConsoleMode(hHandle, &dwMode);
}
+
+
+/********************* Console STREAM IN utility functions ********************/
+
VOID ConInDisable(VOID)
{
HANDLE hInput = GetStdHandle(STD_INPUT_HANDLE);
SetConsoleMode(hInput, dwMode);
}
-
VOID ConInEnable(VOID)
{
HANDLE hInput = GetStdHandle(STD_INPUT_HANDLE);
SetConsoleMode(hInput, dwMode);
}
-
-VOID ConInFlush (VOID)
+VOID ConInFlush(VOID)
{
FlushConsoleInputBuffer(GetStdHandle(STD_INPUT_HANDLE));
}
-
VOID ConInKey(PINPUT_RECORD lpBuffer)
{
HANDLE hInput = GetStdHandle(STD_INPUT_HANDLE);
while (TRUE);
}
-
VOID ConInString(LPTSTR lpInput, DWORD dwLength)
{
DWORD dwOldMode;
SetConsoleMode(hFile, dwOldMode);
}
-static VOID ConWrite(TCHAR *str, DWORD len, DWORD nStdHandle)
+
+
+/******************** Console STREAM OUT utility functions ********************/
+
+static VOID ConWrite(DWORD nStdHandle, TCHAR *str, DWORD len)
{
- DWORD dwWritten;
+ 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))
{
- if (WriteConsole(hOutput, str, len, &dwWritten, NULL))
- return;
+ WriteConsole(hOutput, str, len, &dwNumBytes, NULL);
+ return;
}
/* We're writing to a file or pipe instead of the console. Convert the
#endif
/*
* Find any newline character in the buffer,
- * send the part BEFORE the newline, then send
- * a carriage-return + newline, and then send
+ * 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 (str && *(PWCHAR)str && len > 0)
+ while (len > 0)
{
- p = wcspbrk((PWCHAR)str, L"\r\n");
- if (p)
+ /* 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')
{
- len -= ((PWCHAR)p - (PWCHAR)str) + 1;
- WriteFile(hOutput, str, ((PWCHAR)p - (PWCHAR)str) * sizeof(WCHAR), &dwWritten, NULL);
- WriteFile(hOutput, L"\r\n", 2 * sizeof(WCHAR), &dwWritten, NULL);
- str = (PVOID)((PWCHAR)p + 1);
+ /* Advance one character */
+ p = (PVOID)((PWCHAR)p + 1);
+ len--;
}
- else
+
+ /* 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'))
{
- WriteFile(hOutput, str, len * sizeof(WCHAR), &dwWritten, NULL);
- break;
+ /* ... 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--;
}
}
- // WriteFile(hOutput, str, len * sizeof(WCHAR), &dwWritten, NULL);
#ifndef _UNICODE
cmd_free(buffer);
#endif
#endif
/*
* Find any newline character in the buffer,
- * send the part BEFORE the newline, then send
- * a carriage-return + newline, and then send
+ * 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 (str && *(PCHAR)str && len > 0)
+ while (len > 0)
{
- p = strpbrk((PCHAR)str, "\r\n");
- if (p)
+ /* 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')
{
- len -= ((PCHAR)p - (PCHAR)str) + 1;
- WriteFile(hOutput, str, ((PCHAR)p - (PCHAR)str), &dwWritten, NULL);
- WriteFile(hOutput, "\r\n", 2, &dwWritten, NULL);
- str = (PVOID)((PCHAR)p + 1);
+ /* Advance one character */
+ p = (PVOID)((PCHAR)p + 1);
+ len--;
}
- else
+
+ /* 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'))
{
- WriteFile(hOutput, str, len, &dwWritten, NULL);
- break;
+ /* ... send a carriage-return + newline sequence and skip \r or \n */
+ WriteFile(hOutput, "\r\n", 2, &dwNumBytes, NULL);
+ str = (PVOID)((PCHAR)p + 1);
+ len--;
}
}
- // WriteFile(hOutput, str, len, &dwWritten, NULL);
#ifdef _UNICODE
cmd_free(buffer);
#endif
}
}
-VOID ConOutChar(TCHAR c)
-{
- ConWrite(&c, 1, STD_OUTPUT_HANDLE);
-}
-
-VOID ConPuts(LPTSTR szText, DWORD nStdHandle)
+VOID ConPuts(DWORD nStdHandle, LPTSTR szText)
{
- ConWrite(szText, (DWORD)_tcslen(szText), nStdHandle);
+ ConWrite(nStdHandle, szText, (DWORD)_tcslen(szText));
}
-VOID ConOutResPaging(BOOL NewPage, UINT resID)
+VOID ConResPuts(DWORD nStdHandle, UINT resID)
{
TCHAR szMsg[RC_STRING_MAX_SIZE];
LoadString(CMD_ModuleHandle, resID, szMsg, ARRAYSIZE(szMsg));
- ConOutPrintfPaging(NewPage, szMsg);
+ ConPuts(nStdHandle, szMsg);
}
-VOID ConOutResPuts(UINT resID)
+VOID ConOutChar(TCHAR c)
{
- TCHAR szMsg[RC_STRING_MAX_SIZE];
- LoadString(CMD_ModuleHandle, resID, szMsg, ARRAYSIZE(szMsg));
- ConPuts(szMsg, STD_OUTPUT_HANDLE);
+ ConWrite(STD_OUTPUT_HANDLE, &c, 1);
}
-VOID ConOutPuts(LPTSTR szText)
+VOID ConErrChar(TCHAR c)
{
- ConPuts(szText, STD_OUTPUT_HANDLE);
+ ConWrite(STD_ERROR_HANDLE, &c, 1);
}
-
-VOID ConPrintf(LPTSTR szFormat, va_list arg_ptr, DWORD nStdHandle)
+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(szOut, len, nStdHandle);
+ 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);
}
-INT ConPrintfPaging(BOOL NewPage, LPTSTR szFormat, va_list arg_ptr, DWORD nStdHandle)
+VOID ConResPrintf(DWORD nStdHandle, UINT resID, ...)
+{
+ 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;
+ 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)
+ {
+ ConPuts(nStdHandle, text);
+ LocalFree(text);
+ }
+ else
+ {
+ ConResPrintf(nStdHandle, STRING_CONSOLE_ERROR, MessageId);
+ }
+}
+
+
+
+/************************** Console PAGER functions ***************************/
+
+BOOL ConPrintfVPaging(DWORD nStdHandle, BOOL NewPage, LPTSTR szFormat, va_list arg_ptr)
{
INT len;
CONSOLE_SCREEN_BUFFER_INFO csbi;
DWORD dwWritten;
HANDLE hOutput = GetStdHandle(nStdHandle);
- /* used to count number of lines since last pause */
+ /* Used to count number of lines since last pause */
static int LineCount = 0;
- /* used to see how big the screen is */
+ /* Used to see how big the screen is */
int ScreenLines = 0;
- /* chars since start of line */
+ /* Chars since start of line */
int CharSL;
int from = 0, i = 0;
if (NewPage == TRUE)
LineCount = 0;
- /* rest LineCount and return if no string have been given */
+ /* Reset LineCount and return if no string has been given */
if (szFormat == NULL)
- return 0;
+ return TRUE;
- /* Get the size of the visual screen that can be printed too */
+ /* 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 */
- ConPrintf(szFormat, arg_ptr, nStdHandle);
- return 0;
+ ConPrintfV(nStdHandle, szFormat, arg_ptr);
+ return TRUE;
}
- /* 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;
+
+ /*
+ * 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 they didn't make the screen to small */
+ /* Make sure the user doesn't have the screen too small */
if (ScreenLines < 4)
{
- ConPrintf(szFormat, arg_ptr, nStdHandle);
- return 0;
+ ConPrintfV(nStdHandle, szFormat, arg_ptr);
+ return TRUE;
}
len = _vstprintf(szOut, szFormat, arg_ptr);
WriteConsole(hOutput, &szOut[from], i-from, &dwWritten, NULL);
from = i;
+ /* Prompt the user */
if (PagePrompt() != PROMPT_YES)
- {
- return 1;
- }
+ return FALSE;
+
+ // TODO: Recalculate 'ScreenLines' in case the user redimensions
+ // the window during the prompt.
+
/* Reset the number of lines being printed */
LineCount = 0;
}
WriteConsole(hOutput, &szOut[from], i-from, &dwWritten, NULL);
- return 0;
-}
-
-VOID ConErrFormatMessage(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, ARRAYSIZE(szMsg));
- ConErrPrintf(szMsg);
- }
-}
-
-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, ARRAYSIZE(szMsg));
- ConErrPrintf(szMsg);
- }
+ return TRUE;
}
-VOID ConOutResPrintf(UINT resID, ...)
+BOOL ConOutPrintfPaging(BOOL NewPage, LPTSTR szFormat, ...)
{
- TCHAR szMsg[RC_STRING_MAX_SIZE];
- va_list arg_ptr;
-
- va_start(arg_ptr, resID);
- LoadString(CMD_ModuleHandle, resID, szMsg, ARRAYSIZE(szMsg));
- ConPrintf(szMsg, arg_ptr, STD_OUTPUT_HANDLE);
- va_end(arg_ptr);
-}
-
-VOID ConOutPrintf(LPTSTR szFormat, ...)
-{
- va_list arg_ptr;
-
- va_start(arg_ptr, szFormat);
- ConPrintf(szFormat, arg_ptr, STD_OUTPUT_HANDLE);
- va_end(arg_ptr);
-}
-
-INT ConOutPrintfPaging(BOOL NewPage, LPTSTR szFormat, ...)
-{
- INT iReturn;
+ BOOL bRet;
va_list arg_ptr;
va_start(arg_ptr, szFormat);
- iReturn = ConPrintfPaging(NewPage, szFormat, arg_ptr, STD_OUTPUT_HANDLE);
+ bRet = ConPrintfVPaging(STD_OUTPUT_HANDLE, NewPage, szFormat, arg_ptr);
va_end(arg_ptr);
- return iReturn;
+ return bRet;
}
-VOID ConErrChar(TCHAR c)
-{
- ConWrite(&c, 1, STD_ERROR_HANDLE);
-}
-
-
-VOID ConErrResPuts(UINT resID)
-{
- TCHAR szMsg[RC_STRING_MAX_SIZE];
- LoadString(CMD_ModuleHandle, resID, szMsg, ARRAYSIZE(szMsg));
- ConPuts(szMsg, STD_ERROR_HANDLE);
-}
-
-VOID ConErrPuts(LPTSTR szText)
-{
- ConPuts(szText, STD_ERROR_HANDLE);
-}
-
-
-VOID ConErrResPrintf(UINT resID, ...)
+VOID ConOutResPaging(BOOL NewPage, UINT resID)
{
TCHAR szMsg[RC_STRING_MAX_SIZE];
- va_list arg_ptr;
-
- va_start(arg_ptr, resID);
LoadString(CMD_ModuleHandle, resID, szMsg, ARRAYSIZE(szMsg));
- ConPrintf(szMsg, arg_ptr, STD_ERROR_HANDLE);
- va_end(arg_ptr);
+ ConOutPrintfPaging(NewPage, szMsg);
}
-VOID ConErrPrintf(LPTSTR szFormat, ...)
-{
- va_list arg_ptr;
- va_start(arg_ptr, szFormat);
- ConPrintf(szFormat, arg_ptr, STD_ERROR_HANDLE);
- va_end(arg_ptr);
-}
+/************************** Console SCREEN functions **************************/
VOID SetCursorXY(SHORT x, SHORT y)
{
if (maxy) *maxy = csbi.dwSize.Y;
}
+
+
+
+BOOL ConSetTitle(IN LPCTSTR lpConsoleTitle)
+{
+ /* Now really set the console title */
+ return SetConsoleTitle(lpConsoleTitle);
+}
+
+#ifdef INCLUDE_CMD_BEEP
+VOID ConRingBell(HANDLE hOutput)
+{
+#if 0
+ /* Emit an error beep sound */
+ if (IsConsoleHandle(hOutput))
+ Beep(800, 200);
+ else if (IsTTYHandle(hOutput))
+ ConOutPuts(_T("\a")); // BEL character 0x07
+ else
+#endif
+ MessageBeep(-1);
+}
+#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)
+{
+ DWORD dwWritten;
+ CONSOLE_SCREEN_BUFFER_INFO csbi;
+ COORD coPos;
+
+ /* Foreground and Background colors can't be the same */
+ if ((wColor & 0x0F) == (wColor & 0xF0) >> 4)
+ return FALSE;
+
+ /* Fill the whole background if needed */
+ if (bFill)
+ {
+ GetConsoleScreenBufferInfo(hOutput, &csbi);
+
+ coPos.X = 0;
+ coPos.Y = 0;
+ FillConsoleOutputAttribute(hOutput,
+ wColor & 0x00FF,
+ csbi.dwSize.X * csbi.dwSize.Y,
+ coPos,
+ &dwWritten);
+ }
+
+ /* Set the text attribute */
+ SetConsoleTextAttribute(hOutput, wColor & 0x00FF);
+ return TRUE;
+}
+#endif
+
/* EOF */