Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008/////////////////////////////////////////////////////////////////////////////////Telnet Win32 : an ANSI telnet client.//Copyright (C) 1998-2000 Paul Brannan//Copyright (C) 1998 I.Ioannou//Copyright (C) 1997 Brad Johnson////This program is free software; you can redistribute it and/or//modify it under the terms of the GNU General Public License//as published by the Free Software Foundation; either version 2//of the License, or (at your option) any later version.////This program is distributed in the hope that it will be useful,//but WITHOUT ANY WARRANTY; without even the implied warranty of//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the//GNU General Public License for more details.////You should have received a copy of the GNU General Public License//along with this program; if not, write to the Free Software//Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.////I.Ioannou//roryt@hol.gr/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////// Module: tconsole.cpp//// Contents: screen functions//// Product: telnet////// Revisions: Mar. 29, 2000 pbranna@clemson (Paul Brannan)// June 15, 1998 pbranna@clemson.edu// May 16, 1998 pbranna@clemson.edu// 05. Sep.1997 roryt@hol.gr (I.Ioannou)// 11.May,1997 roryt@hol.gr// 06.April,1997 roryt@hol.gr// 30.M�rz.1997 Titus_Boxberg@public.uni-hamburg.de// 5.Dec.1996 jbj@nounname.com// Version 2.0// 02.Apr.1995 igor.milavec@uni-lj.si// Original code/////////////////////////////////////////////////////////////////////////////////
#include "precomp.h"
// argsused doesn't work on MSVC++#ifdef __BORLANDC__#pragma argsused#endif
TConsole::TConsole(HANDLE h) { hConsole = h;
GetConsoleScreenBufferInfo(hConsole, &ConsoleInfo);
// Start with correct colors int color_fg = ini.get_normal_fg(); int color_bg = ini.get_normal_bg(); if(color_fg == -1) color_fg = defaultfg = origfg = ConsoleInfo.wAttributes & 0xF; else defaultfg = origfg = color_fg; if(color_bg == -1) color_bg = defaultbg = origbg = (ConsoleInfo.wAttributes >> 4) & 0xF; else defaultbg = origbg = color_bg; wAttributes = color_fg | (color_bg << 4); reverse = blink = underline = false; SetConsoleTextAttribute(hConsole, wAttributes);
insert_mode = 0;
// Set the screen size SetWindowSize(ini.get_term_width(), ini.get_term_height());
iScrollStart = -1; iScrollEnd = -1;}
TConsole::~TConsole() { wAttributes = origfg | (origbg << 4); SetCursorPosition(0, CON_HEIGHT); SetConsoleTextAttribute(hConsole, wAttributes); WriteCtrlChar('\x0a');}
// Paul Brannan 8/2/98void TConsole::SetWindowSize(int width, int height) { SMALL_RECT sr = { CON_LEFT, CON_TOP, (width == -1) ? CON_RIGHT : CON_LEFT + width - 1, (height == -1) ? CON_BOTTOM : CON_TOP + height - 1 }; ConsoleInfo.dwSize.X = width; if(ConsoleInfo.dwSize.Y < height) ConsoleInfo.dwSize.Y = height; SetConsoleScreenBufferSize(hConsole, ConsoleInfo.dwSize); SetConsoleWindowInfo(hConsole, TRUE, &sr); SetConsoleScreenBufferSize(hConsole, ConsoleInfo.dwSize); sync();}
// Paul Brannan 5/15/98void TConsole::sync() { GetConsoleScreenBufferInfo(hConsole, &ConsoleInfo);}
void TConsole::HighVideo() { wAttributes = wAttributes | (unsigned char) 8;}
void TConsole::LowVideo() { wAttributes = wAttributes & (unsigned char) (0xff-8);}
void TConsole::Normal() { // I.Ioannou 11 May 1997 // Color 7 is correct on some systems (for example Linux) // but not with others (for example SCO) // we must preserve the colors : // 06/04/98 thanks to Paul a .ini parameter from now on
BlinkOff(); UnderlineOff(); if(ini.get_preserve_colors()) { ReverseOff(); LowVideo(); } else { fg = defaultfg; bg = defaultbg; wAttributes = (unsigned char)fg | (bg << 4); reverse = false; }}
void TConsole::SetForeground(unsigned char wAttrib) { if(reverse) bg = wAttrib; else fg = wAttrib; wAttributes = (wAttributes & (unsigned char)0x88) | (unsigned char)fg | (bg << 4);}
void TConsole::SetBackground(unsigned char wAttrib) { if(reverse) fg = wAttrib; else bg = wAttrib; wAttributes = (wAttributes & (unsigned char)0x88) | (unsigned char)fg | (bg << 4);}
// As far as I can tell, there's no such thing as blink in Windows Console.// I tried using some inline asm to turn off high-intensity backgrounds,// but I got a BSOD. Perhaps there is an undocumented function?// (Paul Brannan 6/27/98)void TConsole::BlinkOn() { blink = 1; if(underline) { UlBlinkOn(); } else { if(ini.get_blink_bg() != -1) { wAttributes &= 0x8f; // turn off bg wAttributes |= ini.get_blink_bg() << 4; } if(ini.get_blink_fg() != -1) { wAttributes &= 0xf8; // turn off fg wAttributes |= ini.get_blink_fg(); } if(ini.get_blink_bg() == -1 && ini.get_blink_fg() == -1) wAttributes |= 0x80; }}
// Added by I.Ioannou 06 April, 1997void TConsole::BlinkOff() { blink = 0; if(underline) { UlBlinkOff(); } else { if(ini.get_blink_bg() != -1) { wAttributes &= 0x8f; // turn off bg wAttributes |= defaultbg << 4; } if(ini.get_blink_fg() != -1) { wAttributes &= 0xf8; // turn off fg wAttributes |= defaultfg; } if(ini.get_blink_bg() == -1 && ini.get_blink_fg() == -1) wAttributes &= 0x7f; }}
// Paul Brannan 6/27/98void TConsole::UnderlineOn() { underline = 1; if(blink) { UlBlinkOn(); } else { if(ini.get_underline_bg() != -1) { wAttributes &= 0x8f; // turn off bg wAttributes |= ini.get_underline_bg() << 4; } if(ini.get_underline_fg() != -1) { wAttributes &= 0xf8; // turn off fg wAttributes |= ini.get_underline_fg(); } if(ini.get_underline_bg() == -1 && ini.get_underline_fg() == -1) wAttributes |= 0x80; }}
// Paul Brannan 6/27/98void TConsole::UnderlineOff() { underline = 0; if(blink) { UlBlinkOff(); } else { if(ini.get_blink_bg() != -1) { wAttributes &= 0x8f; // turn off bg wAttributes |= defaultbg << 4; } if(ini.get_blink_fg() != -1) { wAttributes &= 0xf8; // turn off fg wAttributes |= defaultfg; } if(ini.get_blink_bg() == -1 && ini.get_blink_fg() == -1) wAttributes &= 0x7f; }}
// Paul Brannan 6/27/98void TConsole::UlBlinkOn() { if(ini.get_ulblink_bg() != -1) { wAttributes &= 0x8f; // turn off bg wAttributes |= ini.get_ulblink_bg() << 4; } if(ini.get_ulblink_fg() != -1) { wAttributes &= 0xf8; // turn off fg wAttributes |= ini.get_ulblink_fg(); } if(ini.get_ulblink_bg() == -1 && ini.get_ulblink_fg() == -1) wAttributes |= 0x80;}
// Paul Brannan 6/27/98void TConsole::UlBlinkOff() { if(blink) { BlinkOn(); } else if(underline) { UnderlineOn(); } else { Normal(); }}
// Paul Brannan 6/26/98void TConsole::Lightbg() { WORD *pAttributes = new WORD[CON_COLS]; DWORD Result;
// Paul Brannan 8/5/98 // Correction: processing more than one line at a time causes a segfault // if the screen width != 80 for(int i = CON_TOP; i <= CON_BOTTOM; i++) { COORD Coord = {CON_LEFT, i};
ReadConsoleOutputAttribute(hConsole, pAttributes, (DWORD)(CON_COLS), Coord, &Result);
for(DWORD j = 0; j < Result; j++) pAttributes[j] |= 0x80;
WriteConsoleOutputAttribute(hConsole, pAttributes, Result, Coord, &Result); }
delete[] pAttributes; // clean up
wAttributes |= (unsigned char)0x80; bg |= 8;}
// Paul Brannan 6/26/98void TConsole::Darkbg() { WORD *pAttributes = new WORD[CON_COLS]; DWORD Result;
// Paul Brannan 8/5/98 // Correction: processing more than one line at a time causes a segfault // if the screen width != 80 for(int i = CON_TOP; i <= CON_BOTTOM; i++) { COORD Coord = {CON_LEFT, i};
ReadConsoleOutputAttribute(hConsole, pAttributes, (DWORD)(CON_COLS), Coord, &Result);
for(DWORD j = 0; j < Result; j++) pAttributes[j] &= 0x7f;
WriteConsoleOutputAttribute(hConsole, pAttributes, Result, Coord, &Result); }
delete[] pAttributes; // clean up
wAttributes &= (unsigned char)0x7f; bg &= 7;}
// Added by I.Ioannou 11.May,1997void TConsole::ReverseOn() { if (!reverse) { reverse = true;
// atl : forground attributes without the intensity // ath : backgound attributes without the blink // bl : the blink state // ints : the intensity unsigned char atl = wAttributes & (unsigned char) 0x07; unsigned char ath = wAttributes & (unsigned char) 0x70; unsigned char bl = wAttributes & (unsigned char) 0x80; unsigned char ints = wAttributes & (unsigned char) 0x08; wAttributes = bl | (atl << 4) | ints | (ath >> 4); }}
// Added by I.Ioannou 11.May,1997void TConsole::ReverseOff() { if (reverse) { reverse = false; wAttributes = fg | (bg << 4); }}
unsigned long TConsole::WriteText(const char *pszString, unsigned long cbString) { DWORD Result;
if(insert_mode) { InsertCharacter(cbString); }
WriteConsoleOutputCharacter(hConsole, (char *)pszString, cbString, ConsoleInfo.dwCursorPosition, &Result); FillConsoleOutputAttribute(hConsole, wAttributes, cbString, ConsoleInfo.dwCursorPosition, &Result); return Result;}
// Formerly ConWriteString (Paul Brannan 6/28/98)unsigned long TConsole::WriteStringFast(const char* pszString, unsigned long cbString) { DWORD Result;
SetConsoleTextAttribute(hConsole, wAttributes);
//check to see if the line is longer than the display if (!getLineWrap() && ((unsigned)CON_CUR_X + cbString) >= (unsigned)CON_COLS) { // Take care of the last line last colum exception... // The display scrolls up if you use the normal char out // function even if you only write to the last place // on the line. :-( if ((unsigned)CON_CUR_Y >= (unsigned)CON_HEIGHT) { unsigned long iFakeResult = cbString; cbString = CON_COLS - CON_CUR_X - 1;
// FIX ME !!! This will avoid the exception when cbString // is <= 0 but still doesn't work :-( if (cbString > 0) WriteConsole(hConsole, pszString, cbString, &Result, 0);
COORD dwBufferCoord; dwBufferCoord.X = 0; dwBufferCoord.Y = 0;
CHAR_INFO ciBuffer; ciBuffer.Char.AsciiChar = *(pszString+cbString); ciBuffer.Attributes = wAttributes; SMALL_RECT srWriteRegion; srWriteRegion.Top = (SHORT) CON_BOTTOM; srWriteRegion.Bottom = (SHORT) CON_BOTTOM; srWriteRegion.Left = (SHORT) CON_RIGHT; srWriteRegion.Right = (SHORT) CON_RIGHT;
COORD bufSize = {1,1};
WriteConsoleOutput(hConsole, &ciBuffer, bufSize, dwBufferCoord, &srWriteRegion);
// We need to update the ConsoleInfo struct now (Paul Brannan 5/9/98) ConsoleInfo.dwCursorPosition.X = CON_RIGHT;
return iFakeResult; // Skip the chars that did not fit } // just write the line up to the end else { int iFakeResult = cbString; cbString = CON_COLS - CON_CUR_X;
if(cbString > 0) { WriteConsole(hConsole, pszString, cbString, &Result, 0);
// We need to update the ConsoleInfo struct now (Paul Brannan 5/9/98) ConsoleInfo.dwCursorPosition.X += (unsigned short)Result; }
return iFakeResult; // Skip the chars that did not fit } } else { // If custom scrolling is enabled we must take care of it if(iScrollStart != -1 || iScrollEnd != -1) { return WriteString(pszString, cbString); }
// Apparently VT100 terminals have an invisible "81st" column that // can hold a cursor until another character is printed. I'm not sure // exactly how to handle this, but here's a hack (Paul Brannan 5/28/98) if(ini.get_vt100_mode() && cbString + (unsigned)CON_CUR_X == (unsigned)CON_COLS) {
cbString--; if((long)cbString >= 0) WriteConsole(hConsole, pszString, cbString, &Result, 0);
COORD dwBufferCoord; dwBufferCoord.X = 0; dwBufferCoord.Y = 0;
CHAR_INFO ciBuffer; ciBuffer.Char.AsciiChar = *(pszString+cbString); ciBuffer.Attributes = wAttributes; SMALL_RECT srWriteRegion; srWriteRegion.Top = (SHORT) ConsoleInfo.dwCursorPosition.Y; srWriteRegion.Bottom = (SHORT) ConsoleInfo.dwCursorPosition.Y; srWriteRegion.Left = (SHORT) CON_RIGHT; srWriteRegion.Right = (SHORT) CON_RIGHT;
COORD bufSize = {1,1};
WriteConsoleOutput(hConsole, &ciBuffer, bufSize, dwBufferCoord, &srWriteRegion);
// Update the ConsoleInfo struct ConsoleInfo.dwCursorPosition.X = CON_RIGHT + 1;
return Result + 1; }
// normal line will wrap normally or not to the end of buffer WriteConsole(hConsole, pszString, cbString, &Result, 0);
// We need to update the ConsoleInfo struct now (Paul Brannan 5/9/98) // FIX ME!!! This is susceptible to the same problem as above. // (e.g. we write out 160 characters) ConsoleInfo.dwCursorPosition.X += (unsigned short)Result; while(CON_CUR_X > CON_WIDTH) { ConsoleInfo.dwCursorPosition.X -= ConsoleInfo.dwSize.X; if((unsigned)CON_CUR_Y < (unsigned)CON_HEIGHT) { ConsoleInfo.dwCursorPosition.Y++; } else { // If we aren't at the bottom of the window, then we need to // scroll down (Paul Brannan 4/14/2000) if(ConsoleInfo.srWindow.Bottom < ConsoleInfo.dwSize.Y - 1) { ConsoleInfo.srWindow.Top++; ConsoleInfo.srWindow.Bottom++; ConsoleInfo.dwCursorPosition.Y++; SetConsoleWindowInfo(hConsole, TRUE, &ConsoleInfo.srWindow); } } } }
return Result;
}
unsigned long TConsole::WriteString(const char* pszString, unsigned long cbString) { DWORD Result = 0;
SetConsoleTextAttribute(hConsole, wAttributes);
//check to see if the line is longer than the display if (!getLineWrap()){ unsigned long iFakeResult = cbString; if((CON_CUR_X + cbString) >= (unsigned int)CON_COLS) cbString = CON_COLS - CON_CUR_X; if(cbString > 0) Result = WriteText(pszString, cbString);
// We need to update the ConsoleInfo struct now (Paul Brannan 5/9/98) ConsoleInfo.dwCursorPosition.X += (unsigned short)Result; SetConsoleCursorPosition(hConsole, ConsoleInfo.dwCursorPosition);
return iFakeResult; // Skip the chars that did not fit } else { // Write up to the end of the line unsigned long temp = cbString; if((CON_CUR_X + temp) > (unsigned int)CON_COLS) { temp = CON_COLS - CON_CUR_X; } else { Result = WriteText(pszString, temp); ConsoleInfo.dwCursorPosition.X += (unsigned short)Result; SetConsoleCursorPosition(hConsole, ConsoleInfo.dwCursorPosition); return Result; } if(temp > 0) { Result = WriteText(pszString, temp); ConsoleInfo.dwCursorPosition.X += (unsigned short)Result; temp = (unsigned short)Result; }
// keep writing lines until we get to less than 80 chars left while((temp + (unsigned int)CON_COLS) < cbString) { index(); // LF ConsoleInfo.dwCursorPosition.X = 0; // CR Result = WriteText(&pszString[temp], CON_COLS); temp += (unsigned short)Result; }
// write out the last bit if(temp < cbString) { index(); ConsoleInfo.dwCursorPosition.X = 0; Result = WriteText(&pszString[temp], cbString - temp); temp += (unsigned short)Result; }
// Apparently VT100 terminals have an invisible "81st" column that // can hold a cursor until another character is printed. I'm not sure // exactly how to handle this, but here's a hack (Paul Brannan 5/28/98) if(!ini.get_vt100_mode() && cbString + (unsigned)ConsoleInfo.dwCursorPosition.X == (unsigned int)CON_COLS) { index(); ConsoleInfo.dwCursorPosition.X = 0; }
SetConsoleCursorPosition(hConsole, ConsoleInfo.dwCursorPosition);
return temp; }
return 0;}
// This is for multi-character control strings (Paul Brannan 6/26/98)unsigned long TConsole::WriteCtrlString(const char *pszString, unsigned long cbString) { unsigned long total = 0; while(total < cbString) { unsigned long Result = WriteCtrlChar(*(pszString + total)); if(Result == 0) { Result = WriteStringFast(pszString + total, 1); if(Result == 0) return total; } total += Result; } return total;}
// This is for printing single control characters// WriteCtrlString uses this (Paul Brannan 6/26/98)unsigned long TConsole::WriteCtrlChar(char c) { // The console does not handel the CR/LF chars as we might expect // when using color. The attributes are not set correctly, so we // must interpret them manualy to preserve the colors on the screen.
unsigned long Result = 0; // just in case (Paul Brannan 6/26/98) switch (c) { case '\x09': // horizontal tab SetCursorPosition((((CON_CUR_X/8)+1)*8), CON_CUR_Y); Result = 1; break;
case '\x0a': // line feed index(); Result = 1; break; case '\x0d': // carrage return SetCursorPosition(CON_LEFT, CON_CUR_Y); // move to beginning of line Result = 1; break; case '\b': // backspace // Added support for backspace so the cursor position can be changed // (Paul Brannan 5/25/98) MoveCursorPosition(-1, 0); Result = 1; default : // else just write it like normal break; }
return Result;}
void TConsole::index() { // if on the last line scroll up // This must work with scrolling (Paul Brannan 5/13/98) if(iScrollEnd != -1 && (signed)CON_CUR_Y >= iScrollEnd) { ScrollDown(iScrollStart, iScrollEnd, -1); } else if ((iScrollEnd == -1 && (signed)CON_CUR_Y >= (signed)CON_HEIGHT)) { DWORD Result; WriteConsole(hConsole, "\n", 1, &Result, NULL);
// If we aren't at the bottom of the buffer, then we need to // scroll down (Paul Brannan 4/14/2000) if(iScrollEnd == -1 && ConsoleInfo.srWindow.Bottom < ConsoleInfo.dwSize.Y - 1) { ConsoleInfo.srWindow.Top++; ConsoleInfo.srWindow.Bottom++; ConsoleInfo.dwCursorPosition.Y++; // SetConsoleWindowInfo(hConsole, TRUE, &ConsoleInfo.srWindow); } else { ClearLine(); } } else { // else move cursor down to the next line SetCursorPosition(CON_CUR_X, CON_CUR_Y + 1); }}
void TConsole::reverse_index() { // if on the top line scroll down // This must work with scrolling (Paul Brannan 5/13/98) // We should be comparing against iScrollStart, not iScrollEnd (PB 12/2/98) if (iScrollStart == -1 && (signed)CON_CUR_Y <= 0) { ScrollDown(iScrollStart, -1, 1); } else if (iScrollStart != -1 && (signed)CON_CUR_Y <= iScrollStart) { ScrollDown(iScrollStart, iScrollEnd, 1); } else // else move cursor up to the previous line SetCursorPosition(CON_CUR_X,CON_CUR_Y - 1);}
void TConsole::ScrollDown( int iStartRow , int iEndRow, int bUp ){ CHAR_INFO ciChar; SMALL_RECT srScrollWindow;
// Correction from I.Ioannou 11 May 1997 // check the scroll region if (iStartRow < iScrollStart) iStartRow = iScrollStart;
// Correction from I.Ioannou 11 May 1997 // this will make Top the CON_TOP if ( iStartRow == -1) iStartRow = 0;
// Correction from I.Ioannou 18 Aug 97 if ( iEndRow == -1) { if ( iScrollEnd == -1 ) iEndRow = CON_HEIGHT; else iEndRow = ((CON_HEIGHT <= iScrollEnd) ? CON_HEIGHT : iScrollEnd); } //
if ( iStartRow > CON_HEIGHT) iStartRow = CON_HEIGHT; if ( iEndRow > CON_HEIGHT) iEndRow = CON_HEIGHT;
srScrollWindow.Left = (CON_LEFT); srScrollWindow.Right = (SHORT) (CON_RIGHT); srScrollWindow.Top = (SHORT) (CON_TOP + iStartRow ); srScrollWindow.Bottom = (SHORT) (CON_TOP + iEndRow); // don't subtract 1 (PB 5/28)
ciChar.Char.AsciiChar = ' '; // fill with spaces ciChar.Attributes = wAttributes; // fill with current attrib
// This should speed things up (Paul Brannan 9/2/98) COORD dwDestOrg = {srScrollWindow.Left, srScrollWindow.Top + bUp};
// Note that iEndRow and iStartRow had better not be equal to -1 at this // point. There are four cases to consider for out of bounds. Two of // these cause the scroll window to be cleared; the others cause the // scroll region to be modified. (Paul Brannan 12/3/98) if(dwDestOrg.Y > CON_TOP + iEndRow) { // We are scrolling past the end of the scroll region, so just // clear the window instead (Paul Brannan 12/3/98) ClearWindow(CON_TOP + iStartRow, CON_TOP + iEndRow); return; } else if(dwDestOrg.Y + (iEndRow-iStartRow+1) < CON_TOP + iStartRow) { // We are scrolling past the end of the scroll region, so just // clear the window instead (Paul Brannan 12/3/98) ClearWindow(CON_TOP + iStartRow, CON_TOP + iEndRow); return; } else if(dwDestOrg.Y < CON_TOP + iStartRow) { // Modify the scroll region (Paul Brannan 12/3/98) dwDestOrg.Y = CON_TOP + iStartRow; srScrollWindow.Top -= bUp; } else if(dwDestOrg.Y + (iEndRow-iStartRow+1) > CON_TOP + iEndRow) { // Modify the scroll region (Paul Brannan 12/3/98) srScrollWindow.Bottom -= bUp; }
ScrollConsoleScreenBuffer(hConsole, &srScrollWindow, 0, dwDestOrg, &ciChar);}
// This allows us to clear the screen with an arbitrary character// (Paul Brannan 6/26/98)void TConsole::ClearScreen(char c) { DWORD dwWritten; COORD Coord = {CON_LEFT, CON_TOP}; FillConsoleOutputCharacter(hConsole, c, (DWORD)(CON_COLS)* (DWORD)(CON_LINES), Coord, &dwWritten); FillConsoleOutputAttribute(hConsole, wAttributes, (DWORD)(CON_COLS)* (DWORD)(CON_LINES), Coord, &dwWritten);}
// Same as clear screen, but only affects the scroll regionvoid TConsole::ClearWindow(int iStartRow, int iEndRow, char c) { DWORD dwWritten; COORD Coord = {CON_LEFT, CON_TOP + iStartRow}; FillConsoleOutputCharacter(hConsole, c, (DWORD)(CON_COLS)* (DWORD)(iEndRow-iStartRow+1), Coord, &dwWritten); FillConsoleOutputAttribute(hConsole, wAttributes, (DWORD)(CON_COLS)* (DWORD)(CON_LINES), Coord, &dwWritten);}
// Clear from cursor to end of screenvoid TConsole::ClearEOScreen(char c){ DWORD dwWritten; COORD Coord = {CON_LEFT, CON_TOP + CON_CUR_Y + 1}; FillConsoleOutputCharacter(hConsole, c, (DWORD)(CON_COLS)* (DWORD)(CON_HEIGHT - CON_CUR_Y), Coord, &dwWritten); FillConsoleOutputAttribute(hConsole, wAttributes, (DWORD)(CON_COLS)* (DWORD)(CON_LINES - CON_CUR_Y), Coord, &dwWritten); ClearEOLine();}
// Clear from beginning of screen to cursorvoid TConsole::ClearBOScreen(char c){ DWORD dwWritten; COORD Coord = {CON_LEFT, CON_TOP}; FillConsoleOutputCharacter(hConsole, c, (DWORD)(CON_COLS)* (DWORD)(CON_CUR_Y), Coord, &dwWritten); FillConsoleOutputAttribute(hConsole, wAttributes, (DWORD)(CON_COLS)* (DWORD)(CON_CUR_Y), Coord, &dwWritten); ClearBOLine();}
void TConsole::ClearLine(char c){ DWORD dwWritten; COORD Coord = {CON_LEFT, CON_TOP + CON_CUR_Y}; FillConsoleOutputCharacter(hConsole, c, (DWORD)(CON_COLS), Coord, &dwWritten); FillConsoleOutputAttribute(hConsole, wAttributes, (DWORD)(CON_COLS), Coord, &dwWritten); GetConsoleScreenBufferInfo(hConsole, &ConsoleInfo);}
void TConsole::ClearEOLine(char c){ DWORD dwWritten; COORD Coord = {CON_LEFT + CON_CUR_X, CON_TOP + CON_CUR_Y}; FillConsoleOutputAttribute(hConsole, wAttributes, (DWORD)(CON_RIGHT - CON_CUR_X) +1, Coord, &dwWritten); FillConsoleOutputCharacter(hConsole, c, (DWORD)(CON_RIGHT - CON_CUR_X) +1, Coord, &dwWritten); GetConsoleScreenBufferInfo(hConsole, &ConsoleInfo);}
void TConsole::ClearBOLine(char c){ DWORD dwWritten; COORD Coord = {CON_LEFT, CON_TOP + CON_CUR_Y}; FillConsoleOutputCharacter(hConsole, c, (DWORD)(CON_CUR_X) + 1, Coord, &dwWritten); FillConsoleOutputAttribute(hConsole, wAttributes, (DWORD)(CON_CUR_X) + 1, Coord, &dwWritten); GetConsoleScreenBufferInfo(hConsole, &ConsoleInfo);}
// Inserts blank lines to the cursor-y-position// scrolls down the rest. CURSOR MOVEMENT (to Col#1) ???void TConsole::InsertLine(int numlines){ COORD to; SMALL_RECT from; SMALL_RECT clip; CHAR_INFO fill; int acty;
// Rest of screen would be deleted if ( (acty = GetCursorY()) >= CON_LINES - numlines ) { ClearEOScreen(); // delete rest of screen return; } /* IF */
// Else scroll down the part of the screen which is below the // cursor. from.Left = CON_LEFT; from.Top = CON_TOP + (SHORT)acty; from.Right = CON_LEFT + (SHORT)CON_COLS; from.Bottom = CON_TOP + (SHORT)CON_LINES;
clip = from; to.X = 0; to.Y = (SHORT)(from.Top + numlines);
fill.Char.AsciiChar = ' '; fill.Attributes = 7; // WHICH ATTRIBUTES TO TAKE FOR BLANK LINE ??
ScrollConsoleScreenBuffer(hConsole, &from, &clip, to, &fill);} /* InsertLine */
// Inserts blank characters under the cursorvoid TConsole::InsertCharacter(int numchar){ int actx; SMALL_RECT from; SMALL_RECT clip; COORD to; CHAR_INFO fill;
if ( (actx = GetCursorX()) >= CON_COLS - numchar ) { ClearEOLine(); return; } /* IF */
from.Left = CON_LEFT + (SHORT)actx; from.Top = CON_TOP + (SHORT)GetCursorY(); from.Right = CON_LEFT + (SHORT)CON_COLS; from.Bottom = CON_TOP + (SHORT)from.Top;
clip = from; to.X = (SHORT)(actx + numchar); to.Y = from.Top;
fill.Char.AsciiChar = ' '; fill.Attributes = wAttributes; // WHICH ATTRIBUTES TO TAKE FOR BLANK CHAR ??
ScrollConsoleScreenBuffer(hConsole, &from, &clip, to, &fill);} /* InsertCharacter */
// Deletes characters under the cursor// Note that there are cases in which all the following lines should shift by// a character, but we don't handle these. This could break some// VT102-applications, but it shouldn't be too much of an issue.void TConsole::DeleteCharacter(int numchar){ int actx; SMALL_RECT from; SMALL_RECT clip; COORD to; CHAR_INFO fill;
if ( (actx = GetCursorX()) >= CON_COLS - numchar ) { ClearEOLine(); return; } /* IF */
from.Left = CON_LEFT + (SHORT)actx; from.Top = CON_TOP + (SHORT)GetCursorY(); from.Right = CON_LEFT + (SHORT)CON_COLS; from.Bottom = CON_TOP + from.Top;
clip = from; to.X = (SHORT)(actx - numchar); to.Y = from.Top;
fill.Char.AsciiChar = ' '; fill.Attributes = wAttributes; // WHICH ATTRIBUTES TO TAKE FOR BLANK CHAR ??
ScrollConsoleScreenBuffer(hConsole, &from, &clip, to, &fill);} /* DeleteCharacter */
void TConsole::SetRawCursorPosition(int x, int y) { if (x > CON_WIDTH) x = CON_WIDTH; if (x < 0) x = 0; if (y > CON_HEIGHT) y = CON_HEIGHT; if (y < 0) y = 0; COORD Coord = {(short)(CON_LEFT + x), (short)(CON_TOP + y)}; SetConsoleCursorPosition(hConsole, Coord);
// Update the ConsoleInfo struct (Paul Brannan 5/9/98) ConsoleInfo.dwCursorPosition.Y = Coord.Y; ConsoleInfo.dwCursorPosition.X = Coord.X;
// bug fix in case we went too far (Paul Brannan 5/25/98) if(ConsoleInfo.dwCursorPosition.X < CON_LEFT) ConsoleInfo.dwCursorPosition.X = CON_LEFT; if(ConsoleInfo.dwCursorPosition.X > CON_RIGHT) ConsoleInfo.dwCursorPosition.X = CON_RIGHT; if(ConsoleInfo.dwCursorPosition.Y < CON_TOP) ConsoleInfo.dwCursorPosition.Y = CON_TOP; if(ConsoleInfo.dwCursorPosition.Y > CON_BOTTOM) ConsoleInfo.dwCursorPosition.Y = CON_BOTTOM;}
// The new SetCursorPosition takes scroll regions into consideration// (Paul Brannan 6/27/98)void TConsole::SetCursorPosition(int x, int y) { if (x > CON_WIDTH) x = CON_WIDTH; if (x < 0) x = 0; if(iScrollEnd != -1) { if(y > iScrollEnd) y = iScrollEnd; } else { if(y > CON_HEIGHT) y = CON_HEIGHT; } if(iScrollStart != -1) { if(y < iScrollStart) y = iScrollStart; } else { if(y < 0) y = 0; }
COORD Coord = {(short)(CON_LEFT + x), (short)(CON_TOP + y)}; SetConsoleCursorPosition(hConsole, Coord);
// Update the ConsoleInfo struct ConsoleInfo.dwCursorPosition.Y = Coord.Y; ConsoleInfo.dwCursorPosition.X = Coord.X;}
void TConsole::MoveCursorPosition(int x, int y) { SetCursorPosition(CON_CUR_X + x, CON_CUR_Y + y);}
void TConsole::SetExtendedMode(int iFunction, BOOL bEnable){ // Probably should do something here... // Should change the screen mode, but do we need this?}
void TConsole::SetScroll(int start, int end) { iScrollStart = start; iScrollEnd = end;}
void TConsole::Beep() { if(ini.get_do_beep()) { if(!ini.get_speaker_beep()) printit("\a"); else ::Beep(400, 100); }}
void TConsole::SetCursorSize(int pct) { CONSOLE_CURSOR_INFO ci = {(pct != 0)?pct:1, pct != 0}; SetConsoleCursorInfo(hConsole, &ci);}
void saveScreen(CHAR_INFO *chiBuffer) { HANDLE hStdout; CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo; SMALL_RECT srctReadRect; COORD coordBufSize; COORD coordBufCoord;
hStdout = GetStdHandle(STD_OUTPUT_HANDLE); GetConsoleScreenBufferInfo(hStdout, &ConsoleInfo);
srctReadRect.Top = CON_TOP; /* top left: row 0, col 0 */ srctReadRect.Left = CON_LEFT; srctReadRect.Bottom = CON_BOTTOM; /* bot. right: row 1, col 79 */ srctReadRect.Right = CON_RIGHT;
coordBufSize.Y = CON_BOTTOM-CON_TOP+1; coordBufSize.X = CON_RIGHT-CON_LEFT+1;
coordBufCoord.X = CON_TOP; coordBufCoord.Y = CON_LEFT;
ReadConsoleOutput( hStdout, /* screen buffer to read from */ chiBuffer, /* buffer to copy into */ coordBufSize, /* col-row size of chiBuffer */
coordBufCoord, /* top left dest. cell in chiBuffer */ &srctReadRect); /* screen buffer source rectangle */}
void restoreScreen(CHAR_INFO *chiBuffer) { HANDLE hStdout; CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo; SMALL_RECT srctReadRect; COORD coordBufSize; COORD coordBufCoord;
hStdout = GetStdHandle(STD_OUTPUT_HANDLE); GetConsoleScreenBufferInfo(hStdout, &ConsoleInfo);
// restore screen srctReadRect.Top = CON_TOP; /* top left: row 0, col 0 */ srctReadRect.Left = CON_LEFT; srctReadRect.Bottom = CON_BOTTOM; /* bot. right: row 1, col 79 */ srctReadRect.Right = CON_RIGHT;
coordBufSize.Y = CON_BOTTOM-CON_TOP+1; coordBufSize.X = CON_RIGHT-CON_LEFT+1;
coordBufCoord.X = CON_TOP; coordBufCoord.Y = CON_LEFT; WriteConsoleOutput( hStdout, /* screen buffer to write to */ chiBuffer, /* buffer to copy from */ coordBufSize, /* col-row size of chiBuffer */ coordBufCoord, /* top left src cell in chiBuffer */ &srctReadRect); /* dest. screen buffer rectangle */ // end restore screen
}
CHAR_INFO* newBuffer() { CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo; HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE); GetConsoleScreenBufferInfo(hStdout, &ConsoleInfo); CHAR_INFO * chiBuffer; chiBuffer = new CHAR_INFO[(CON_BOTTOM-CON_TOP+1)*(CON_RIGHT-CON_LEFT+1)]; return chiBuffer;}
void deleteBuffer(CHAR_INFO* chiBuffer) { delete[] chiBuffer;}