📄 conio.c
字号:
{
Buff->CurrentY = 0;
}
ClearLineBuffer(Buff);
UpdateRect->left = 0;
UpdateRect->right = Buff->MaxX - 1;
if (UpdateRect->top == (LONG)Buff->CurrentY)
{
if (++UpdateRect->top == Buff->MaxY)
{
UpdateRect->top = 0;
}
}
UpdateRect->bottom = Buff->CurrentY;
}
static NTSTATUS FASTCALL
ConioWriteConsole(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER Buff,
CHAR *Buffer, DWORD Length, BOOL Attrib)
{
UINT i;
DWORD Offset;
RECT UpdateRect;
LONG CursorStartX, CursorStartY;
UINT ScrolledLines;
ConioPhysicalToLogical(Buff, Buff->CurrentX, Buff->CurrentY, &CursorStartX, &CursorStartY);
UpdateRect.left = Buff->MaxX;
UpdateRect.top = Buff->CurrentY;
UpdateRect.right = -1;
UpdateRect.bottom = Buff->CurrentY;
ScrolledLines = 0;
for (i = 0; i < Length; i++)
{
if (Buff->Mode & ENABLE_PROCESSED_OUTPUT)
{
/* --- LF --- */
if (Buffer[i] == '\n')
{
Buff->CurrentX = 0;
ConioNextLine(Buff, &UpdateRect, &ScrolledLines);
continue;
}
/* --- BS --- */
else if (Buffer[i] == '\b')
{
/* Only handle BS if we're not on the first pos of the first line */
if (0 != Buff->CurrentX || Buff->ShowY != Buff->CurrentY)
{
if (0 == Buff->CurrentX)
{
/* slide virtual position up */
Buff->CurrentX = Buff->MaxX - 1;
if (0 == Buff->CurrentY)
{
Buff->CurrentY = Buff->MaxY;
}
else
{
Buff->CurrentY--;
}
if ((0 == UpdateRect.top && UpdateRect.bottom < (LONG)Buff->CurrentY)
|| (0 != UpdateRect.top && (LONG)Buff->CurrentY < UpdateRect.top))
{
UpdateRect.top = Buff->CurrentY;
}
}
else
{
Buff->CurrentX--;
}
Offset = 2 * ((Buff->CurrentY * Buff->MaxX) + Buff->CurrentX);
SET_CELL_BUFFER(Buff, Offset, ' ', Buff->DefaultAttrib);
UpdateRect.left = min(UpdateRect.left, (LONG) Buff->CurrentX);
UpdateRect.right = max(UpdateRect.right, (LONG) Buff->CurrentX);
}
continue;
}
/* --- CR --- */
else if (Buffer[i] == '\r')
{
Buff->CurrentX = 0;
UpdateRect.left = min(UpdateRect.left, (LONG) Buff->CurrentX);
UpdateRect.right = max(UpdateRect.right, (LONG) Buff->CurrentX);
continue;
}
/* --- TAB --- */
else if (Buffer[i] == '\t')
{
UINT EndX;
UpdateRect.left = min(UpdateRect.left, (LONG)Buff->CurrentX);
EndX = (Buff->CurrentX + 8) & ~7;
if (EndX > Buff->MaxX)
{
EndX = Buff->MaxX;
}
Offset = 2 * (((Buff->CurrentY * Buff->MaxX)) + Buff->CurrentX);
while (Buff->CurrentX < EndX)
{
Buff->Buffer[Offset] = ' ';
Offset += 2;
Buff->CurrentX++;
}
UpdateRect.right = max(UpdateRect.right, (LONG) Buff->CurrentX - 1);
if (Buff->CurrentX == Buff->MaxX)
{
if (Buff->Mode & ENABLE_WRAP_AT_EOL_OUTPUT)
{
Buff->CurrentX = 0;
ConioNextLine(Buff, &UpdateRect, &ScrolledLines);
}
else
{
Buff->CurrentX--;
}
}
continue;
}
}
UpdateRect.left = min(UpdateRect.left, (LONG)Buff->CurrentX);
UpdateRect.right = max(UpdateRect.right, (LONG) Buff->CurrentX);
Offset = 2 * (((Buff->CurrentY * Buff->MaxX)) + Buff->CurrentX);
Buff->Buffer[Offset++] = Buffer[i];
if (Attrib)
{
Buff->Buffer[Offset] = Buff->DefaultAttrib;
}
Buff->CurrentX++;
if (Buff->CurrentX == Buff->MaxX)
{
if (Buff->Mode & ENABLE_WRAP_AT_EOL_OUTPUT)
{
Buff->CurrentX = 0;
ConioNextLine(Buff, &UpdateRect, &ScrolledLines);
}
else
{
Buff->CurrentX = CursorStartX;
}
}
}
ConioPhysicalToLogical(Buff, UpdateRect.left, UpdateRect.top, &(UpdateRect.left),
&(UpdateRect.top));
ConioPhysicalToLogical(Buff, UpdateRect.right, UpdateRect.bottom, &(UpdateRect.right),
&(UpdateRect.bottom));
if (! ConioIsRectEmpty(&UpdateRect) && NULL != Console && Buff == Console->ActiveBuffer)
{
ConioWriteStream(Console, &UpdateRect, CursorStartX, CursorStartY, ScrolledLines,
Buffer, Length);
}
return STATUS_SUCCESS;
}
CSR_API(CsrReadConsole)
{
PLIST_ENTRY CurrentEntry;
ConsoleInput *Input;
PUCHAR Buffer;
PWCHAR UnicodeBuffer;
ULONG i;
ULONG nNumberOfCharsToRead, CharSize;
PCSRSS_CONSOLE Console;
NTSTATUS Status;
DPRINT("CsrReadConsole\n");
CharSize = (Request->Data.ReadConsoleRequest.Unicode ? sizeof(WCHAR) : sizeof(CHAR));
/* truncate length to CSRSS_MAX_READ_CONSOLE_REQUEST */
nNumberOfCharsToRead = min(Request->Data.ReadConsoleRequest.NrCharactersToRead, CSRSS_MAX_READ_CONSOLE / CharSize);
Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
Buffer = Request->Data.ReadConsoleRequest.Buffer;
UnicodeBuffer = (PWCHAR)Buffer;
Status = ConioLockConsole(ProcessData, Request->Data.ReadConsoleRequest.ConsoleHandle,
&Console);
if (! NT_SUCCESS(Status))
{
return Request->Status = Status;
}
Request->Data.ReadConsoleRequest.EventHandle = ProcessData->ConsoleEvent;
for (i = 0; i < nNumberOfCharsToRead && Console->InputEvents.Flink != &Console->InputEvents; i++)
{
/* remove input event from queue */
CurrentEntry = RemoveHeadList(&Console->InputEvents);
if (IsListEmpty(&Console->InputEvents))
{
CHECKPOINT;
ResetEvent(Console->ActiveEvent);
}
Input = CONTAINING_RECORD(CurrentEntry, ConsoleInput, ListEntry);
/* only pay attention to valid ascii chars, on key down */
if (KEY_EVENT == Input->InputEvent.EventType
&& Input->InputEvent.Event.KeyEvent.bKeyDown
&& Input->InputEvent.Event.KeyEvent.uChar.AsciiChar != '\0')
{
/*
* backspace handling - if we are in charge of echoing it then we handle it here
* otherwise we treat it like a normal char.
*/
if ('\b' == Input->InputEvent.Event.KeyEvent.uChar.AsciiChar && 0
!= (Console->Mode & ENABLE_ECHO_INPUT))
{
/* echo if it has not already been done, and either we or the client has chars to be deleted */
if (! Input->Echoed
&& (0 != i || Request->Data.ReadConsoleRequest.nCharsCanBeDeleted))
{
ConioWriteConsole(Console, Console->ActiveBuffer,
&Input->InputEvent.Event.KeyEvent.uChar.AsciiChar, 1, TRUE);
}
if (0 != i)
{
i -= 2; /* if we already have something to return, just back it up by 2 */
}
else
{ /* otherwise, return STATUS_NOTIFY_CLEANUP to tell client to back up its buffer */
Console->WaitingChars--;
ConioUnlockConsole(Console);
HeapFree(Win32CsrApiHeap, 0, Input);
Request->Data.ReadConsoleRequest.NrCharactersRead = 0;
Request->Status = STATUS_NOTIFY_CLEANUP;
return STATUS_NOTIFY_CLEANUP;
}
Request->Data.ReadConsoleRequest.nCharsCanBeDeleted--;
Input->Echoed = TRUE; /* mark as echoed so we don't echo it below */
}
/* do not copy backspace to buffer */
else
{
if(Request->Data.ReadConsoleRequest.Unicode)
UnicodeBuffer[i] = Input->InputEvent.Event.KeyEvent.uChar.AsciiChar; /* FIXME */
else
Buffer[i] = Input->InputEvent.Event.KeyEvent.uChar.AsciiChar;
}
/* echo to screen if enabled and we did not already echo the char */
if (0 != (Console->Mode & ENABLE_ECHO_INPUT)
&& ! Input->Echoed
&& '\r' != Input->InputEvent.Event.KeyEvent.uChar.AsciiChar)
{
ConioWriteConsole(Console, Console->ActiveBuffer,
&Input->InputEvent.Event.KeyEvent.uChar.AsciiChar, 1, TRUE);
}
}
else
{
i--;
}
Console->WaitingChars--;
HeapFree(Win32CsrApiHeap, 0, Input);
}
Request->Data.ReadConsoleRequest.NrCharactersRead = i;
if (0 == i)
{
Request->Status = STATUS_PENDING; /* we didn't read anything */
}
else if (0 != (Console->Mode & ENABLE_LINE_INPUT))
{
if (0 == Console->WaitingLines ||
(Request->Data.ReadConsoleRequest.Unicode ? (L'\n' != UnicodeBuffer[i - 1]) : ('\n' != Buffer[i - 1])))
{
Request->Status = STATUS_PENDING; /* line buffered, didn't get a complete line */
}
else
{
Console->WaitingLines--;
Request->Status = STATUS_SUCCESS; /* line buffered, did get a complete line */
}
}
else
{
Request->Status = STATUS_SUCCESS; /* not line buffered, did read something */
}
if (Request->Status == STATUS_PENDING)
{
Console->EchoCount = nNumberOfCharsToRead - i;
}
else
{
Console->EchoCount = 0; /* if the client is no longer waiting on input, do not echo */
}
ConioUnlockConsole(Console);
if (CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE) + i * CharSize > sizeof(CSR_API_MESSAGE))
{
Request->Header.u1.s1.TotalLength = CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE) + i * CharSize;
Request->Header.u1.s1.DataLength = Request->Header.u1.s1.TotalLength - sizeof(PORT_MESSAGE);
}
return Request->Status;
}
VOID FASTCALL
ConioPhysicalToLogical(PCSRSS_SCREEN_BUFFER Buff,
ULONG PhysicalX,
ULONG PhysicalY,
LONG *LogicalX,
LONG *LogicalY)
{
*LogicalX = PhysicalX;
if (PhysicalY < Buff->ShowY)
{
*LogicalY = Buff->MaxY - Buff->ShowY + PhysicalY;
}
else
{
*LogicalY = PhysicalY - Buff->ShowY;
}
}
BOOLEAN __inline ConioIsEqualRect(
RECT *Rect1,
RECT *Rect2)
{
return ((Rect1->left == Rect2->left) && (Rect1->right == Rect2->right) &&
(Rect1->top == Rect2->top) && (Rect1->bottom == Rect2->bottom));
}
BOOLEAN __inline ConioGetIntersection(
RECT *Intersection,
RECT *Rect1,
RECT *Rect2)
{
if (ConioIsRectEmpty(Rect1) ||
(ConioIsRectEmpty(Rect2)) ||
(Rect1->top > Rect2->bottom) ||
(Rect1->left > Rect2->right) ||
(Rect1->bottom < Rect2->top) ||
(Rect1->right < Rect2->left))
{
/* The rectangles do not intersect */
ConioInitRect(Intersection, 0, -1, 0, -1);
return FALSE;
}
ConioInitRect(Intersection,
max(Rect1->top, Rect2->top),
max(Rect1->left, Rect2->left),
min(Rect1->bottom, Rect2->bottom),
min(Rect1->right, Rect2->right));
return TRUE;
}
BOOLEAN __inline ConioGetUnion(
RECT *Union,
RECT *Rect1,
RECT *Rect2)
{
if (ConioIsRectEmpty(Rect1))
{
if (ConioIsRectEmpty(Rect2))
{
ConioInitRect(Union, 0, -1, 0, -1);
return FALSE;
}
else
{
*Union = *Rect2;
}
}
else if (ConioIsRectEmpty(Rect2))
{
*Union = *Rect1;
}
else
{
ConioInitRect(Union,
min(Rect1->top, Rect2->top),
min(Rect1->left, Rect2->left),
max(Rect1->bottom, Rect2->bottom),
max(Rect1->right, Rect2->right));
}
return TRUE;
}
BOOLEAN __inline ConioSubtractRect(
RECT *Subtraction,
RECT *Rect1,
RECT *Rect2)
{
RECT tmp;
if (ConioIsRectEmpty(Rect1))
{
ConioInitRect(Subtraction, 0, -1, 0, -1);
return FALSE;
}
*Subtraction = *Rect1;
if (ConioGetIntersection(&tmp, Rect1, Rect2))
{
if (ConioIsEqualRect(&tmp, Subtraction))
{
ConioInitRect(Subtraction, 0, -1, 0, -1);
return FALSE;
}
if ((tmp.top == Subtraction->top) && (tmp.bottom == Subtraction->bottom))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -