tconsole.cpp
来自「一个类似windows」· C++ 代码 · 共 1,009 行 · 第 1/3 页
CPP
1,009 行
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(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;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?