mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
414 lines
9.2 KiB
414 lines
9.2 KiB
/*++
|
|
|
|
Copyright (c) 1990 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
cursor.c
|
|
|
|
Abstract:
|
|
|
|
This file implements the NT console server cursor routines.
|
|
|
|
Author:
|
|
|
|
Therese Stowell (thereses) 5-Dec-1990
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
#ifdef i386
|
|
extern HANDLE ScreenHandle;
|
|
#endif
|
|
|
|
//#define PROFILE_GDI
|
|
#ifdef PROFILE_GDI
|
|
LONG InvertCount=0;
|
|
#define INVERT_CALL InvertCount+=1
|
|
#else
|
|
#define INVERT_CALL
|
|
#endif
|
|
|
|
VOID
|
|
InvertPixels(
|
|
IN PSCREEN_INFORMATION ScreenInfo
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine inverts the cursor pixels, making it either visible or
|
|
invisible.
|
|
|
|
Arguments:
|
|
|
|
ScreenInfo - pointer to screen info structure.
|
|
|
|
Return Value:
|
|
|
|
none.
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG CursorYSize;
|
|
INVERT_CALL;
|
|
CursorYSize = ScreenInfo->BufferInfo.TextInfo.CursorYSize;
|
|
if (ScreenInfo->BufferInfo.TextInfo.DoubleCursor) {
|
|
if (ScreenInfo->BufferInfo.TextInfo.CursorSize > 50)
|
|
CursorYSize = CursorYSize >> 1;
|
|
else
|
|
CursorYSize = CursorYSize << 1;
|
|
}
|
|
PatBlt(ScreenInfo->Console->hDC,
|
|
(ScreenInfo->BufferInfo.TextInfo.CursorPosition.X-ScreenInfo->Window.Left)*ScreenInfo->BufferInfo.TextInfo.FontSize.X,
|
|
(ScreenInfo->BufferInfo.TextInfo.CursorPosition.Y-ScreenInfo->Window.Top)*ScreenInfo->BufferInfo.TextInfo.FontSize.Y+(CURSOR_Y_OFFSET_IN_PIXELS(ScreenInfo->BufferInfo.TextInfo.FontSize.Y,CursorYSize)),
|
|
ScreenInfo->BufferInfo.TextInfo.FontSize.X,
|
|
CursorYSize,
|
|
DSTINVERT
|
|
);
|
|
GdiFlush();
|
|
}
|
|
|
|
VOID
|
|
ConsoleShowCursor(
|
|
IN PSCREEN_INFORMATION ScreenInfo
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine makes the cursor visible both in the data structures
|
|
and on the screen.
|
|
|
|
Arguments:
|
|
|
|
ScreenInfo - pointer to screen info structure.
|
|
|
|
Return Value:
|
|
|
|
none.
|
|
|
|
--*/
|
|
|
|
{
|
|
if (ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER) {
|
|
ASSERT (ScreenInfo->BufferInfo.TextInfo.UpdatingScreen>0);
|
|
if (--ScreenInfo->BufferInfo.TextInfo.UpdatingScreen == 0) {
|
|
ScreenInfo->BufferInfo.TextInfo.CursorOn = FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
VOID
|
|
ConsoleHideCursor(
|
|
IN PSCREEN_INFORMATION ScreenInfo
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine makes the cursor invisible both in the data structures
|
|
and on the screen.
|
|
|
|
Arguments:
|
|
|
|
ScreenInfo - pointer to screen info structure.
|
|
|
|
Return Value:
|
|
|
|
none.
|
|
|
|
--*/
|
|
|
|
{
|
|
if (ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER) {
|
|
if (++ScreenInfo->BufferInfo.TextInfo.UpdatingScreen == 1) {
|
|
if (ScreenInfo->BufferInfo.TextInfo.CursorVisible &&
|
|
ScreenInfo->BufferInfo.TextInfo.CursorOn &&
|
|
ScreenInfo->Console->CurrentScreenBuffer == ScreenInfo &&
|
|
!(ScreenInfo->Console->Flags & CONSOLE_IS_ICONIC)) {
|
|
InvertPixels(ScreenInfo);
|
|
ScreenInfo->BufferInfo.TextInfo.CursorOn = FALSE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
NTSTATUS
|
|
SetCursorInformation(
|
|
IN PSCREEN_INFORMATION ScreenInfo,
|
|
ULONG Size,
|
|
BOOLEAN Visible
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine sets the cursor size and visibility both in the data structures
|
|
and on the screen.
|
|
|
|
Arguments:
|
|
|
|
ScreenInfo - pointer to screen info structure.
|
|
|
|
Size - cursor size
|
|
|
|
Visible - cursor visibility
|
|
|
|
Return Value:
|
|
|
|
Status
|
|
|
|
--*/
|
|
|
|
{
|
|
if (ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER) {
|
|
ConsoleHideCursor(ScreenInfo);
|
|
ScreenInfo->BufferInfo.TextInfo.CursorSize = Size;
|
|
ScreenInfo->BufferInfo.TextInfo.CursorVisible = Visible;
|
|
ScreenInfo->BufferInfo.TextInfo.CursorYSize = (WORD)CURSOR_SIZE_IN_PIXELS(ScreenInfo->BufferInfo.TextInfo.FontSize.Y,ScreenInfo->BufferInfo.TextInfo.CursorSize);
|
|
#ifdef i386
|
|
if ((!(ScreenInfo->Console->Flags & CONSOLE_VDM_REGISTERED)) &&
|
|
ScreenInfo->Console->FullScreenFlags & CONSOLE_FULLSCREEN_HARDWARE) {
|
|
SetCursorInformationHW(ScreenInfo,Size,Visible);
|
|
}
|
|
#endif
|
|
ConsoleShowCursor(ScreenInfo);
|
|
}
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS
|
|
SetCursorMode(
|
|
IN PSCREEN_INFORMATION ScreenInfo,
|
|
BOOL DoubleCursor
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine sets a flag saying whether the cursor should be displayed
|
|
with it's default size or it should be modified to indicate the
|
|
insert/overtype mode has changed.
|
|
|
|
Arguments:
|
|
|
|
ScreenInfo - pointer to screen info structure.
|
|
|
|
DoubleCursor - should we indicated non-normal mode
|
|
|
|
Return Value:
|
|
|
|
Status
|
|
|
|
--*/
|
|
|
|
{
|
|
if ((ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER) &&
|
|
(ScreenInfo->BufferInfo.TextInfo.DoubleCursor != DoubleCursor)) {
|
|
ConsoleHideCursor(ScreenInfo);
|
|
ScreenInfo->BufferInfo.TextInfo.DoubleCursor = DoubleCursor;
|
|
#ifdef i386
|
|
if ((!(ScreenInfo->Console->Flags & CONSOLE_VDM_REGISTERED)) &&
|
|
ScreenInfo->Console->FullScreenFlags & CONSOLE_FULLSCREEN_HARDWARE) {
|
|
SetCursorInformationHW(ScreenInfo,
|
|
ScreenInfo->BufferInfo.TextInfo.CursorSize,
|
|
ScreenInfo->BufferInfo.TextInfo.CursorVisible);
|
|
}
|
|
#endif
|
|
ConsoleShowCursor(ScreenInfo);
|
|
}
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
VOID
|
|
CursorTimerRoutine(
|
|
IN PSCREEN_INFORMATION ScreenInfo
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called when the timer in the console with the focus
|
|
goes off. It blinks the cursor.
|
|
|
|
Arguments:
|
|
|
|
ScreenInfo - pointer to screen info structure.
|
|
|
|
Return Value:
|
|
|
|
none.
|
|
|
|
--*/
|
|
|
|
{
|
|
if (!(ScreenInfo->Console->Flags & CONSOLE_HAS_FOCUS))
|
|
return;
|
|
|
|
if (ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER) {
|
|
|
|
// if the DelayCursor flag has been set, wait one more tick before toggle.
|
|
// This is used to guarantee the cursor is on for a finite period of time
|
|
// after a move and off for a finite period of time after a WriteString
|
|
|
|
if (ScreenInfo->BufferInfo.TextInfo.DelayCursor) {
|
|
ScreenInfo->BufferInfo.TextInfo.DelayCursor = FALSE;
|
|
return;
|
|
}
|
|
|
|
if (ScreenInfo->BufferInfo.TextInfo.CursorVisible &&
|
|
!ScreenInfo->BufferInfo.TextInfo.UpdatingScreen) {
|
|
InvertPixels(ScreenInfo);
|
|
ScreenInfo->BufferInfo.TextInfo.CursorOn = !ScreenInfo->BufferInfo.TextInfo.CursorOn;
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef i386
|
|
NTSTATUS
|
|
SetCursorPositionHW(
|
|
IN OUT PSCREEN_INFORMATION ScreenInfo,
|
|
IN COORD Position
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine moves the cursor.
|
|
|
|
Arguments:
|
|
|
|
ScreenInfo - Pointer to screen buffer information.
|
|
|
|
Position - Contains the new position of the cursor in screen buffer
|
|
coordinates.
|
|
|
|
Return Value:
|
|
|
|
none.
|
|
|
|
--*/
|
|
|
|
{
|
|
VIDEO_CURSOR_POSITION CursorPosition;
|
|
|
|
// set cursor position
|
|
|
|
CursorPosition.Column = Position.X - ScreenInfo->Window.Left;
|
|
CursorPosition.Row = Position.Y - ScreenInfo->Window.Top;
|
|
|
|
return NtUserFullscreenControl(FullscreenControlSetCursorPosition,
|
|
(PVOID)&CursorPosition,
|
|
sizeof(CursorPosition),
|
|
NULL,
|
|
0);
|
|
}
|
|
#endif
|
|
|
|
NTSTATUS
|
|
SetCursorPosition(
|
|
IN OUT PSCREEN_INFORMATION ScreenInfo,
|
|
IN COORD Position,
|
|
IN BOOL TurnOn
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine sets the cursor position in the data structures and on
|
|
the screen.
|
|
|
|
Arguments:
|
|
|
|
ScreenInfo - pointer to screen info structure.
|
|
|
|
Position - new position of cursor
|
|
|
|
TurnOn - true if cursor should be left on, false if should be left off
|
|
|
|
Return Value:
|
|
|
|
Status
|
|
|
|
--*/
|
|
|
|
{
|
|
//
|
|
// don't let cursorposition be set beyond edge of screen buffer
|
|
//
|
|
|
|
if (Position.X >= ScreenInfo->ScreenBufferSize.X ||
|
|
Position.Y >= ScreenInfo->ScreenBufferSize.Y) {
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
ConsoleHideCursor(ScreenInfo);
|
|
ScreenInfo->BufferInfo.TextInfo.CursorPosition = Position;
|
|
#ifdef i386
|
|
if ((!(ScreenInfo->Console->Flags & CONSOLE_VDM_REGISTERED)) &&
|
|
ScreenInfo->Console->FullScreenFlags & CONSOLE_FULLSCREEN_HARDWARE) {
|
|
SetCursorPositionHW(ScreenInfo,Position);
|
|
}
|
|
#endif
|
|
ConsoleShowCursor(ScreenInfo);
|
|
|
|
// if we have the focus, adjust the cursor state
|
|
|
|
if (ScreenInfo->Console->Flags & CONSOLE_HAS_FOCUS) {
|
|
|
|
if (TurnOn) {
|
|
ScreenInfo->BufferInfo.TextInfo.DelayCursor = FALSE;
|
|
CursorTimerRoutine(ScreenInfo);
|
|
} else {
|
|
ScreenInfo->BufferInfo.TextInfo.DelayCursor = TRUE;
|
|
}
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
#ifdef i386
|
|
NTSTATUS
|
|
SetCursorInformationHW(
|
|
PSCREEN_INFORMATION ScreenInfo,
|
|
ULONG Size,
|
|
BOOLEAN Visible
|
|
)
|
|
{
|
|
VIDEO_CURSOR_ATTRIBUTES CursorAttr;
|
|
ULONG FontSizeY;
|
|
|
|
if (ScreenInfo->BufferInfo.TextInfo.DoubleCursor) {
|
|
if (Size > 50)
|
|
Size = Size >> 1;
|
|
else
|
|
Size = Size << 1;
|
|
}
|
|
ASSERT (Size <= 100 && Size > 0);
|
|
FontSizeY = CONSOLE_WINDOW_SIZE_Y(ScreenInfo) > 25 ? 8 : 16;
|
|
CursorAttr.Height = (USHORT)CURSOR_PERCENTAGE_TO_TOP_SCAN_LINE(FontSizeY,Size);
|
|
CursorAttr.Width = 31;
|
|
CursorAttr.Enable = Visible;
|
|
|
|
return NtUserFullscreenControl(FullscreenControlSetCursorAttributes,
|
|
(PVOID)&CursorAttr,
|
|
sizeof(CursorAttr),
|
|
NULL,
|
|
0);
|
|
|
|
}
|
|
|
|
|
|
#endif
|