openssh-portable/contrib/win32/win32compat/console.c

1562 lines
39 KiB
C
Raw Normal View History

2016-12-19 23:46:28 +01:00
/*
* Author: Microsoft Corp.
*
* Copyright (c) 2015 Microsoft Corp.
* All rights reserved
*
* Common library for Windows Console Screen IO.
* Contains Windows console related definition so that emulation code can draw
* on Windows console screen surface.
2016-12-19 23:46:28 +01:00
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <windows.h>
#include <conio.h>
#include "console.h"
2016-12-19 23:46:28 +01:00
#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x4
#endif
HANDLE hOutputConsole = NULL;
DWORD dwSavedAttributes = 0;
WORD wStartingAttributes = 0;
int ScreenX;
int ScreenY;
int ScrollTop;
int ScrollBottom;
int LastCursorX;
int LastCursorY;
BOOL isAnsiParsingRequired = FALSE;
2016-12-19 23:46:28 +01:00
char *pSavedScreen = NULL;
static COORD ZeroCoord = { 0,0 };
COORD SavedScreenSize = { 0,0 };
COORD SavedScreenCursor = { 0, 0 };
SMALL_RECT SavedViewRect = { 0,0,0,0 };
2016-12-19 23:46:28 +01:00
CONSOLE_SCREEN_BUFFER_INFOEX SavedWindowState;
BOOL isConHostParserEnabled = TRUE;
2016-12-19 23:46:28 +01:00
typedef struct _SCREEN_RECORD {
PCHAR_INFO pScreenBuf;
COORD ScreenSize;
COORD ScreenCursor;
SMALL_RECT srWindowRect;
}SCREEN_RECORD, *PSCREEN_RECORD;
2016-12-19 23:46:28 +01:00
PSCREEN_RECORD pSavedScreenRec = NULL;
int in_raw_mode = 0;
char *consoleTitle = "Microsoft openSSH client";
2016-12-19 23:46:28 +01:00
/* Used to enter the raw mode */
int
ConEnterRawMode(DWORD OutputHandle, BOOL fSmartInit)
2016-12-19 23:46:28 +01:00
{
OSVERSIONINFO os;
DWORD dwAttributes = 0;
DWORD dwRet = 0;
BOOL bRet = FALSE;
CONSOLE_SCREEN_BUFFER_INFO csbi;
static bool bFirstConInit = true;
os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&os);
hOutputConsole = GetStdHandle(OutputHandle);
if (hOutputConsole == INVALID_HANDLE_VALUE) {
dwRet = GetLastError();
error("GetStdHandle on OutputHandle failed with %d\n", dwRet);
return dwRet;
}
if (!GetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), &dwSavedAttributes)) {
dwRet = GetLastError();
error("GetConsoleMode on STD_INPUT_HANDLE failed with %d\n", dwRet);
return dwRet;
}
SetConsoleTitle(consoleTitle);
dwAttributes = dwSavedAttributes;
dwAttributes &= ~(ENABLE_LINE_INPUT |
ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT);
dwAttributes |= ENABLE_WINDOW_INPUT;
if (!SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), dwAttributes)) { /* Windows NT */
dwRet = GetLastError();
error("SetConsoleMode on STD_INPUT_HANDLE failed with %d\n", dwRet);
return dwRet;
}
if (!GetConsoleMode(hOutputConsole, &dwAttributes)) {
dwRet = GetLastError();
error("GetConsoleMode on hOutputConsole failed with %d\n", dwRet);
return dwRet;
}
dwAttributes |= (DWORD)ENABLE_VIRTUAL_TERMINAL_PROCESSING;
if (NULL != getenv("SSH_TERM_CONHOST_PARSER"))
isConHostParserEnabled = atoi(getenv("SSH_TERM_CONHOST_PARSER"));
/* We use our custom ANSI parser when
* a) User sets the environment variable "SSH_TERM_CONHOST_PARSER" to 0
* b) or when the console doesn't have the inbuilt capability to parse the ANSI/Xterm raw buffer.
*/
if (FALSE == isConHostParserEnabled || !SetConsoleMode(hOutputConsole, dwAttributes)) /* Windows NT */
isAnsiParsingRequired = TRUE;
GetConsoleScreenBufferInfo(hOutputConsole, &csbi);
/* if we are passing rawbuffer to console then we need to move the cursor to top
* so that the clearscreen will not erase any lines.
*/
if (TRUE == isAnsiParsingRequired) {
SavedViewRect = csbi.srWindow;
debug("console doesn't support the ansi parsing");
} else {
ConMoveCurosorTop(csbi);
debug("console supports the ansi parsing");
}
ConSetScreenX();
ConSetScreenY();
ScrollTop = 0;
ScrollBottom = ConVisibleWindowHeight();
in_raw_mode = 1;
return 0;
2016-12-19 23:46:28 +01:00
}
/* Used to Uninitialize the Console */
int
ConExitRawMode()
2016-12-19 23:46:28 +01:00
{
CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
in_raw_mode = 0;
if (hOutputConsole == NULL || !GetConsoleScreenBufferInfo(hOutputConsole, &consoleInfo))
return 0;
SetConsoleMode(hOutputConsole, dwSavedAttributes);
2016-12-19 23:46:28 +01:00
return 0;
2016-12-19 23:46:28 +01:00
}
/* Used to exit the raw mode */
int
ConUnInitWithRestore()
2016-12-19 23:46:28 +01:00
{
DWORD dwWritten;
COORD Coord;
CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
if (hOutputConsole == NULL)
return 0;
if (!GetConsoleScreenBufferInfo(hOutputConsole, &consoleInfo))
return 0;
SetConsoleMode(hOutputConsole, dwSavedAttributes);
Coord = consoleInfo.dwCursorPosition;
Coord.X = 0;
DWORD dwNumChar = (consoleInfo.dwSize.Y - consoleInfo.dwCursorPosition.Y) * consoleInfo.dwSize.X;
FillConsoleOutputCharacter(hOutputConsole, ' ', dwNumChar, Coord, &dwWritten);
FillConsoleOutputAttribute(hOutputConsole, wStartingAttributes, dwNumChar, Coord, &dwWritten);
SetConsoleTextAttribute(hOutputConsole, wStartingAttributes);
return 0;
2016-12-19 23:46:28 +01:00
}
BOOL
ConSetScreenRect(int xSize, int ySize)
2016-12-19 23:46:28 +01:00
{
BOOL bSuccess = TRUE;
CONSOLE_SCREEN_BUFFER_INFO csbi; /* hold current console buffer info */
SMALL_RECT srWindowRect; /* hold the new console size */
COORD coordScreen;
bSuccess = GetConsoleScreenBufferInfo(hOutputConsole, &csbi);
if (!bSuccess)
return bSuccess;
/* get the largest size we can size the console window to */
coordScreen = GetLargestConsoleWindowSize(hOutputConsole);
/* define the new console window size and scroll position */
srWindowRect.Top = csbi.srWindow.Top;
srWindowRect.Left = csbi.srWindow.Left;
srWindowRect.Right = xSize - 1 + srWindowRect.Left;
srWindowRect.Bottom = ySize - 1 + srWindowRect.Top;
/* define the new console buffer size */
coordScreen.X = max(csbi.dwSize.X, xSize);
coordScreen.Y = max(csbi.dwSize.Y, ySize);
/* if the current buffer is larger than what we want, resize the */
/* console window first, then the buffer */
if (csbi.dwSize.X < coordScreen.X || csbi.dwSize.Y < coordScreen.Y) {
bSuccess = SetConsoleScreenBufferSize(hOutputConsole, coordScreen);
if (bSuccess)
bSuccess = SetConsoleWindowInfo(hOutputConsole, TRUE, &srWindowRect);
} else {
bSuccess = SetConsoleWindowInfo(hOutputConsole, TRUE, &srWindowRect);
if (bSuccess)
bSuccess = SetConsoleScreenBufferSize(hOutputConsole, coordScreen);
}
if (bSuccess)
ConSaveViewRect();
/* if the current buffer *is* the size we want, don't do anything! */
return bSuccess;
2016-12-19 23:46:28 +01:00
}
BOOL
ConSetScreenSize(int xSize, int ySize)
2016-12-19 23:46:28 +01:00
{
BOOL bSuccess = TRUE;
CONSOLE_SCREEN_BUFFER_INFO csbi; /* hold current console buffer info */
SMALL_RECT srWindowRect; /* hold the new console size */
COORD coordScreen;
bSuccess = GetConsoleScreenBufferInfo(hOutputConsole, &csbi);
if (!bSuccess)
return bSuccess;
/* get the largest size we can size the console window to */
coordScreen = GetLargestConsoleWindowSize(hOutputConsole);
/* define the new console window size and scroll position */
srWindowRect.Right = (SHORT)(min(xSize, coordScreen.X) - 1);
srWindowRect.Bottom = (SHORT)(min(ySize, coordScreen.Y) - 1);
srWindowRect.Left = srWindowRect.Top = (SHORT)0;
/* define the new console buffer size */
coordScreen.X = xSize;
coordScreen.Y = ySize;
/* if the current buffer is larger than what we want, resize the */
/* console window first, then the buffer */
if ((DWORD)csbi.dwSize.X * csbi.dwSize.Y > (DWORD)xSize * ySize) {
bSuccess = SetConsoleWindowInfo(hOutputConsole, TRUE, &srWindowRect);
if (bSuccess)
bSuccess = SetConsoleScreenBufferSize(hOutputConsole, coordScreen);
}
/* if the current buffer is smaller than what we want, resize the */
/* buffer first, then the console window */
if ((DWORD)csbi.dwSize.X * csbi.dwSize.Y < (DWORD)xSize * ySize) {
bSuccess = SetConsoleScreenBufferSize(hOutputConsole, coordScreen);
if (bSuccess)
bSuccess = SetConsoleWindowInfo(hOutputConsole, TRUE, &srWindowRect);
}
if (bSuccess)
ConSaveViewRect();
/* if the current buffer *is* the size we want, don't do anything! */
return bSuccess;
2016-12-19 23:46:28 +01:00
}
/* Used to set the Color of the console and other attributes */
void
ConSetAttribute(int *iParam, int iParamCount)
2016-12-19 23:46:28 +01:00
{
static int iAttr = 0;
int i = 0;
BOOL bRet = TRUE;
if (iParamCount < 1) {
iAttr |= FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
iAttr = iAttr & ~BACKGROUND_INTENSITY;
iAttr = iAttr & ~FOREGROUND_INTENSITY;
iAttr = iAttr & ~COMMON_LVB_UNDERSCORE;
iAttr = iAttr & ~COMMON_LVB_REVERSE_VIDEO;
SetConsoleTextAttribute(hOutputConsole, (WORD)iAttr);
} else {
for (i = 0; i < iParamCount; i++) {
switch (iParam[i]) {
case ANSI_ATTR_RESET:
iAttr |= FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
iAttr = iAttr & ~BACKGROUND_RED;
iAttr = iAttr & ~BACKGROUND_BLUE;
iAttr = iAttr & ~BACKGROUND_GREEN;
iAttr = iAttr & ~BACKGROUND_INTENSITY;
iAttr = iAttr & ~FOREGROUND_INTENSITY;
iAttr = iAttr & ~COMMON_LVB_UNDERSCORE;
iAttr = iAttr & ~COMMON_LVB_REVERSE_VIDEO;
break;
case ANSI_BRIGHT:
iAttr |= FOREGROUND_INTENSITY;
break;
case ANSI_DIM:
break;
case ANSI_NOUNDERSCORE:
iAttr = iAttr & ~COMMON_LVB_UNDERSCORE;
break;
case ANSI_UNDERSCORE:
iAttr |= COMMON_LVB_UNDERSCORE;
break;
case ANSI_BLINK:
break;
case ANSI_REVERSE:
iAttr |= COMMON_LVB_REVERSE_VIDEO;
break;
case ANSI_HIDDEN:
break;
case ANSI_NOREVERSE:
iAttr = iAttr & ~COMMON_LVB_REVERSE_VIDEO;
break;
case ANSI_DEFAULT_FOREGROUND:
/* White */
iAttr |= FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
break;
case ANSI_FOREGROUND_BLACK:
iAttr = iAttr & ~FOREGROUND_RED;
iAttr = iAttr & ~FOREGROUND_BLUE;
iAttr = iAttr & ~FOREGROUND_GREEN;
iAttr |= 0;
break;
case ANSI_FOREGROUND_RED:
iAttr = iAttr & ~FOREGROUND_GREEN;
iAttr = iAttr & ~FOREGROUND_BLUE;
iAttr |= FOREGROUND_RED;
break;
case ANSI_FOREGROUND_GREEN:
iAttr = iAttr & ~FOREGROUND_BLUE;
iAttr = iAttr & ~FOREGROUND_RED;
iAttr |= FOREGROUND_GREEN;
break;
case ANSI_FOREGROUND_YELLOW:
iAttr = iAttr & ~FOREGROUND_BLUE;
iAttr |= FOREGROUND_RED | FOREGROUND_GREEN;
break;
case ANSI_FOREGROUND_BLUE:
iAttr = iAttr & ~FOREGROUND_GREEN;
iAttr = iAttr & ~FOREGROUND_RED;
iAttr |= FOREGROUND_BLUE;
break;
case ANSI_FOREGROUND_MAGENTA:
iAttr = iAttr & ~FOREGROUND_GREEN;
iAttr |= FOREGROUND_BLUE | FOREGROUND_RED;
break;
case ANSI_FOREGROUND_CYAN:
iAttr = iAttr & ~FOREGROUND_RED;
iAttr |= FOREGROUND_BLUE | FOREGROUND_GREEN;
break;
case ANSI_FOREGROUND_WHITE:
iAttr |= FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_GREEN;
break;
case ANSI_DEFAULT_BACKGROUND:
/* Black */
iAttr = iAttr & ~BACKGROUND_RED;
iAttr = iAttr & ~BACKGROUND_BLUE;
iAttr = iAttr & ~BACKGROUND_GREEN;
iAttr |= 0;
break;
case ANSI_BACKGROUND_BLACK:
iAttr = iAttr & ~BACKGROUND_RED;
iAttr = iAttr & ~BACKGROUND_BLUE;
iAttr = iAttr & ~BACKGROUND_GREEN;
iAttr |= 0;
break;
case ANSI_BACKGROUND_RED:
iAttr = iAttr & ~BACKGROUND_GREEN;
iAttr = iAttr & ~BACKGROUND_BLUE;
iAttr |= BACKGROUND_RED;
break;
case ANSI_BACKGROUND_GREEN:
iAttr = iAttr & ~BACKGROUND_RED;
iAttr = iAttr & ~BACKGROUND_BLUE;
iAttr |= BACKGROUND_GREEN;
break;
case ANSI_BACKGROUND_YELLOW:
iAttr = iAttr & ~BACKGROUND_BLUE;
iAttr |= BACKGROUND_RED | BACKGROUND_GREEN;
break;
case ANSI_BACKGROUND_BLUE:
iAttr = iAttr & ~BACKGROUND_GREEN;
iAttr = iAttr & ~BACKGROUND_RED;
iAttr |= BACKGROUND_BLUE;
break;
case ANSI_BACKGROUND_MAGENTA:
iAttr = iAttr & ~BACKGROUND_GREEN;
iAttr |= BACKGROUND_BLUE | BACKGROUND_RED;
break;
case ANSI_BACKGROUND_CYAN:
iAttr = iAttr & ~BACKGROUND_RED;
iAttr |= BACKGROUND_BLUE | BACKGROUND_GREEN;
break;
case ANSI_BACKGROUND_WHITE:
iAttr |= BACKGROUND_BLUE | BACKGROUND_RED | BACKGROUND_GREEN;
break;
case ANSI_BACKGROUND_BRIGHT:
iAttr |= BACKGROUND_INTENSITY;
break;
default:
continue;
}
}
if (iAttr)
bRet = SetConsoleTextAttribute(hOutputConsole, (WORD)iAttr);
}
}
/* Returns the width of current screen */
int
ConScreenSizeX()
2016-12-19 23:46:28 +01:00
{
CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
2016-12-19 23:46:28 +01:00
if (!GetConsoleScreenBufferInfo(hOutputConsole, &consoleInfo))
return (-1);
2016-12-19 23:46:28 +01:00
return (consoleInfo.dwSize.X);
2016-12-19 23:46:28 +01:00
}
/* Sets the width of the screen */
int
ConSetScreenX()
2016-12-19 23:46:28 +01:00
{
CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
2016-12-19 23:46:28 +01:00
if (!GetConsoleScreenBufferInfo(hOutputConsole, &consoleInfo))
return (-1);
ScreenX = (consoleInfo.dwSize.X);
return 0;
2016-12-19 23:46:28 +01:00
}
/* returns actual size of screen buffer */
int
ConScreenSizeY()
2016-12-19 23:46:28 +01:00
{
CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
2016-12-19 23:46:28 +01:00
if (!GetConsoleScreenBufferInfo(hOutputConsole, &consoleInfo))
return (-1);
2016-12-19 23:46:28 +01:00
return (consoleInfo.srWindow.Bottom - consoleInfo.srWindow.Top + 1);
2016-12-19 23:46:28 +01:00
}
/* returns width of visible window */
int
ConVisibleWindowWidth()
2016-12-19 23:46:28 +01:00
{
CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
if (!GetConsoleScreenBufferInfo(hOutputConsole, &consoleInfo))
return (-1);
2016-12-19 23:46:28 +01:00
return (consoleInfo.srWindow.Right - consoleInfo.srWindow.Left + 1);
2016-12-19 23:46:28 +01:00
}
/* returns height of visible window */
int
ConVisibleWindowHeight()
2016-12-19 23:46:28 +01:00
{
CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
2016-12-19 23:46:28 +01:00
if (!GetConsoleScreenBufferInfo(hOutputConsole, &consoleInfo))
return (-1);
return (consoleInfo.srWindow.Bottom - consoleInfo.srWindow.Top + 1);
2016-12-19 23:46:28 +01:00
}
int
ConSetScreenY()
2016-12-19 23:46:28 +01:00
{
CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
2016-12-19 23:46:28 +01:00
if (!GetConsoleScreenBufferInfo(hOutputConsole, &consoleInfo))
return (-1);
2016-12-19 23:46:28 +01:00
ScreenY = consoleInfo.dwSize.Y - 1;
2016-12-19 23:46:28 +01:00
return 0;
2016-12-19 23:46:28 +01:00
}
void
ConFillToEndOfLine()
2016-12-19 23:46:28 +01:00
{
DWORD rc = 0;
2016-12-19 23:46:28 +01:00
int size = ConScreenSizeX();
for (int i = ConGetCursorX(); i < size; i++)
WriteConsole(hOutputConsole, (char *)" ", 1, &rc, 0);
2016-12-19 23:46:28 +01:00
}
int
ConWriteString(char* pszString, int cbString)
2016-12-19 23:46:28 +01:00
{
DWORD Result = 0;
int needed = 0;
int cnt = 0;
wchar_t* utf16 = NULL;
if ((needed = MultiByteToWideChar(CP_UTF8, 0, pszString, cbString, NULL, 0)) == 0 ||
(utf16 = malloc(needed * sizeof(wchar_t))) == NULL ||
(cnt = MultiByteToWideChar(CP_UTF8, 0, pszString, cbString, utf16, needed)) == 0) {
Result = (DWORD)printf(pszString);
} else {
if (hOutputConsole)
WriteConsoleW(hOutputConsole, utf16, cnt, &Result, 0);
else
Result = (DWORD)wprintf(utf16);
}
if (utf16)
free(utf16);
return cbString;
2016-12-19 23:46:28 +01:00
}
int
ConTranslateAndWriteString(char* pszString, int cbString)
2016-12-19 23:46:28 +01:00
{
DWORD Result = 0;
2016-12-19 23:46:28 +01:00
if (hOutputConsole)
WriteConsole(hOutputConsole, pszString, cbString, &Result, 0);
else
Result = (DWORD)printf(pszString);
2016-12-19 23:46:28 +01:00
return Result;
2016-12-19 23:46:28 +01:00
}
BOOL
ConWriteChar(CHAR ch)
2016-12-19 23:46:28 +01:00
{
int X, Y, Result;
BOOL fOkay = TRUE;
Y = ConGetCursorY();
X = ConGetCursorX();
switch (ch) {
case 0x8: /* BackSpace */
if (X == 0) {
ConSetCursorPosition(ScreenX - 1, --Y);
WriteConsole(hOutputConsole, " ", 1, (LPDWORD)&Result, 0);
ConSetCursorPosition(ScreenX - 1, Y);
} else {
ConSetCursorPosition(X - 1, Y);
WriteConsole(hOutputConsole, " ", 1, (LPDWORD)&Result, 0);
ConSetCursorPosition(X - 1, Y);
}
break;
case '\r':
ConSetCursorPosition(0, Y);
break;
case '\n':
Y++;
if (Y > ScrollBottom - 1) {
ConScrollDown(ScrollTop, ScrollBottom);
ConSetCursorPosition(0, ScrollBottom);
} else
ConSetCursorPosition(0, Y);
break;
default:
fOkay = (BOOL)WriteConsole(hOutputConsole, &ch, 1, (LPDWORD)&Result, 0);
/* last coord */
if (X >= ScreenX - 1) {
if (Y >= ScrollBottom - 1) { /* last coord */
ConScrollDown(ScrollTop, ScrollBottom);
ConMoveCursorPosition(-ConGetCursorX(), 0);
} else
ConMoveCursorPosition(-ConGetCursorX(), 1);
}
break;
}
return fOkay;
2016-12-19 23:46:28 +01:00
}
BOOL
ConWriteCharW(WCHAR ch)
2016-12-19 23:46:28 +01:00
{
int X, Y, Result;
BOOL fOkay = TRUE;
Y = ConGetCursorY();
X = ConGetCursorX();
switch (ch) {
case 0x8: /* BackSpace */
if (X == 0) {
ConSetCursorPosition(ScreenX - 1, --Y);
WriteConsole(hOutputConsole, " ", 1, (LPDWORD)&Result, 0);
ConSetCursorPosition(ScreenX - 1, Y);
} else {
ConSetCursorPosition(X - 1, Y);
WriteConsole(hOutputConsole, " ", 1, (LPDWORD)&Result, 0);
ConSetCursorPosition(X - 1, Y);
}
break;
case L'\r':
ConSetCursorPosition(0, Y);
break;
case L'\n':
Y++;
if (Y > ScrollBottom - 1) {
ConScrollDown(ScrollTop, ScrollBottom);
ConSetCursorPosition(0, ScrollBottom);
}
else
ConSetCursorPosition(0, Y);
break;
default:
fOkay = (BOOL)WriteConsoleW(hOutputConsole, &ch, 1, (LPDWORD)&Result, 0);
if (X >= ScreenX - 1) { /* last coord */
if (Y >= ScrollBottom - 1) { /* last coord */
ConScrollDown(ScrollTop, ScrollBottom);
ConMoveCursorPosition(-ConGetCursorX(), 0);
} else
ConMoveCursorPosition(-ConGetCursorX(), 1);
}
break;
}
return fOkay;
2016-12-19 23:46:28 +01:00
}
/* Special Function for handling TABS and other bad control chars */
int
ConWriteConsole(char *pData, int NumChars)
2016-12-19 23:46:28 +01:00
{
int X, CurrentY, CurrentX, Result;
for (X = 0; (X < NumChars) && (pData[X] != '\0'); X++) {
switch (pData[X]) {
case 0: /* FALLTHROUGH */
case 1: /* FALLTHROUGH */
case 2: /* FALLTHROUGH */
case 3: /* FALLTHROUGH */
case 4: /* FALLTHROUGH */
case 5: /* FALLTHROUGH */
case 6: /* FALLTHROUGH */
case 11: /* FALLTHROUGH */
break;
case 7:
Beep(1000, 400);
break;
case 8:
ConMoveCursorPosition(-1, 0);
WriteConsole(hOutputConsole, " ", 1, (LPDWORD)&Result, 0);
ConMoveCursorPosition(-1, 0);
break;
case 9:
{
int i, MoveRight = TAB_LENGTH - (ConGetCursorX() % TAB_LENGTH);
for (i = 0; i < MoveRight; i++)
WriteConsole(hOutputConsole, " ", 1, (LPDWORD)&Result, 0);
}
break;
case 10:
CurrentY = ConGetCursorY() + 1;
if (CurrentY >= ScrollBottom) {
ConScrollDown(ScrollTop, ScrollBottom);
ConMoveCursorPosition(-ConGetCursorX(), 0);
} else
ConMoveCursorPosition(0, 1);
break;
case 12:
ConClearScreen();
ConSetCursorPosition(0, 0);
break;
case 13:
ConMoveCursorPosition(-ConGetCursorX(), 0);
break;
case 14: /* FALLTHROUGH */
case 15:
break;
default:
{
CurrentY = ConGetCursorY();
CurrentX = ConGetCursorX();
WriteConsole(hOutputConsole, &pData[X], 1, (LPDWORD)&Result, 0);
if (CurrentX >= ScreenX - 1) { /* last coord */
if (CurrentY >= ScrollBottom - 1) { /* last coord */
ConScrollDown(ScrollTop, ScrollBottom);
ConMoveCursorPosition(-ConGetCursorX(), 0);
} else
ConMoveCursorPosition(-ConGetCursorX(), 1);
}
}
}
}
return X;
2016-12-19 23:46:28 +01:00
}
PCHAR
ConWriteLine(char* pData)
2016-12-19 23:46:28 +01:00
{
PCHAR pCurrent, pNext, pTab;
DWORD Result;
size_t distance, tabCount, pos;
size_t tabLength, charCount;
pCurrent = pData;
pNext = strchr(pCurrent, '\r');
if (pNext != NULL) {
distance = pNext - pCurrent;
if (distance > (size_t)ScreenX)
distance = (size_t)ScreenX;
pos = 0;
tabCount = 0;
pTab = strchr(pCurrent, TAB_CHAR);
if ((pTab != NULL) && (pTab < pNext)) {
/* Tab exists in string So we use our WriteString */
while ((pTab != NULL) && (pTab < pNext) && (pos < (size_t)ScreenX)) {
tabCount++;
charCount = (pTab - pCurrent) - 1; /* Ignore actual TAB since we add 8 for it */
pos = charCount + (tabCount * TAB_LENGTH);
pTab++; /* increment past last tab */
pTab = strchr(pTab, TAB_CHAR);
}
tabLength = (tabCount * TAB_LENGTH);
distance = ConWriteConsole(pCurrent, (int)distance); /* Special routine for handling TABS */
} else
WriteConsole(hOutputConsole, pCurrent, (DWORD)distance, &Result, 0);
ConSetCursorPosition(0, ConGetCursorY() + 1);
pCurrent += (distance + 2); /* Add one to always skip last char printed */
} else {
distance = strlen(pCurrent);
if (distance > (size_t)ScreenX)
distance = (size_t)ScreenX;
WriteConsole(hOutputConsole, pCurrent, (DWORD)distance, &Result, 0);
pCurrent += distance;
}
return pCurrent;
2016-12-19 23:46:28 +01:00
}
PCHAR
ConDisplayData(char* pData, int NumLines)
2016-12-19 23:46:28 +01:00
{
PCHAR pCurrent, pNext, pTab;
DWORD Result;
size_t Y, distance, pos, add;
int linecnt = 0;
pCurrent = pData;
for (; (pCurrent) && ((Y = (size_t)ConGetCursorY()) <= (size_t)ScrollBottom) && (*pCurrent != '\0'); ) {
pNext = strchr(pCurrent, '\n');
if (pNext != NULL) {
--pNext;
if (*pNext != '\r') {
pNext++;
add = 1;
}
else
add = 2;
distance = pNext - pCurrent;
if (distance > 0 && linecnt < NumLines) {
pos = 0;
pTab = strchr(pCurrent, TAB_CHAR);
if ((distance > (size_t)ScreenX) || ((pTab != NULL) && (pTab < pNext)))
ConWriteConsole(pCurrent, (int)distance); /* Special routine for handling TABS */
else
WriteConsole(hOutputConsole, pCurrent, (DWORD)distance, &Result, 0);
}
ConMoveCursorPosition(-ConGetCursorX(), 1);
pCurrent += (distance + add); /* Add one to always skip last char printed */
linecnt++;
} else {
distance = strlen(pCurrent);
if (distance > (size_t)ScreenX)
distance = ScreenX;
if (linecnt < NumLines)
WriteConsole(hOutputConsole, pCurrent, (DWORD)distance, &Result, 0);
return pCurrent + distance;
}
}
return pCurrent;
2016-12-19 23:46:28 +01:00
}
int
Con_printf(const char *Format, ...)
2016-12-19 23:46:28 +01:00
{
va_list va_data;
int len;
char temp[4096];
2016-12-19 23:46:28 +01:00
memset(temp, '\0', sizeof(temp));
va_start(va_data, Format);
len = vsnprintf(temp, sizeof(temp), Format, va_data);
ConWriteConsole(temp, len);
va_end(va_data);
2016-12-19 23:46:28 +01:00
return len;
2016-12-19 23:46:28 +01:00
}
BOOL
ConDisplayCursor(BOOL bVisible)
2016-12-19 23:46:28 +01:00
{
CONSOLE_CURSOR_INFO ConsoleCursorInfo;
2016-12-19 23:46:28 +01:00
if (GetConsoleCursorInfo(hOutputConsole, &ConsoleCursorInfo)) {
ConsoleCursorInfo.bVisible = bVisible;
return SetConsoleCursorInfo(hOutputConsole, &ConsoleCursorInfo);
}
2016-12-19 23:46:28 +01:00
return FALSE;
2016-12-19 23:46:28 +01:00
}
void
ConClearScreen()
2016-12-19 23:46:28 +01:00
{
DWORD dwWritten;
COORD Coord;
CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
SMALL_RECT srcWindow;
if (!GetConsoleScreenBufferInfo(hOutputConsole, &consoleInfo))
return;
Coord.X = 0;
Coord.Y = 0;
DWORD dwNumChar = (consoleInfo.dwSize.Y) * (consoleInfo.dwSize.X);
FillConsoleOutputCharacter(hOutputConsole, ' ', dwNumChar, Coord, &dwWritten);
FillConsoleOutputAttribute(hOutputConsole, consoleInfo.wAttributes, dwNumChar, Coord, &dwWritten);
srcWindow = consoleInfo.srWindow;
ConSetCursorPosition(0, 0);
}
2016-12-19 23:46:28 +01:00
void
ConClearScrollRegion()
{
DWORD dwWritten;
COORD Coord;
CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
if (!GetConsoleScreenBufferInfo(hOutputConsole, &consoleInfo))
return;
2016-12-19 23:46:28 +01:00
Coord.X = 0;
Coord.Y = ScrollTop + consoleInfo.srWindow.Top;
FillConsoleOutputCharacter(hOutputConsole, ' ', (DWORD)consoleInfo.dwSize.X * (DWORD)ScrollBottom,
Coord, &dwWritten);
2016-12-19 23:46:28 +01:00
FillConsoleOutputAttribute(hOutputConsole, consoleInfo.wAttributes,
(DWORD)consoleInfo.dwSize.X * (DWORD)ScrollBottom, Coord, &dwWritten);
2016-12-19 23:46:28 +01:00
ConSetCursorPosition(0, ScrollTop);
2016-12-19 23:46:28 +01:00
}
void
ConClearEOScreen()
2016-12-19 23:46:28 +01:00
{
DWORD dwWritten;
COORD Coord;
CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
if (!GetConsoleScreenBufferInfo(hOutputConsole, &consoleInfo))
return;
Coord.X = 0;
Coord.Y = (short)(ConGetCursorY() + 1) + consoleInfo.srWindow.Top;
FillConsoleOutputCharacter(hOutputConsole, ' ',
(DWORD)(consoleInfo.dwSize.X)*
(DWORD)(consoleInfo.srWindow.Bottom - Coord.Y + 1),
Coord, &dwWritten);
FillConsoleOutputAttribute(hOutputConsole, consoleInfo.wAttributes,
(DWORD)(consoleInfo.dwSize.X)*
(DWORD)(consoleInfo.srWindow.Bottom - Coord.Y + 1),
Coord, &dwWritten);
ConClearEOLine();
2016-12-19 23:46:28 +01:00
}
void
ConClearBOScreen()
2016-12-19 23:46:28 +01:00
{
DWORD dwWritten;
COORD Coord;
CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
if (!GetConsoleScreenBufferInfo(hOutputConsole, &consoleInfo))
return;
Coord.X = 0;
Coord.Y = 0;
FillConsoleOutputCharacter(hOutputConsole, ' ',
(DWORD)(consoleInfo.dwSize.X)*
(DWORD)(consoleInfo.dwSize.Y - ConGetCursorY() - 1),
Coord, &dwWritten);
FillConsoleOutputAttribute(hOutputConsole, consoleInfo.wAttributes,
(DWORD)(consoleInfo.dwSize.X)*
(DWORD)(consoleInfo.dwSize.Y - ConGetCursorY() - 1),
Coord, &dwWritten);
ConClearBOLine();
2016-12-19 23:46:28 +01:00
}
void
ConClearLine()
2016-12-19 23:46:28 +01:00
{
DWORD dwWritten;
COORD Coord;
CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
if (!GetConsoleScreenBufferInfo(hOutputConsole, &consoleInfo))
return;
Coord.X = 0;
Coord.Y = ConGetCursorY();
FillConsoleOutputAttribute(hOutputConsole, consoleInfo.wAttributes, ScreenX, Coord, &dwWritten);
FillConsoleOutputCharacter(hOutputConsole, ' ', ScreenX, Coord, &dwWritten);
2016-12-19 23:46:28 +01:00
}
void
ConClearEOLine()
2016-12-19 23:46:28 +01:00
{
DWORD dwWritten;
COORD Coord;
CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
if (!GetConsoleScreenBufferInfo(hOutputConsole, &consoleInfo))
return;;
Coord.X = ConGetCursorX() + consoleInfo.srWindow.Left;
Coord.Y = ConGetCursorY() + consoleInfo.srWindow.Top;
FillConsoleOutputCharacter(hOutputConsole, ' ',
(DWORD)(ScreenX - ConGetCursorX()),
Coord, &dwWritten);
FillConsoleOutputAttribute(hOutputConsole, consoleInfo.wAttributes,
(DWORD)(ScreenX - ConGetCursorX()),
Coord, &dwWritten);
2016-12-19 23:46:28 +01:00
}
void
ConClearNFromCursorRight(int n)
2016-12-19 23:46:28 +01:00
{
DWORD dwWritten;
COORD Coord;
CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
if (!GetConsoleScreenBufferInfo(hOutputConsole, &consoleInfo))
return;
Coord.X = ConGetCursorX() + consoleInfo.srWindow.Left;
Coord.Y = ConGetCursorY() + consoleInfo.srWindow.Top;
FillConsoleOutputCharacter(hOutputConsole, ' ', (DWORD)n, Coord, &dwWritten);
FillConsoleOutputAttribute(hOutputConsole, consoleInfo.wAttributes, (DWORD)n, Coord, &dwWritten);
2016-12-19 23:46:28 +01:00
}
void
ConClearNFromCursorLeft(int n)
2016-12-19 23:46:28 +01:00
{
DWORD dwWritten;
COORD Coord;
CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
2016-12-19 23:46:28 +01:00
if (!GetConsoleScreenBufferInfo(hOutputConsole, &consoleInfo))
return;
Coord.X = ConGetCursorX() + consoleInfo.srWindow.Left - n;
Coord.Y = ConGetCursorY() + consoleInfo.srWindow.Top;
FillConsoleOutputCharacter(hOutputConsole, ' ', (DWORD)n, Coord, &dwWritten);
FillConsoleOutputAttribute(hOutputConsole, consoleInfo.wAttributes, (DWORD)n, Coord, &dwWritten);
2016-12-19 23:46:28 +01:00
}
void
ConScrollDownEntireBuffer()
2016-12-19 23:46:28 +01:00
{
CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
2016-12-19 23:46:28 +01:00
if (!GetConsoleScreenBufferInfo(hOutputConsole, &consoleInfo))
return;
ConScrollDown(0, consoleInfo.dwSize.Y - 1);
return;
2016-12-19 23:46:28 +01:00
}
void
ConScrollUpEntireBuffer()
2016-12-19 23:46:28 +01:00
{
CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
2016-12-19 23:46:28 +01:00
if (!GetConsoleScreenBufferInfo(hOutputConsole, &consoleInfo))
return;
ConScrollUp(0, consoleInfo.dwSize.Y - 1);
return;
2016-12-19 23:46:28 +01:00
}
void
ConScrollUp(int topline, int botline)
2016-12-19 23:46:28 +01:00
{
SMALL_RECT ScrollRect;
SMALL_RECT ClipRect;
COORD destination;
CHAR_INFO Fill;
CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
if (!GetConsoleScreenBufferInfo(hOutputConsole, &consoleInfo))
return;
if ((botline - topline) == consoleInfo.dwSize.Y - 1) { /* scrolling whole buffer */
ScrollRect.Top = topline;
ScrollRect.Bottom = botline;
} else {
ScrollRect.Top = topline + consoleInfo.srWindow.Top;
ScrollRect.Bottom = botline + consoleInfo.srWindow.Top;
}
ScrollRect.Left = 0;
ScrollRect.Right = ConScreenSizeX() - 1;
ClipRect.Top = ScrollRect.Top;
ClipRect.Bottom = ScrollRect.Bottom;
ClipRect.Left = ScrollRect.Left;
ClipRect.Right = ScrollRect.Right;
destination.X = 0;
destination.Y = ScrollRect.Top + 1;
Fill.Attributes = consoleInfo.wAttributes;
Fill.Char.AsciiChar = ' ';
BOOL bRet = ScrollConsoleScreenBuffer(hOutputConsole,
&ScrollRect,
&ClipRect,
destination,
&Fill
);
2016-12-19 23:46:28 +01:00
}
void
ConMoveVisibleWindow(int offset)
{
CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
SMALL_RECT visibleWindowRect;
if (GetConsoleScreenBufferInfo(hOutputConsole, &consoleInfo)) {
memcpy(&visibleWindowRect, &consoleInfo.srWindow, sizeof(visibleWindowRect));
visibleWindowRect.Top += offset;
visibleWindowRect.Bottom += offset;
SetConsoleWindowInfo(hOutputConsole, TRUE, &visibleWindowRect);
}
}
void
ConScrollDown(int topline, int botline)
2016-12-19 23:46:28 +01:00
{
SMALL_RECT ScrollRect;
COORD destination;
CHAR_INFO Fill;
CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
if (!GetConsoleScreenBufferInfo(hOutputConsole, &consoleInfo))
return;
if ((botline - topline) == consoleInfo.dwSize.Y - 1) { /* scrolling whole buffer */
ScrollRect.Top = topline;
ScrollRect.Bottom = botline;
} else {
ScrollRect.Top = topline + consoleInfo.srWindow.Top + 1;
ScrollRect.Bottom = botline + consoleInfo.srWindow.Top;
}
ScrollRect.Left = 0;
ScrollRect.Right = ConScreenSizeX() - 1;
destination.X = 0;
destination.Y = ScrollRect.Top - 1;
Fill.Attributes = consoleInfo.wAttributes;
Fill.Char.AsciiChar = ' ';
BOOL bRet = ScrollConsoleScreenBuffer(hOutputConsole,
&ScrollRect,
NULL,
destination,
&Fill
);
2016-12-19 23:46:28 +01:00
}
void
ConClearBOLine()
2016-12-19 23:46:28 +01:00
{
DWORD dwWritten;
COORD Coord;
CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
if (!GetConsoleScreenBufferInfo(hOutputConsole, &consoleInfo))
return;
Coord.X = 0;
Coord.Y = (short)(ConGetCursorY());
FillConsoleOutputAttribute(hOutputConsole, consoleInfo.wAttributes,
(DWORD)(ConGetCursorX()),
Coord, &dwWritten);
FillConsoleOutputCharacter(hOutputConsole, ' ',
(DWORD)(ConGetCursorX()),
Coord, &dwWritten);
2016-12-19 23:46:28 +01:00
}
void
ConSetCursorPosition(int x, int y)
2016-12-19 23:46:28 +01:00
{
CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
COORD Coord;
int rc;
2016-12-19 23:46:28 +01:00
if (!GetConsoleScreenBufferInfo(hOutputConsole, &consoleInfo))
return;
2016-12-19 23:46:28 +01:00
Coord.X = (short)(x);
Coord.Y = (short)(y);
2016-12-19 23:46:28 +01:00
if ((y > consoleInfo.dwSize.Y - 1) && y > LastCursorY) {
for (int n = LastCursorY; n < y; n++)
GoToNextLine();
}
2016-12-19 23:46:28 +01:00
if (y >= consoleInfo.dwSize.Y) {
Coord.Y = consoleInfo.dwSize.Y - 1;
}
2016-12-19 23:46:28 +01:00
if (!SetConsoleCursorPosition(hOutputConsole, Coord))
rc = GetLastError();
2016-12-19 23:46:28 +01:00
LastCursorX = x;
LastCursorY = y;
2016-12-19 23:46:28 +01:00
}
BOOL
ConChangeCursor(CONSOLE_CURSOR_INFO *pCursorInfo)
2016-12-19 23:46:28 +01:00
{
return SetConsoleCursorInfo(hOutputConsole, pCursorInfo);
2016-12-19 23:46:28 +01:00
}
void
ConGetCursorPosition(int *x, int *y)
{
CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
if (GetConsoleScreenBufferInfo(hOutputConsole, &consoleInfo)) {
*x = consoleInfo.dwCursorPosition.X;
*y = consoleInfo.dwCursorPosition.Y;
}
}
int
ConGetCursorX()
2016-12-19 23:46:28 +01:00
{
CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
2016-12-19 23:46:28 +01:00
if (!GetConsoleScreenBufferInfo(hOutputConsole, &consoleInfo))
return 0;
2016-12-19 23:46:28 +01:00
return consoleInfo.dwCursorPosition.X;
2016-12-19 23:46:28 +01:00
}
int
is_cursor_at_lastline_of_visible_window()
{
CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
int return_val = 0;
if (GetConsoleScreenBufferInfo(hOutputConsole, &consoleInfo)) {
int cursor_linenum_in_visible_window = consoleInfo.dwCursorPosition.Y - consoleInfo.srWindow.Top;
if (cursor_linenum_in_visible_window >= ConVisibleWindowHeight() - 1)
return_val = 1;
}
return return_val;
}
int
ConGetCursorY()
2016-12-19 23:46:28 +01:00
{
CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
2016-12-19 23:46:28 +01:00
if (!GetConsoleScreenBufferInfo(hOutputConsole, &consoleInfo))
return 0;
2016-12-19 23:46:28 +01:00
return (consoleInfo.dwCursorPosition.Y - consoleInfo.srWindow.Top);
2016-12-19 23:46:28 +01:00
}
int
ConGetBufferHeight()
2016-12-19 23:46:28 +01:00
{
CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
2016-12-19 23:46:28 +01:00
if (!GetConsoleScreenBufferInfo(hOutputConsole, &consoleInfo))
return 0;
2016-12-19 23:46:28 +01:00
return (consoleInfo.dwSize.Y - 1);
2016-12-19 23:46:28 +01:00
}
void
ConMoveCursorPosition(int x, int y)
2016-12-19 23:46:28 +01:00
{
CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
COORD Coord;
2016-12-19 23:46:28 +01:00
if (!GetConsoleScreenBufferInfo(hOutputConsole, &consoleInfo))
return;
2016-12-19 23:46:28 +01:00
Coord.X = (short)(consoleInfo.dwCursorPosition.X + x);
Coord.Y = (short)(consoleInfo.dwCursorPosition.Y + y);
2016-12-19 23:46:28 +01:00
SetConsoleCursorPosition(hOutputConsole, Coord);
2016-12-19 23:46:28 +01:00
}
void
ConGetRelativeCursorPosition(int *x, int *y)
2016-12-19 23:46:28 +01:00
{
CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
2016-12-19 23:46:28 +01:00
if (!GetConsoleScreenBufferInfo(hOutputConsole, &consoleInfo))
return;
2016-12-19 23:46:28 +01:00
*x -= consoleInfo.srWindow.Left;
*y -= consoleInfo.srWindow.Top;
2016-12-19 23:46:28 +01:00
}
void
ConDeleteChars(int n)
2016-12-19 23:46:28 +01:00
{
CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
COORD coord;
CHAR_INFO chiBuffer[256]; // 1 row, 256 characters
SMALL_RECT sr;
COORD temp;
int result;
if (!GetConsoleScreenBufferInfo(hOutputConsole, &consoleInfo))
return;
coord.X = (short)(consoleInfo.dwCursorPosition.X);
coord.Y = (short)(consoleInfo.dwCursorPosition.Y);
sr.Left = coord.X + n;
sr.Top = coord.Y;
sr.Bottom = coord.Y;
sr.Right = consoleInfo.srWindow.Right;
temp.X = 256;
temp.Y = 1;
result = ReadConsoleOutput(hOutputConsole, /* console screen buffer handle */
(PCHAR_INFO)chiBuffer, /* address of buffer that receives data */
temp, /* column-row size of destination buffer */
ZeroCoord, /* upper-left cell to write to */
&sr /* address of rectangle to read from */
);
ConClearEOLine();
sr.Left = coord.X;
temp.X = 256;
temp.Y = 1;
sr.Right -= n;
result = WriteConsoleOutput(hOutputConsole, (PCHAR_INFO)chiBuffer, temp, ZeroCoord, &sr);
2016-12-19 23:46:28 +01:00
}
SCREEN_HANDLE
ConSaveScreenHandle(SCREEN_HANDLE hScreen)
2016-12-19 23:46:28 +01:00
{
CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
PSCREEN_RECORD pScreenRec = (PSCREEN_RECORD)hScreen;
int result, width, height;
if (hOutputConsole == NULL)
return NULL;
if (!GetConsoleScreenBufferInfo(hOutputConsole, &consoleInfo))
return (NULL);
if (pScreenRec == NULL) {
pScreenRec = (PSCREEN_RECORD)malloc(sizeof(SCREEN_RECORD));
pScreenRec->pScreenBuf = NULL;
}
pScreenRec->srWindowRect = consoleInfo.srWindow;
width = consoleInfo.srWindow.Right - consoleInfo.srWindow.Left + 1;
height = consoleInfo.srWindow.Bottom - consoleInfo.srWindow.Top + 1;
pScreenRec->ScreenSize.X = width;
pScreenRec->ScreenSize.Y = height;
pScreenRec->ScreenCursor.X = consoleInfo.dwCursorPosition.X - consoleInfo.srWindow.Left;
pScreenRec->ScreenCursor.Y = consoleInfo.dwCursorPosition.Y - consoleInfo.srWindow.Top;
if (pScreenRec->pScreenBuf == NULL)
pScreenRec->pScreenBuf = (PCHAR_INFO)malloc(sizeof(CHAR_INFO) * width * height);
if (!pScreenRec->pScreenBuf) {
if (pScreenRec != (PSCREEN_RECORD)hScreen)
free(pScreenRec);
return NULL;
}
result = ReadConsoleOutput(hOutputConsole, /* console screen buffer handle */
(PCHAR_INFO)(pScreenRec->pScreenBuf),/* address of buffer that receives data */
pScreenRec->ScreenSize, /* column-row size of destination buffer */
ZeroCoord, /* upper-left cell to write to */
&consoleInfo.srWindow /* address of rectangle to read from */
);
return((SCREEN_HANDLE)pScreenRec);
2016-12-19 23:46:28 +01:00
}
BOOL
ConRestoreScreenHandle(SCREEN_HANDLE hScreen)
2016-12-19 23:46:28 +01:00
{
BOOL fOkay = FALSE;
CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
COORD beginOfScreen = { 0, 0 };
PCHAR_INFO pSavedCharInfo;
DWORD dwWritten;
PSCREEN_RECORD pScreenRec = (PSCREEN_RECORD)hScreen;
int width, height;
if (hOutputConsole == NULL)
return FALSE;
if (!GetConsoleScreenBufferInfo(hOutputConsole, &consoleInfo))
return (FALSE);
width = consoleInfo.srWindow.Right - consoleInfo.srWindow.Left + 1;
height = consoleInfo.srWindow.Bottom - consoleInfo.srWindow.Top + 1;
beginOfScreen.X = consoleInfo.srWindow.Left;
beginOfScreen.Y = consoleInfo.srWindow.Top;
FillConsoleOutputCharacter(hOutputConsole, ' ', (DWORD)width*height, beginOfScreen, &dwWritten);
pSavedCharInfo = (PCHAR_INFO)(pScreenRec->pScreenBuf);
SetConsoleTextAttribute(hOutputConsole, pSavedCharInfo->Attributes);
FillConsoleOutputAttribute(hOutputConsole, pSavedCharInfo->Attributes,
(DWORD)width*height,
beginOfScreen, &dwWritten);
fOkay = WriteConsoleOutput(hOutputConsole, /* handle to a console screen buffer */
(PCHAR_INFO)(pScreenRec->pScreenBuf), /* pointer to buffer with data to write */
pScreenRec->ScreenSize, /* column-row size of source buffer */
ZeroCoord, /* upper-left cell to write from */
&consoleInfo.srWindow /* pointer to rectangle to write to */
);
SetConsoleWindowInfo(hOutputConsole, TRUE, &pScreenRec->srWindowRect);
ConSetCursorPosition(pScreenRec->ScreenCursor.X, pScreenRec->ScreenCursor.Y);
return fOkay;
2016-12-19 23:46:28 +01:00
}
BOOL
ConRestoreScreenColors()
2016-12-19 23:46:28 +01:00
{
SCREEN_HANDLE hScreen = pSavedScreenRec;
BOOL fOkay = FALSE;
CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
COORD beginOfScreen = { 0, 0 };
PCHAR_INFO pSavedCharInfo;
DWORD dwWritten;
PSCREEN_RECORD pScreenRec = (PSCREEN_RECORD)hScreen;
2016-12-19 23:46:28 +01:00
if (hOutputConsole == NULL)
return FALSE;
2016-12-19 23:46:28 +01:00
if (pSavedScreen == NULL)
return FALSE;
2016-12-19 23:46:28 +01:00
if (!GetConsoleScreenBufferInfo(hOutputConsole, &consoleInfo))
return (FALSE);
2016-12-19 23:46:28 +01:00
beginOfScreen.X = consoleInfo.srWindow.Left;
beginOfScreen.Y = consoleInfo.srWindow.Top;
2016-12-19 23:46:28 +01:00
FillConsoleOutputCharacter(hOutputConsole, ' ',
(DWORD)pScreenRec->ScreenSize.X*pScreenRec->ScreenSize.Y,
beginOfScreen, &dwWritten);
2016-12-19 23:46:28 +01:00
pSavedCharInfo = (PCHAR_INFO)(pScreenRec->pScreenBuf);
SetConsoleTextAttribute(hOutputConsole, pSavedCharInfo->Attributes);
2016-12-19 23:46:28 +01:00
FillConsoleOutputAttribute(hOutputConsole, pSavedCharInfo->Attributes,
(DWORD)pScreenRec->ScreenSize.X*pScreenRec->ScreenSize.Y,
beginOfScreen, &dwWritten);
2016-12-19 23:46:28 +01:00
return fOkay;
2016-12-19 23:46:28 +01:00
}
void
ConDeleteScreenHandle(SCREEN_HANDLE hScreen)
2016-12-19 23:46:28 +01:00
{
PSCREEN_RECORD pScreenRec = (PSCREEN_RECORD)hScreen;
2016-12-19 23:46:28 +01:00
free(pScreenRec->pScreenBuf);
free(pScreenRec);
2016-12-19 23:46:28 +01:00
}
/* Restores Previous Saved screen info and buffer */
BOOL
ConRestoreScreen()
2016-12-19 23:46:28 +01:00
{
return ConRestoreScreenHandle(pSavedScreenRec);
2016-12-19 23:46:28 +01:00
}
/* Saves current screen info and buffer */
void
ConSaveScreen()
2016-12-19 23:46:28 +01:00
{
pSavedScreenRec = (PSCREEN_RECORD)ConSaveScreenHandle(pSavedScreenRec);
2016-12-19 23:46:28 +01:00
}
void
ConSaveViewRect()
2016-12-19 23:46:28 +01:00
{
CONSOLE_SCREEN_BUFFER_INFO csbi;
2016-12-19 23:46:28 +01:00
if (GetConsoleScreenBufferInfo(hOutputConsole, &csbi))
SavedViewRect = csbi.srWindow;
}
void
ConRestoreViewRect()
{
CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
HWND hwnd = FindWindow(NULL, consoleTitle);
WINDOWPLACEMENT wp;
wp.length = sizeof(WINDOWPLACEMENT);
GetWindowPlacement(hwnd, &wp);
if (GetConsoleScreenBufferInfo(hOutputConsole, &consoleInfo) &&
((consoleInfo.srWindow.Top != SavedViewRect.Top ||
consoleInfo.srWindow.Bottom != SavedViewRect.Bottom))) {
if ((SavedViewRect.Right - SavedViewRect.Left > consoleInfo.dwSize.X) ||
(wp.showCmd == SW_SHOWMAXIMIZED)) {
COORD coordScreen;
coordScreen.X = SavedViewRect.Right - SavedViewRect.Left;
coordScreen.Y = consoleInfo.dwSize.Y;
SetConsoleScreenBufferSize(hOutputConsole, coordScreen);
ShowWindow(hwnd, SW_SHOWMAXIMIZED);
} else
ShowWindow(hwnd, SW_RESTORE);
2016-12-19 23:46:28 +01:00
SetConsoleWindowInfo(hOutputConsole, TRUE, &SavedViewRect);
}
2016-12-19 23:46:28 +01:00
}
BOOL
ConIsRedirected(HANDLE hInput)
2016-12-19 23:46:28 +01:00
{
DWORD dwMode;
return !GetConsoleMode(hInput, &dwMode);
2016-12-19 23:46:28 +01:00
}
HANDLE
GetConsoleOutputHandle()
2016-12-19 23:46:28 +01:00
{
SECURITY_ATTRIBUTES sa;
2016-12-19 23:46:28 +01:00
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
2016-12-19 23:46:28 +01:00
HANDLE hTemp = GetStdHandle(STD_OUTPUT_HANDLE);
2016-12-19 23:46:28 +01:00
if (ConIsRedirected(hTemp))
hTemp = CreateFile(TEXT("CONOUT$"), GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_WRITE | FILE_SHARE_READ,
&sa, OPEN_EXISTING, 0, NULL);
2016-12-19 23:46:28 +01:00
return hTemp;
2016-12-19 23:46:28 +01:00
}
HANDLE
GetConsoleInputHandle()
2016-12-19 23:46:28 +01:00
{
SECURITY_ATTRIBUTES sa;
2016-12-19 23:46:28 +01:00
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
2016-12-19 23:46:28 +01:00
HANDLE hTemp = GetStdHandle(STD_INPUT_HANDLE);
2016-12-19 23:46:28 +01:00
if (ConIsRedirected(hTemp))
hTemp = CreateFile(TEXT("CONIN$"), GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_WRITE | FILE_SHARE_READ,
&sa, OPEN_EXISTING, 0, NULL);
2016-12-19 23:46:28 +01:00
return hTemp;
2016-12-19 23:46:28 +01:00
}
void
ConSaveWindowsState()
2016-12-19 23:46:28 +01:00
{
CONSOLE_SCREEN_BUFFER_INFOEX csbiex;
csbiex.cbSize = sizeof(CONSOLE_SCREEN_BUFFER_INFOEX);
2016-12-19 23:46:28 +01:00
if (!GetConsoleScreenBufferInfoEx(hOutputConsole, &csbiex))
return;
2016-12-19 23:46:28 +01:00
SavedWindowState = csbiex;
2016-12-19 23:46:28 +01:00
}
void
ConMoveCurosorTop(CONSOLE_SCREEN_BUFFER_INFO csbi)
{
int offset = csbi.dwCursorPosition.Y - csbi.srWindow.Top;
ConMoveVisibleWindow(offset);
ConSaveViewRect();
}