/* console.c * Author: Pragma Systems, Inc. * Contribution by Pragma Systems, Inc. for Microsoft openssh win32 port * Copyright (c) 2011, 2015 Pragma Systems, Inc. * 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. * * 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. * 2. Binaries produced provide no direct or implied warranties or any * guarantee of performance or suitability. */ #include #include #include #include #include #include HANDLE hConsole = NULL; DWORD dwSavedAttributes = 0; WORD wStartingAttributes = 0; int ScreenX; int ScreenY; int ScrollTop; int ScrollBottom; char *pSavedScreen = NULL; static COORD ZeroCoord = {0,0}; COORD SavedScreenSize = {0,0}; COORD SavedScreenCursor = {0, 0 }; SMALL_RECT SavedViewRect = {0,0,0,0}; typedef struct _SCREEN_RECORD{ PCHAR_INFO pScreenBuf; COORD ScreenSize; COORD ScreenCursor; SMALL_RECT srWindowRect; }SCREEN_RECORD,*PSCREEN_RECORD; PSCREEN_RECORD pSavedScreenRec = NULL; /* ************************************************************ */ /* Function: ConInit */ /* Used to Initialize the Console for output */ /* ************************************************************ */ int ConInit( DWORD OutputHandle, bool fSmartInit ) { OSVERSIONINFO os; DWORD dwAttributes = 0; CONSOLE_SCREEN_BUFFER_INFO csbi; static bool bFirstConInit = true; os.dwOSVersionInfoSize = sizeof( OSVERSIONINFO ); GetVersionEx( &os ); hConsole = GetStdHandle( OutputHandle ); if (hConsole == INVALID_HANDLE_VALUE) printf("GetStdHandle failed with %d\n",GetLastError()); if (!GetConsoleMode( hConsole, &dwSavedAttributes )) printf("GetConsoleMode failed with %d\n",GetLastError()); dwAttributes = dwSavedAttributes; if ( os.dwPlatformId == VER_PLATFORM_WIN32_NT ) { // dwAttributes = (DWORD)ENABLE_WRAP_AT_EOL_OUTPUT; // Causes screen scroll in Edit // dwAttributes = (DWORD)(ENABLE_PROCESSED_OUTPUT & ~(ENABLE_WRAP_AT_EOL_OUTPUT)); // dwAttributes = 0; // Causes wrong FONTS and doesn't handle CRLF dwAttributes = (DWORD)ENABLE_PROCESSED_OUTPUT; // PERFECT in NT // dwAttributes = (DWORD)ENABLE_PROCESSED_OUTPUT | (DWORD)ENABLE_WRAP_AT_EOL_OUTPUT; // PERFECT in NT SetConsoleMode(hConsole, dwAttributes ); // Windows NT } else { dwAttributes = (DWORD)ENABLE_WRAP_AT_EOL_OUTPUT; // Doesn't always print last column & doesn't handle CRLF // dwAttributes = (DWORD)(ENABLE_PROCESSED_OUTPUT & ~(ENABLE_WRAP_AT_EOL_OUTPUT)); // dwAttributes = 0; // Causes wrong FONTS and doesn't handle CRLF // dwAttributes = (DWORD)ENABLE_PROCESSED_OUTPUT; // Scrolls in Windows 95 SetConsoleMode(hConsole, dwAttributes ); // Windows 95 } if (bFirstConInit && fSmartInit) { if (GetConsoleScreenBufferInfo(hConsole, &csbi)) { SMALL_RECT sr; wStartingAttributes = csbi.wAttributes; int ydelta = csbi.srWindow.Bottom-csbi.srWindow.Top+1; if (csbi.dwCursorPosition.Y+ydelta > csbi.dwSize.Y) { // not enough buffer to reposition window.. must scroll SMALL_RECT ScrollRect; SMALL_RECT ClipRect; COORD destination; CHAR_INFO Fill; COORD newCursorPos; ScrollRect.Top = (csbi.dwCursorPosition.Y+ydelta - csbi.dwSize.Y); ScrollRect.Bottom = csbi.dwCursorPosition.Y+1; ScrollRect.Left = 0; ScrollRect.Right = csbi.dwSize.X; ClipRect = ScrollRect; ClipRect.Top = 0; destination.X = 0; destination.Y = 0; Fill.Attributes = csbi.wAttributes; Fill.Char.AsciiChar = ' '; ScrollConsoleScreenBuffer( hConsole, &ScrollRect, &ClipRect, destination, &Fill ); newCursorPos.Y = csbi.dwSize.Y-ydelta; newCursorPos.X = csbi.dwCursorPosition.X; SetConsoleCursorPosition(hConsole,newCursorPos); sr = csbi.srWindow; sr.Top = newCursorPos.Y; sr.Bottom = csbi.dwSize.Y-1; BOOL rc = SetConsoleWindowInfo(hConsole,TRUE,&sr); }else{ GetConsoleScreenBufferInfo(hConsole, &csbi); sr = csbi.srWindow; sr.Top = csbi.dwCursorPosition.Y; sr.Bottom = sr.Top+ydelta-1; BOOL rc = SetConsoleWindowInfo(hConsole,TRUE,&sr); } } bFirstConInit = false; } ConSetScreenX(); ConSetScreenY(); ScrollTop = 0; ScrollBottom = ConWindowSizeY(); if (GetConsoleScreenBufferInfo(hConsole, &csbi)) SavedViewRect = csbi.srWindow; return 0; } /* ************************************************************ */ /* Function: ConUnInit */ /* Used to Uninitialize the Console */ /* ************************************************************ */ int ConUnInit( void ) { CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo; if ( hConsole == NULL ) return 0; if (!GetConsoleScreenBufferInfo(hConsole, &ConsoleInfo)) return 0; SetConsoleMode(hConsole,dwSavedAttributes); return 0; } /* ************************************************************ */ /* Function: ConUnInit */ /* Used to Uninitialize the Console */ /* ************************************************************ */ int ConUnInitWithRestore( void ) { DWORD dwWritten; COORD Coord ; CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo; if ( hConsole == NULL ) return 0; if (!GetConsoleScreenBufferInfo(hConsole, &ConsoleInfo)) return 0; SetConsoleMode(hConsole,dwSavedAttributes); Coord = ConsoleInfo.dwCursorPosition; Coord.X = 0; DWORD dwNumChar = (ConsoleInfo.dwSize.Y - ConsoleInfo.dwCursorPosition.Y) * ConsoleInfo.dwSize.X; FillConsoleOutputCharacter(hConsole, ' ', dwNumChar, Coord, &dwWritten); FillConsoleOutputAttribute(hConsole, wStartingAttributes, dwNumChar, Coord, &dwWritten); SetConsoleTextAttribute( hConsole, wStartingAttributes ); return 0; } // BLR - rewrite of ConSetScreenSize that doesn't alter buffer size BOOL ConSetScreenRect( int xSize, int ySize ) { CONSOLE_SCREEN_BUFFER_INFO csbi; /* hold current console buffer info */ BOOL bSuccess = TRUE; SMALL_RECT srWindowRect; /* hold the new console size */ COORD coordScreen; bSuccess = GetConsoleScreenBufferInfo(hConsole, &csbi); /* get the largest size we can size the console window to */ coordScreen = GetLargestConsoleWindowSize(hConsole); /* 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(hConsole, coordScreen); if (bSuccess) bSuccess = SetConsoleWindowInfo(hConsole, TRUE, &srWindowRect); } else { bSuccess = SetConsoleWindowInfo(hConsole, TRUE, &srWindowRect); if (bSuccess) bSuccess = SetConsoleScreenBufferSize(hConsole, coordScreen); } if (bSuccess) ConSaveViewRect(); /* if the current buffer *is* the size we want, don't do anything! */ return bSuccess; } BOOL ConSetScreenSize( int xSize, int ySize ) { CONSOLE_SCREEN_BUFFER_INFO csbi; /* hold current console buffer info */ BOOL bSuccess = TRUE; SMALL_RECT srWindowRect; /* hold the new console size */ COORD coordScreen; bSuccess = GetConsoleScreenBufferInfo(hConsole, &csbi); /* get the largest size we can size the console window to */ coordScreen = GetLargestConsoleWindowSize(hConsole); /* 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(hConsole, TRUE, &srWindowRect); if (bSuccess) { bSuccess = SetConsoleScreenBufferSize(hConsole, 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(hConsole, coordScreen); if (bSuccess) bSuccess = SetConsoleWindowInfo(hConsole, TRUE, &srWindowRect); } if (bSuccess) ConSaveViewRect(); /* if the current buffer *is* the size we want, don't do anything! */ return bSuccess; } /* ************************************************************ */ /* Function: ConRedrawScreen */ /* Redraws the saved screen */ /* ************************************************************ */ DWORD ConRedrawScreen( void ) { PCHAR_INFO pInfo; CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo; int i; if ( pSavedScreen == NULL ) return 1; if (!GetConsoleScreenBufferInfo(hConsole, &ConsoleInfo)) return 1; pInfo = (PCHAR_INFO)pSavedScreen; for ( i = 0; i < (ConsoleInfo.dwSize.X * ConsoleInfo.dwSize.Y); i++ ) { pInfo++; } return 0; } bool fFirstTime = true; /* ************************************************************ */ /* Function: ConSetAttributes */ /* Used to set the Color of the console and other attributes */ /* 6/21/99 BLH commented out INTENSITY FLAGS for cyan, magenta, and yellow */ /* it appears that they weren't commented out when the check for intensity was added - since i'm not sure why we would explicitly state high intensity for those colors /* ************************************************************ */ void ConSetAttribute( int *iParam, int iParamCount ) { int iAttr; int i; iAttr = 0; if (iParamCount < 1) SetConsoleTextAttribute(hConsole,FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); else { for (i=0;i