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 + -
显示快捷键?