[WIN32CSR]

- Make consistent use of RECT/SMALL_RECT structures: a RECT uses pixel coordinates relative to the window client area and is endpoint-exclusive; a SMALL_RECT uses character coordinates relative to the screen buffer and is endpoint-inclusive.
- Allow text selections outside of the visible window
- Implement GetConsoleSelectionInfo

svn path=/trunk/; revision=47335
This commit is contained in:
Jeffrey Morlan 2010-05-23 22:38:16 +00:00
parent 8f6739ed2e
commit 7fa77031b0
6 changed files with 257 additions and 332 deletions

View file

@ -3805,15 +3805,23 @@ GetConsoleProcessList(LPDWORD lpdwProcessList,
/*--------------------------------------------------------------
* GetConsoleSelectionInfo
*
* @unimplemented
* @implemented
*/
BOOL
WINAPI
GetConsoleSelectionInfo(PCONSOLE_SELECTION_INFO lpConsoleSelectionInfo)
{
DPRINT1("GetConsoleSelectionInfo(0x%x) UNIMPLEMENTED!\n", lpConsoleSelectionInfo);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
CSR_API_MESSAGE Request;
ULONG CsrRequest = MAKE_CSR_API(GET_CONSOLE_SELECTION_INFO, CSR_CONSOLE);
NTSTATUS Status = CsrClientCallServer(&Request, NULL, CsrRequest, sizeof(CSR_API_MESSAGE));
if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request.Status))
{
SetLastErrorByStatus(Status);
return FALSE;
}
*lpConsoleSelectionInfo = Request.Data.GetConsoleSelectionInfo.Info;
return TRUE;
}

View file

@ -473,6 +473,11 @@ typedef struct
COORD Size;
} CSRSS_SET_SCREEN_BUFFER_SIZE, *PCSRSS_SET_SCREEN_BUFFER_SIZE;
typedef struct
{
CONSOLE_SELECTION_INFO Info;
} CSRSS_GET_CONSOLE_SELECTION_INFO, *PCSRSS_GET_CONSOLE_SELECTION_INFO;
#define CSR_API_MESSAGE_HEADER_SIZE(Type) (FIELD_OFFSET(CSR_API_MESSAGE, Data) + sizeof(Type))
#define CSRSS_MAX_WRITE_CONSOLE (LPC_MAX_DATA_LENGTH - CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE))
@ -552,6 +557,7 @@ typedef struct
#define GENERATE_CTRL_EVENT (0x3E)
#define CREATE_THREAD (0x3F)
#define SET_SCREEN_BUFFER_SIZE (0x40)
#define GET_CONSOLE_SELECTION_INFO (0x41)
/* Keep in sync with definition below. */
#define CSRSS_HEADER_SIZE (sizeof(PORT_MESSAGE) + sizeof(ULONG) + sizeof(NTSTATUS))
@ -626,6 +632,7 @@ typedef struct _CSR_API_MESSAGE
CSRSS_GET_CONSOLE_ALIASES_EXES_LENGTH GetConsoleAliasesExesLength;
CSRSS_GENERATE_CTRL_EVENT GenerateCtrlEvent;
CSRSS_SET_SCREEN_BUFFER_SIZE SetScreenBufferSize;
CSRSS_GET_CONSOLE_SELECTION_INFO GetConsoleSelectionInfo;
} Data;
} CSR_API_MESSAGE, *PCSR_API_MESSAGE;

View file

@ -14,14 +14,14 @@
/* GLOBALS *******************************************************************/
#define ConioInitRect(Rect, Top, Left, Bottom, Right) \
((Rect)->top) = Top; \
((Rect)->left) = Left; \
((Rect)->bottom) = Bottom; \
((Rect)->right) = Right
#define ConioInitRect(Rect, top, left, bottom, right) \
((Rect)->Top) = top; \
((Rect)->Left) = left; \
((Rect)->Bottom) = bottom; \
((Rect)->Right) = right
#define ConioIsRectEmpty(Rect) \
(((Rect)->left > (Rect)->right) || ((Rect)->top > (Rect)->bottom))
(((Rect)->Left > (Rect)->Right) || ((Rect)->Top > (Rect)->Bottom))
#define ConsoleInputUnicodeCharToAnsiChar(Console, dChar, sWChar) \
WideCharToMultiByte((Console)->CodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL)
@ -392,7 +392,7 @@ CSR_API(CsrFreeConsole)
}
static VOID FASTCALL
ConioNextLine(PCSRSS_SCREEN_BUFFER Buff, RECT *UpdateRect, UINT *ScrolledLines)
ConioNextLine(PCSRSS_SCREEN_BUFFER Buff, SMALL_RECT *UpdateRect, UINT *ScrolledLines)
{
/* If we hit bottom, slide the viewable screen */
if (++Buff->CurrentY == Buff->MaxY)
@ -404,14 +404,14 @@ ConioNextLine(PCSRSS_SCREEN_BUFFER Buff, RECT *UpdateRect, UINT *ScrolledLines)
}
(*ScrolledLines)++;
ClearLineBuffer(Buff);
if (UpdateRect->top != 0)
if (UpdateRect->Top != 0)
{
UpdateRect->top--;
UpdateRect->Top--;
}
}
UpdateRect->left = 0;
UpdateRect->right = Buff->MaxX - 1;
UpdateRect->bottom = Buff->CurrentY;
UpdateRect->Left = 0;
UpdateRect->Right = Buff->MaxX - 1;
UpdateRect->Bottom = Buff->CurrentY;
}
static NTSTATUS FASTCALL
@ -420,16 +420,16 @@ ConioWriteConsole(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER Buff,
{
UINT i;
PBYTE Ptr;
RECT UpdateRect;
SMALL_RECT UpdateRect;
LONG CursorStartX, CursorStartY;
UINT ScrolledLines;
CursorStartX = Buff->CurrentX;
CursorStartY = Buff->CurrentY;
UpdateRect.left = Buff->MaxX;
UpdateRect.top = Buff->CurrentY;
UpdateRect.right = -1;
UpdateRect.bottom = Buff->CurrentY;
UpdateRect.Left = Buff->MaxX;
UpdateRect.Top = Buff->CurrentY;
UpdateRect.Right = -1;
UpdateRect.Bottom = Buff->CurrentY;
ScrolledLines = 0;
for (i = 0; i < Length; i++)
@ -454,7 +454,7 @@ ConioWriteConsole(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER Buff,
/* slide virtual position up */
Buff->CurrentX = Buff->MaxX - 1;
Buff->CurrentY--;
UpdateRect.top = min(UpdateRect.top, (LONG)Buff->CurrentY);
UpdateRect.Top = min(UpdateRect.Top, (LONG)Buff->CurrentY);
}
else
{
@ -463,8 +463,8 @@ ConioWriteConsole(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER Buff,
Ptr = ConioCoordToPointer(Buff, Buff->CurrentX, Buff->CurrentY);
Ptr[0] = ' ';
Ptr[1] = Buff->DefaultAttrib;
UpdateRect.left = min(UpdateRect.left, (LONG) Buff->CurrentX);
UpdateRect.right = max(UpdateRect.right, (LONG) Buff->CurrentX);
UpdateRect.Left = min(UpdateRect.Left, (LONG) Buff->CurrentX);
UpdateRect.Right = max(UpdateRect.Right, (LONG) Buff->CurrentX);
}
continue;
}
@ -472,8 +472,8 @@ ConioWriteConsole(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER Buff,
else if (Buffer[i] == '\r')
{
Buff->CurrentX = 0;
UpdateRect.left = min(UpdateRect.left, (LONG) Buff->CurrentX);
UpdateRect.right = max(UpdateRect.right, (LONG) Buff->CurrentX);
UpdateRect.Left = min(UpdateRect.Left, (LONG) Buff->CurrentX);
UpdateRect.Right = max(UpdateRect.Right, (LONG) Buff->CurrentX);
continue;
}
/* --- TAB --- */
@ -481,7 +481,7 @@ ConioWriteConsole(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER Buff,
{
UINT EndX;
UpdateRect.left = min(UpdateRect.left, (LONG)Buff->CurrentX);
UpdateRect.Left = min(UpdateRect.Left, (LONG)Buff->CurrentX);
EndX = (Buff->CurrentX + 8) & ~7;
if (EndX > Buff->MaxX)
{
@ -494,7 +494,7 @@ ConioWriteConsole(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER Buff,
*Ptr++ = Buff->DefaultAttrib;
Buff->CurrentX++;
}
UpdateRect.right = max(UpdateRect.right, (LONG) Buff->CurrentX - 1);
UpdateRect.Right = max(UpdateRect.Right, (LONG) Buff->CurrentX - 1);
if (Buff->CurrentX == Buff->MaxX)
{
if (Buff->Mode & ENABLE_WRAP_AT_EOL_OUTPUT)
@ -510,8 +510,8 @@ ConioWriteConsole(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER Buff,
continue;
}
}
UpdateRect.left = min(UpdateRect.left, (LONG)Buff->CurrentX);
UpdateRect.right = max(UpdateRect.right, (LONG) Buff->CurrentX);
UpdateRect.Left = min(UpdateRect.Left, (LONG)Buff->CurrentX);
UpdateRect.Right = max(UpdateRect.Right, (LONG) Buff->CurrentX);
Ptr = ConioCoordToPointer(Buff, Buff->CurrentX, Buff->CurrentY);
Ptr[0] = Buffer[i];
if (Attrib)
@ -684,16 +684,16 @@ CSR_API(CsrReadConsole)
}
__inline BOOLEAN ConioGetIntersection(
RECT *Intersection,
RECT *Rect1,
RECT *Rect2)
SMALL_RECT *Intersection,
SMALL_RECT *Rect1,
SMALL_RECT *Rect2)
{
if (ConioIsRectEmpty(Rect1) ||
(ConioIsRectEmpty(Rect2)) ||
(Rect1->top > Rect2->bottom) ||
(Rect1->left > Rect2->right) ||
(Rect1->bottom < Rect2->top) ||
(Rect1->right < Rect2->left))
(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);
@ -701,18 +701,18 @@ __inline BOOLEAN ConioGetIntersection(
}
ConioInitRect(Intersection,
max(Rect1->top, Rect2->top),
max(Rect1->left, Rect2->left),
min(Rect1->bottom, Rect2->bottom),
min(Rect1->right, Rect2->right));
max(Rect1->Top, Rect2->Top),
max(Rect1->Left, Rect2->Left),
min(Rect1->Bottom, Rect2->Bottom),
min(Rect1->Right, Rect2->Right));
return TRUE;
}
__inline BOOLEAN ConioGetUnion(
RECT *Union,
RECT *Rect1,
RECT *Rect2)
SMALL_RECT *Union,
SMALL_RECT *Rect1,
SMALL_RECT *Rect2)
{
if (ConioIsRectEmpty(Rect1))
{
@ -733,10 +733,10 @@ __inline BOOLEAN ConioGetUnion(
else
{
ConioInitRect(Union,
min(Rect1->top, Rect2->top),
min(Rect1->left, Rect2->left),
max(Rect1->bottom, Rect2->bottom),
max(Rect1->right, Rect2->right));
min(Rect1->Top, Rect2->Top),
min(Rect1->Left, Rect2->Left),
max(Rect1->Bottom, Rect2->Bottom),
max(Rect1->Right, Rect2->Right));
}
return TRUE;
@ -746,9 +746,9 @@ __inline BOOLEAN ConioGetUnion(
* this is done, to avoid overwriting parts of the source before they are moved. */
static VOID FASTCALL
ConioMoveRegion(PCSRSS_SCREEN_BUFFER ScreenBuffer,
RECT *SrcRegion,
RECT *DstRegion,
RECT *ClipRegion,
SMALL_RECT *SrcRegion,
SMALL_RECT *DstRegion,
SMALL_RECT *ClipRegion,
WORD Fill)
{
int Width = ConioRectWidth(SrcRegion);
@ -758,14 +758,14 @@ ConioMoveRegion(PCSRSS_SCREEN_BUFFER ScreenBuffer,
int XDelta, YDelta;
int i, j;
SY = SrcRegion->top;
DY = DstRegion->top;
SY = SrcRegion->Top;
DY = DstRegion->Top;
YDelta = 1;
if (SY < DY)
{
/* Moving down: work from bottom up */
SY = SrcRegion->bottom;
DY = DstRegion->bottom;
SY = SrcRegion->Bottom;
DY = DstRegion->Bottom;
YDelta = -1;
}
for (i = 0; i < Height; i++)
@ -773,26 +773,26 @@ ConioMoveRegion(PCSRSS_SCREEN_BUFFER ScreenBuffer,
PWORD SRow = (PWORD)ConioCoordToPointer(ScreenBuffer, 0, SY);
PWORD DRow = (PWORD)ConioCoordToPointer(ScreenBuffer, 0, DY);
SX = SrcRegion->left;
DX = DstRegion->left;
SX = SrcRegion->Left;
DX = DstRegion->Left;
XDelta = 1;
if (SX < DX)
{
/* Moving right: work from right to left */
SX = SrcRegion->right;
DX = DstRegion->right;
SX = SrcRegion->Right;
DX = DstRegion->Right;
XDelta = -1;
}
for (j = 0; j < Width; j++)
{
WORD Cell = SRow[SX];
if (SX >= ClipRegion->left && SX <= ClipRegion->right
&& SY >= ClipRegion->top && SY <= ClipRegion->bottom)
if (SX >= ClipRegion->Left && SX <= ClipRegion->Right
&& SY >= ClipRegion->Top && SY <= ClipRegion->Bottom)
{
SRow[SX] = Fill;
}
if (DX >= ClipRegion->left && DX <= ClipRegion->right
&& DY >= ClipRegion->top && DY <= ClipRegion->bottom)
if (DX >= ClipRegion->Left && DX <= ClipRegion->Right
&& DY >= ClipRegion->Top && DY <= ClipRegion->Bottom)
{
DRow[DX] = Cell;
}
@ -920,7 +920,7 @@ ConioDeleteScreenBuffer(PCSRSS_SCREEN_BUFFER Buffer)
VOID FASTCALL
ConioDrawConsole(PCSRSS_CONSOLE Console)
{
RECT Region;
SMALL_RECT Region;
ConioInitRect(&Region, 0, 0, Console->Size.Y - 1, Console->Size.X - 1);
@ -1362,29 +1362,29 @@ CSR_API(CsrSetCursor)
}
static VOID FASTCALL
ConioComputeUpdateRect(PCSRSS_SCREEN_BUFFER Buff, RECT *UpdateRect, COORD *Start, UINT Length)
ConioComputeUpdateRect(PCSRSS_SCREEN_BUFFER Buff, SMALL_RECT *UpdateRect, COORD *Start, UINT Length)
{
if (Buff->MaxX <= Start->X + Length)
{
UpdateRect->left = 0;
UpdateRect->Left = 0;
}
else
{
UpdateRect->left = Start->X;
UpdateRect->Left = Start->X;
}
if (Buff->MaxX <= Start->X + Length)
{
UpdateRect->right = Buff->MaxX - 1;
UpdateRect->Right = Buff->MaxX - 1;
}
else
{
UpdateRect->right = Start->X + Length - 1;
UpdateRect->Right = Start->X + Length - 1;
}
UpdateRect->top = Start->Y;
UpdateRect->bottom = Start->Y+ (Start->X + Length - 1) / Buff->MaxX;
if (Buff->MaxY <= UpdateRect->bottom)
UpdateRect->Top = Start->Y;
UpdateRect->Bottom = Start->Y+ (Start->X + Length - 1) / Buff->MaxX;
if (Buff->MaxY <= UpdateRect->Bottom)
{
UpdateRect->bottom = Buff->MaxY - 1;
UpdateRect->Bottom = Buff->MaxY - 1;
}
}
@ -1396,7 +1396,7 @@ CSR_API(CsrWriteConsoleOutputChar)
PCSRSS_CONSOLE Console;
PCSRSS_SCREEN_BUFFER Buff;
DWORD X, Y, Length, CharSize, Written = 0;
RECT UpdateRect;
SMALL_RECT UpdateRect;
DPRINT("CsrWriteConsoleOutputChar\n");
@ -1498,7 +1498,7 @@ CSR_API(CsrFillOutputChar)
DWORD X, Y, Length, Written = 0;
CHAR Char;
PBYTE Buffer;
RECT UpdateRect;
SMALL_RECT UpdateRect;
DPRINT("CsrFillOutputChar\n");
@ -1636,7 +1636,7 @@ CSR_API(CsrWriteConsoleOutputAttrib)
PWORD Attribute;
int X, Y, Length;
NTSTATUS Status;
RECT UpdateRect;
SMALL_RECT UpdateRect;
DPRINT("CsrWriteConsoleOutputAttrib\n");
@ -1705,7 +1705,7 @@ CSR_API(CsrFillOutputAttrib)
NTSTATUS Status;
int X, Y, Length;
UCHAR Attr;
RECT UpdateRect;
SMALL_RECT UpdateRect;
PCSRSS_CONSOLE Console;
DPRINT("CsrFillOutputAttrib\n");
@ -2119,9 +2119,9 @@ CSR_API(CsrWriteConsoleOutput)
SHORT i, X, Y, SizeX, SizeY;
PCSRSS_CONSOLE Console;
PCSRSS_SCREEN_BUFFER Buff;
RECT ScreenBuffer;
SMALL_RECT ScreenBuffer;
CHAR_INFO* CurCharInfo;
RECT WriteRegion;
SMALL_RECT WriteRegion;
CHAR_INFO* CharInfo;
COORD BufferCoord;
COORD BufferSize;
@ -2154,15 +2154,12 @@ CSR_API(CsrWriteConsoleOutput)
ConioUnlockScreenBuffer(Buff);
return STATUS_ACCESS_VIOLATION;
}
WriteRegion.left = Request->Data.WriteConsoleOutputRequest.WriteRegion.Left;
WriteRegion.top = Request->Data.WriteConsoleOutputRequest.WriteRegion.Top;
WriteRegion.right = Request->Data.WriteConsoleOutputRequest.WriteRegion.Right;
WriteRegion.bottom = Request->Data.WriteConsoleOutputRequest.WriteRegion.Bottom;
WriteRegion = Request->Data.WriteConsoleOutputRequest.WriteRegion;
SizeY = min(BufferSize.Y - BufferCoord.Y, ConioRectHeight(&WriteRegion));
SizeX = min(BufferSize.X - BufferCoord.X, ConioRectWidth(&WriteRegion));
WriteRegion.bottom = WriteRegion.top + SizeY - 1;
WriteRegion.right = WriteRegion.left + SizeX - 1;
WriteRegion.Bottom = WriteRegion.Top + SizeY - 1;
WriteRegion.Right = WriteRegion.Left + SizeX - 1;
/* Make sure WriteRegion is inside the screen buffer */
ConioInitRect(&ScreenBuffer, 0, 0, Buff->MaxY - 1, Buff->MaxX - 1);
@ -2175,11 +2172,11 @@ CSR_API(CsrWriteConsoleOutput)
return STATUS_SUCCESS;
}
for (i = 0, Y = WriteRegion.top; Y <= WriteRegion.bottom; i++, Y++)
for (i = 0, Y = WriteRegion.Top; Y <= WriteRegion.Bottom; i++, Y++)
{
CurCharInfo = CharInfo + (i + BufferCoord.Y) * BufferSize.X + BufferCoord.X;
Ptr = ConioCoordToPointer(Buff, WriteRegion.left, Y);
for (X = WriteRegion.left; X <= WriteRegion.right; X++)
Ptr = ConioCoordToPointer(Buff, WriteRegion.Left, Y);
for (X = WriteRegion.Left; X <= WriteRegion.Right; X++)
{
CHAR AsciiChar;
if (Request->Data.WriteConsoleOutputRequest.Unicode)
@ -2200,10 +2197,10 @@ CSR_API(CsrWriteConsoleOutput)
ConioUnlockScreenBuffer(Buff);
Request->Data.WriteConsoleOutputRequest.WriteRegion.Right = WriteRegion.left + SizeX - 1;
Request->Data.WriteConsoleOutputRequest.WriteRegion.Bottom = WriteRegion.top + SizeY - 1;
Request->Data.WriteConsoleOutputRequest.WriteRegion.Left = WriteRegion.left;
Request->Data.WriteConsoleOutputRequest.WriteRegion.Top = WriteRegion.top;
Request->Data.WriteConsoleOutputRequest.WriteRegion.Right = WriteRegion.Left + SizeX - 1;
Request->Data.WriteConsoleOutputRequest.WriteRegion.Bottom = WriteRegion.Top + SizeY - 1;
Request->Data.WriteConsoleOutputRequest.WriteRegion.Left = WriteRegion.Left;
Request->Data.WriteConsoleOutputRequest.WriteRegion.Top = WriteRegion.Top;
return STATUS_SUCCESS;
}
@ -2248,12 +2245,12 @@ CSR_API(CsrScrollConsoleScreenBuffer)
{
PCSRSS_CONSOLE Console;
PCSRSS_SCREEN_BUFFER Buff;
RECT ScreenBuffer;
RECT SrcRegion;
RECT DstRegion;
RECT UpdateRegion;
RECT ScrollRectangle;
RECT ClipRectangle;
SMALL_RECT ScreenBuffer;
SMALL_RECT SrcRegion;
SMALL_RECT DstRegion;
SMALL_RECT UpdateRegion;
SMALL_RECT ScrollRectangle;
SMALL_RECT ClipRectangle;
NTSTATUS Status;
HANDLE ConsoleHandle;
BOOLEAN UseClipRectangle;
@ -2277,10 +2274,7 @@ CSR_API(CsrScrollConsoleScreenBuffer)
}
Console = Buff->Header.Console;
ScrollRectangle.left = Request->Data.ScrollConsoleScreenBufferRequest.ScrollRectangle.Left;
ScrollRectangle.top = Request->Data.ScrollConsoleScreenBufferRequest.ScrollRectangle.Top;
ScrollRectangle.right = Request->Data.ScrollConsoleScreenBufferRequest.ScrollRectangle.Right;
ScrollRectangle.bottom = Request->Data.ScrollConsoleScreenBufferRequest.ScrollRectangle.Bottom;
ScrollRectangle = Request->Data.ScrollConsoleScreenBufferRequest.ScrollRectangle;
/* Make sure source rectangle is inside the screen buffer */
ConioInitRect(&ScreenBuffer, 0, 0, Buff->MaxY - 1, Buff->MaxX - 1);
@ -2291,21 +2285,18 @@ CSR_API(CsrScrollConsoleScreenBuffer)
}
/* If the source was clipped on the left or top, adjust the destination accordingly */
if (ScrollRectangle.left < 0)
if (ScrollRectangle.Left < 0)
{
DestinationOrigin.X -= ScrollRectangle.left;
DestinationOrigin.X -= ScrollRectangle.Left;
}
if (ScrollRectangle.top < 0)
if (ScrollRectangle.Top < 0)
{
DestinationOrigin.Y -= ScrollRectangle.top;
DestinationOrigin.Y -= ScrollRectangle.Top;
}
if (UseClipRectangle)
{
ClipRectangle.left = Request->Data.ScrollConsoleScreenBufferRequest.ClipRectangle.Left;
ClipRectangle.top = Request->Data.ScrollConsoleScreenBufferRequest.ClipRectangle.Top;
ClipRectangle.right = Request->Data.ScrollConsoleScreenBufferRequest.ClipRectangle.Right;
ClipRectangle.bottom = Request->Data.ScrollConsoleScreenBufferRequest.ClipRectangle.Bottom;
ClipRectangle = Request->Data.ScrollConsoleScreenBufferRequest.ClipRectangle;
if (!ConioGetIntersection(&ClipRectangle, &ClipRectangle, &ScreenBuffer))
{
ConioUnlockScreenBuffer(Buff);
@ -2601,8 +2592,8 @@ CSR_API(CsrReadConsoleOutput)
NTSTATUS Status;
COORD BufferSize;
COORD BufferCoord;
RECT ReadRegion;
RECT ScreenRect;
SMALL_RECT ReadRegion;
SMALL_RECT ScreenRect;
DWORD i;
PBYTE Ptr;
LONG X, Y;
@ -2620,10 +2611,7 @@ CSR_API(CsrReadConsoleOutput)
}
CharInfo = Request->Data.ReadConsoleOutputRequest.CharInfo;
ReadRegion.left = Request->Data.ReadConsoleOutputRequest.ReadRegion.Left;
ReadRegion.top = Request->Data.ReadConsoleOutputRequest.ReadRegion.Top;
ReadRegion.right = Request->Data.ReadConsoleOutputRequest.ReadRegion.Right;
ReadRegion.bottom = Request->Data.ReadConsoleOutputRequest.ReadRegion.Bottom;
ReadRegion = Request->Data.ReadConsoleOutputRequest.ReadRegion;
BufferSize = Request->Data.ReadConsoleOutputRequest.BufferSize;
BufferCoord = Request->Data.ReadConsoleOutputRequest.BufferCoord;
Length = BufferSize.X * BufferSize.Y;
@ -2641,8 +2629,8 @@ CSR_API(CsrReadConsoleOutput)
SizeY = min(BufferSize.Y - BufferCoord.Y, ConioRectHeight(&ReadRegion));
SizeX = min(BufferSize.X - BufferCoord.X, ConioRectWidth(&ReadRegion));
ReadRegion.bottom = ReadRegion.top + SizeY;
ReadRegion.right = ReadRegion.left + SizeX;
ReadRegion.Bottom = ReadRegion.Top + SizeY;
ReadRegion.Right = ReadRegion.Left + SizeX;
ConioInitRect(&ScreenRect, 0, 0, Buff->MaxY, Buff->MaxX);
if (! ConioGetIntersection(&ReadRegion, &ScreenRect, &ReadRegion))
@ -2651,12 +2639,12 @@ CSR_API(CsrReadConsoleOutput)
return STATUS_SUCCESS;
}
for (i = 0, Y = ReadRegion.top; Y < ReadRegion.bottom; ++i, ++Y)
for (i = 0, Y = ReadRegion.Top; Y < ReadRegion.Bottom; ++i, ++Y)
{
CurCharInfo = CharInfo + (i * BufferSize.X);
Ptr = ConioCoordToPointer(Buff, ReadRegion.left, Y);
for (X = ReadRegion.left; X < ReadRegion.right; ++X)
Ptr = ConioCoordToPointer(Buff, ReadRegion.Left, Y);
for (X = ReadRegion.Left; X < ReadRegion.Right; ++X)
{
if (Request->Data.ReadConsoleOutputRequest.Unicode)
{
@ -2675,10 +2663,10 @@ CSR_API(CsrReadConsoleOutput)
ConioUnlockScreenBuffer(Buff);
Request->Data.ReadConsoleOutputRequest.ReadRegion.Right = ReadRegion.left + SizeX - 1;
Request->Data.ReadConsoleOutputRequest.ReadRegion.Bottom = ReadRegion.top + SizeY - 1;
Request->Data.ReadConsoleOutputRequest.ReadRegion.Left = ReadRegion.left;
Request->Data.ReadConsoleOutputRequest.ReadRegion.Top = ReadRegion.top;
Request->Data.ReadConsoleOutputRequest.ReadRegion.Right = ReadRegion.Left + SizeX - 1;
Request->Data.ReadConsoleOutputRequest.ReadRegion.Bottom = ReadRegion.Top + SizeY - 1;
Request->Data.ReadConsoleOutputRequest.ReadRegion.Left = ReadRegion.Left;
Request->Data.ReadConsoleOutputRequest.ReadRegion.Top = ReadRegion.Top;
return STATUS_SUCCESS;
}
@ -3063,4 +3051,23 @@ CSR_API(CsrSetScreenBufferSize)
return Status;
}
CSR_API(CsrGetConsoleSelectionInfo)
{
NTSTATUS Status;
PCSRSS_CONSOLE Console;
Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
Status = ConioConsoleFromProcessData(ProcessData, &Console);
if (NT_SUCCESS(Status))
{
memset(&Request->Data.GetConsoleSelectionInfo.Info, 0, sizeof(CONSOLE_SELECTION_INFO));
if (Console->Selection.dwFlags != 0)
Request->Data.GetConsoleSelectionInfo.Info = Console->Selection;
ConioUnlockConsole(Console);
}
return Status;
}
/* EOF */

View file

@ -54,9 +54,9 @@ typedef struct tagCSRSS_CONSOLE *PCSRSS_CONSOLE;
typedef struct tagCSRSS_CONSOLE_VTBL
{
VOID (WINAPI *InitScreenBuffer)(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER ScreenBuffer);
VOID (WINAPI *WriteStream)(PCSRSS_CONSOLE Console, RECT *Block, LONG CursorStartX, LONG CursorStartY,
VOID (WINAPI *WriteStream)(PCSRSS_CONSOLE Console, SMALL_RECT *Block, LONG CursorStartX, LONG CursorStartY,
UINT ScrolledLines, CHAR *Buffer, UINT Length);
VOID (WINAPI *DrawRegion)(PCSRSS_CONSOLE Console, RECT *Region);
VOID (WINAPI *DrawRegion)(PCSRSS_CONSOLE Console, SMALL_RECT *Region);
BOOL (WINAPI *SetCursorInfo)(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER ScreenBuffer);
BOOL (WINAPI *SetScreenInfo)(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER ScreenBuffer,
UINT OldCursorX, UINT OldCursorY);
@ -92,6 +92,7 @@ typedef struct tagCSRSS_CONSOLE
PCSRSS_CONSOLE_VTBL Vtbl;
LIST_ENTRY ProcessList;
struct tagALIAS_HEADER *Aliases;
CONSOLE_SELECTION_INFO Selection;
} CSRSS_CONSOLE;
typedef struct ConsoleInput_t
@ -103,6 +104,13 @@ typedef struct ConsoleInput_t
BOOLEAN NotChar; // message should not be used to return a character
} ConsoleInput;
/* CONSOLE_SELECTION_INFO dwFlags values */
#define CONSOLE_NO_SELECTION 0x0
#define CONSOLE_SELECTION_IN_PROGRESS 0x1
#define CONSOLE_SELECTION_NOT_EMPTY 0x2
#define CONSOLE_MOUSE_SELECTION 0x4
#define CONSOLE_MOUSE_DOWN 0x8
NTSTATUS FASTCALL ConioConsoleFromProcessData(PCSRSS_PROCESS_DATA ProcessData, PCSRSS_CONSOLE *Console);
VOID WINAPI ConioDeleteConsole(Object_t *Object);
VOID WINAPI ConioDeleteScreenBuffer(PCSRSS_SCREEN_BUFFER Buffer);
@ -155,6 +163,7 @@ CSR_API(CsrSetConsoleOutputCodePage);
CSR_API(CsrGetProcessList);
CSR_API(CsrGenerateCtrlEvent);
CSR_API(CsrSetScreenBufferSize);
CSR_API(CsrGetConsoleSelectionInfo);
#define ConioInitScreenBuffer(Console, Buff) (Console)->Vtbl->InitScreenBuffer((Console), (Buff))
#define ConioDrawRegion(Console, Region) (Console)->Vtbl->DrawRegion((Console), (Region))
@ -172,9 +181,9 @@ CSR_API(CsrSetScreenBufferSize);
#define ConioResizeBuffer(Console, Buff, Size) (Console)->Vtbl->ResizeBuffer(Console, Buff, Size)
#define ConioRectHeight(Rect) \
(((Rect)->top) > ((Rect)->bottom) ? 0 : ((Rect)->bottom) - ((Rect)->top) + 1)
(((Rect)->Top) > ((Rect)->Bottom) ? 0 : ((Rect)->Bottom) - ((Rect)->Top) + 1)
#define ConioRectWidth(Rect) \
(((Rect)->left) > ((Rect)->right) ? 0 : ((Rect)->right) - ((Rect)->left) + 1)
(((Rect)->Left) > ((Rect)->Right) ? 0 : ((Rect)->Right) - ((Rect)->Left) + 1)
#define ConioLockConsole(ProcessData, Handle, Ptr, Access) \
Win32CsrLockObject((ProcessData), (Handle), (Object_t **)(Ptr), Access, CONIO_CONSOLE_MAGIC)

View file

@ -81,6 +81,7 @@ static CSRSS_API_DEFINITION Win32CsrApiDefinitions[] =
CSRSS_DEFINE_API(GET_CONSOLE_ALIASES_EXES_LENGTH, CsrGetConsoleAliasesExesLength),
CSRSS_DEFINE_API(GENERATE_CTRL_EVENT, CsrGenerateCtrlEvent),
CSRSS_DEFINE_API(SET_SCREEN_BUFFER_SIZE, CsrSetScreenBufferSize),
CSRSS_DEFINE_API(GET_CONSOLE_SELECTION_INFO, CsrGetConsoleSelectionInfo),
{ 0, 0, NULL }
};

View file

@ -25,9 +25,6 @@ typedef struct GUI_CONSOLE_DATA_TAG
BOOL CursorBlinkOn;
BOOL ForceCursorOff;
CRITICAL_SECTION Lock;
RECT Selection;
POINT SelectionStart;
BOOL MouseDown;
HMODULE ConsoleLibrary;
HANDLE hGuiInitEvent;
WCHAR FontName[LF_FACESIZE];
@ -773,7 +770,6 @@ GuiConsoleHandleNcCreate(HWND hWnd, CREATESTRUCTW *Create)
GuiData->CursorBlinkOn = TRUE;
GuiData->ForceCursorOff = FALSE;
GuiData->Selection.left = -1;
DPRINT("Console %p GuiData %p\n", Console, GuiData);
Console->PrivateData = GuiData;
SetWindowLongPtrW(hWnd, GWL_USERDATA, (DWORD_PTR) Console);
@ -790,40 +786,46 @@ GuiConsoleHandleNcCreate(HWND hWnd, CREATESTRUCTW *Create)
return (BOOL) DefWindowProcW(hWnd, WM_NCCREATE, 0, (LPARAM) Create);
}
static VOID FASTCALL
GuiConsoleUpdateSelection(HWND hWnd, PRECT rc, PGUI_CONSOLE_DATA GuiData)
static VOID
SmallRectToRect(PCSRSS_CONSOLE Console, PRECT Rect, PSMALL_RECT SmallRect)
{
RECT oldRect = GuiData->Selection;
PCSRSS_SCREEN_BUFFER Buffer = Console->ActiveBuffer;
PGUI_CONSOLE_DATA GuiData = Console->PrivateData;
Rect->left = (SmallRect->Left - Buffer->ShowX) * GuiData->CharWidth;
Rect->top = (SmallRect->Top - Buffer->ShowY) * GuiData->CharHeight;
Rect->right = (SmallRect->Right + 1 - Buffer->ShowX) * GuiData->CharWidth;
Rect->bottom = (SmallRect->Bottom + 1 - Buffer->ShowY) * GuiData->CharHeight;
}
if(rc != NULL)
static VOID FASTCALL
GuiConsoleUpdateSelection(PCSRSS_CONSOLE Console, PCOORD coord)
{
RECT oldRect, newRect;
HWND hWnd = Console->hWindow;
SmallRectToRect(Console, &oldRect, &Console->Selection.srSelection);
if(coord != NULL)
{
RECT changeRect = *rc;
SMALL_RECT rc;
/* exchange left/top with right/bottom if required */
rc.Left = min(Console->Selection.dwSelectionAnchor.X, coord->X);
rc.Top = min(Console->Selection.dwSelectionAnchor.Y, coord->Y);
rc.Right = max(Console->Selection.dwSelectionAnchor.X, coord->X);
rc.Bottom = max(Console->Selection.dwSelectionAnchor.Y, coord->Y);
GuiData->Selection = *rc;
SmallRectToRect(Console, &newRect, &rc);
changeRect.left *= GuiData->CharWidth;
changeRect.top *= GuiData->CharHeight;
changeRect.right *= GuiData->CharWidth;
changeRect.bottom *= GuiData->CharHeight;
if(rc->left != oldRect.left ||
rc->top != oldRect.top ||
rc->right != oldRect.right ||
rc->bottom != oldRect.bottom)
if (Console->Selection.dwFlags & CONSOLE_SELECTION_NOT_EMPTY)
{
if(oldRect.left != -1)
if (memcmp(&rc, &Console->Selection.srSelection, sizeof(SMALL_RECT)) != 0)
{
HRGN rgn1, rgn2;
oldRect.left *= GuiData->CharWidth;
oldRect.top *= GuiData->CharHeight;
oldRect.right *= GuiData->CharWidth;
oldRect.bottom *= GuiData->CharHeight;
/* calculate the region that needs to be updated */
if((rgn1 = CreateRectRgnIndirect(&oldRect)))
{
if((rgn2 = CreateRectRgnIndirect(&changeRect)))
if((rgn2 = CreateRectRgnIndirect(&newRect)))
{
if(CombineRgn(rgn1, rgn2, rgn1, RGN_XOR) != ERROR)
{
@ -835,21 +837,22 @@ GuiConsoleUpdateSelection(HWND hWnd, PRECT rc, PGUI_CONSOLE_DATA GuiData)
DeleteObject(rgn1);
}
}
else
{
InvalidateRect(hWnd, &changeRect, FALSE);
}
}
else
{
InvalidateRect(hWnd, &newRect, FALSE);
}
Console->Selection.dwFlags |= CONSOLE_SELECTION_NOT_EMPTY;
Console->Selection.srSelection = rc;
}
else if(oldRect.left != -1)
else
{
/* clear the selection */
GuiData->Selection.left = -1;
oldRect.left *= GuiData->CharWidth;
oldRect.top *= GuiData->CharHeight;
oldRect.right *= GuiData->CharWidth;
oldRect.bottom *= GuiData->CharHeight;
InvalidateRect(hWnd, &oldRect, FALSE);
if (Console->Selection.dwFlags & CONSOLE_SELECTION_NOT_EMPTY)
{
InvalidateRect(hWnd, &oldRect, FALSE);
}
Console->Selection.dwFlags = CONSOLE_NO_SELECTION;
}
}
@ -1005,14 +1008,10 @@ GuiConsoleHandlePaint(HWND hWnd, HDC hDCPaint)
hDC,
&ps.rcPaint);
if (GuiData->Selection.left != -1)
if (Console->Selection.dwFlags & CONSOLE_SELECTION_NOT_EMPTY)
{
RECT rc = GuiData->Selection;
rc.left *= GuiData->CharWidth;
rc.top *= GuiData->CharHeight;
rc.right *= GuiData->CharWidth;
rc.bottom *= GuiData->CharHeight;
RECT rc;
SmallRectToRect(Console, &rc, &Console->Selection.srSelection);
/* invert the selection */
if (IntersectRect(&rc,
@ -1052,51 +1051,29 @@ GuiConsoleHandleKey(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
if(msg == WM_CHAR || msg == WM_SYSKEYDOWN)
{
/* clear the selection */
GuiConsoleUpdateSelection(hWnd, NULL, GuiData);
GuiConsoleUpdateSelection(Console, NULL);
}
ConioProcessKey(&Message, Console, FALSE);
}
static VOID FASTCALL
GuiIntDrawRegion(PCSRSS_SCREEN_BUFFER Buff, PGUI_CONSOLE_DATA GuiData, HWND Wnd, RECT *Region)
{
RECT RegionRect;
RegionRect.left = (Region->left - Buff->ShowX) * GuiData->CharWidth;
RegionRect.top = (Region->top - Buff->ShowY) * GuiData->CharHeight;
RegionRect.right = (Region->right + 1 - Buff->ShowX) * GuiData->CharWidth;
RegionRect.bottom = (Region->bottom + 1 - Buff->ShowY) * GuiData->CharHeight;
InvalidateRect(Wnd, &RegionRect, FALSE);
}
static VOID WINAPI
GuiDrawRegion(PCSRSS_CONSOLE Console, RECT *Region)
GuiDrawRegion(PCSRSS_CONSOLE Console, SMALL_RECT *Region)
{
PGUI_CONSOLE_DATA GuiData = (PGUI_CONSOLE_DATA) Console->PrivateData;
if (NULL != Console->hWindow && NULL != GuiData)
{
GuiIntDrawRegion(Console->ActiveBuffer, GuiData, Console->hWindow, Region);
}
RECT RegionRect;
SmallRectToRect(Console, &RegionRect, Region);
InvalidateRect(Console->hWindow, &RegionRect, FALSE);
}
static VOID FASTCALL
GuiInvalidateCell(PCSRSS_SCREEN_BUFFER Buff, PGUI_CONSOLE_DATA GuiData, HWND Wnd, UINT x, UINT y)
GuiInvalidateCell(PCSRSS_CONSOLE Console, UINT x, UINT y)
{
RECT CellRect;
CellRect.left = x;
CellRect.top = y;
CellRect.right = x;
CellRect.bottom = y;
GuiIntDrawRegion(Buff, GuiData, Wnd, &CellRect);
SMALL_RECT CellRect = { x, y, x, y };
GuiDrawRegion(Console, &CellRect);
}
static VOID WINAPI
GuiWriteStream(PCSRSS_CONSOLE Console, RECT *Region, LONG CursorStartX, LONG CursorStartY,
GuiWriteStream(PCSRSS_CONSOLE Console, SMALL_RECT *Region, LONG CursorStartX, LONG CursorStartY,
UINT ScrolledLines, CHAR *Buffer, UINT Length)
{
PGUI_CONSOLE_DATA GuiData = (PGUI_CONSOLE_DATA) Console->PrivateData;
@ -1114,26 +1091,7 @@ GuiWriteStream(PCSRSS_CONSOLE Console, RECT *Region, LONG CursorStartX, LONG Cur
ScrollRect.left = 0;
ScrollRect.top = 0;
ScrollRect.right = Console->Size.X * GuiData->CharWidth;
ScrollRect.bottom = Region->top * GuiData->CharHeight;
if (GuiData->Selection.left != -1)
{
/* scroll the selection */
if (GuiData->Selection.top > ScrolledLines)
{
GuiData->Selection.top -= ScrolledLines;
GuiData->Selection.bottom -= ScrolledLines;
}
else if (GuiData->Selection.bottom < ScrolledLines)
{
GuiData->Selection.left = -1;
}
else
{
GuiData->Selection.top = 0;
GuiData->Selection.bottom -= ScrolledLines;
}
}
ScrollRect.bottom = Region->Top * GuiData->CharHeight;
ScrollWindowEx(Console->hWindow,
0,
@ -1145,21 +1103,21 @@ GuiWriteStream(PCSRSS_CONSOLE Console, RECT *Region, LONG CursorStartX, LONG Cur
SW_INVALIDATE);
}
GuiIntDrawRegion(Buff, GuiData, Console->hWindow, Region);
GuiDrawRegion(Console, Region);
if (CursorStartX < Region->left || Region->right < CursorStartX
|| CursorStartY < Region->top || Region->bottom < CursorStartY)
if (CursorStartX < Region->Left || Region->Right < CursorStartX
|| CursorStartY < Region->Top || Region->Bottom < CursorStartY)
{
GuiInvalidateCell(Buff, GuiData, Console->hWindow, CursorStartX, CursorStartY);
GuiInvalidateCell(Console, CursorStartX, CursorStartY);
}
CursorEndX = Buff->CurrentX;
CursorEndY = Buff->CurrentY;
if ((CursorEndX < Region->left || Region->right < CursorEndX
|| CursorEndY < Region->top || Region->bottom < CursorEndY)
if ((CursorEndX < Region->Left || Region->Right < CursorEndX
|| CursorEndY < Region->Top || Region->Bottom < CursorEndY)
&& (CursorEndX != CursorStartX || CursorEndY != CursorStartY))
{
GuiInvalidateCell(Buff, GuiData, Console->hWindow, CursorEndX, CursorEndY);
GuiInvalidateCell(Console, CursorEndX, CursorEndY);
}
// Set up the update timer (very short interval) - this is a "hack" for getting the OS to
@ -1171,15 +1129,9 @@ GuiWriteStream(PCSRSS_CONSOLE Console, RECT *Region, LONG CursorStartX, LONG Cur
static BOOL WINAPI
GuiSetCursorInfo(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER Buff)
{
RECT UpdateRect;
if (Console->ActiveBuffer == Buff)
{
UpdateRect.left = Buff->CurrentX;
UpdateRect.top = Buff->CurrentY;
UpdateRect.right = UpdateRect.left;
UpdateRect.bottom = UpdateRect.top;
ConioDrawRegion(Console, &UpdateRect);
GuiInvalidateCell(Console, Buff->CurrentX, Buff->CurrentY);
}
return TRUE;
@ -1188,22 +1140,12 @@ GuiSetCursorInfo(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER Buff)
static BOOL WINAPI
GuiSetScreenInfo(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER Buff, UINT OldCursorX, UINT OldCursorY)
{
RECT UpdateRect;
if (Console->ActiveBuffer == Buff)
{
/* Redraw char at old position (removes cursor) */
UpdateRect.left = OldCursorX;
UpdateRect.top = OldCursorY;
UpdateRect.right = OldCursorX;
UpdateRect.bottom = OldCursorY;
ConioDrawRegion(Console, &UpdateRect);
GuiInvalidateCell(Console, OldCursorX, OldCursorY);
/* Redraw char at new position (shows cursor) */
UpdateRect.left = Buff->CurrentX;
UpdateRect.top = Buff->CurrentY;
UpdateRect.right = UpdateRect.left;
UpdateRect.bottom = UpdateRect.top;
ConioDrawRegion(Console, &UpdateRect);
GuiInvalidateCell(Console, Buff->CurrentX, Buff->CurrentY);
}
return TRUE;
@ -1229,18 +1171,13 @@ GuiConsoleHandleTimer(HWND hWnd)
PCSRSS_CONSOLE Console;
PGUI_CONSOLE_DATA GuiData;
PCSRSS_SCREEN_BUFFER Buff;
RECT CursorRect;
SetTimer(hWnd, CONGUI_UPDATE_TIMER, CURSOR_BLINK_TIME, NULL);
GuiConsoleGetDataPointers(hWnd, &Console, &GuiData);
Buff = Console->ActiveBuffer;
CursorRect.left = Buff->CurrentX;
CursorRect.top = Buff->CurrentY;
CursorRect.right = CursorRect.left;
CursorRect.bottom = CursorRect.top;
GuiDrawRegion(Console, &CursorRect);
GuiInvalidateCell(Console, Buff->CurrentX, Buff->CurrentY);
GuiData->CursorBlinkOn = ! GuiData->CursorBlinkOn;
if((GuiData->OldCursor.x != Buff->CurrentX) || (GuiData->OldCursor.y != Buff->CurrentY))
@ -1362,32 +1299,39 @@ GuiConsoleHandleNcDestroy(HWND hWnd)
HeapFree(Win32CsrApiHeap, 0, GuiData);
}
static COORD
PointToCoord(PCSRSS_CONSOLE Console, LPARAM lParam)
{
PCSRSS_SCREEN_BUFFER Buffer = Console->ActiveBuffer;
PGUI_CONSOLE_DATA GuiData = Console->PrivateData;
COORD Coord;
Coord.X = Buffer->ShowX + ((short)LOWORD(lParam) / (int)GuiData->CharWidth);
Coord.Y = Buffer->ShowY + ((short)HIWORD(lParam) / (int)GuiData->CharHeight);
/* Clip coordinate to ensure it's inside buffer */
if (Coord.X < 0) Coord.X = 0;
else if (Coord.X >= Buffer->MaxX) Coord.X = Buffer->MaxX - 1;
if (Coord.Y < 0) Coord.Y = 0;
else if (Coord.Y >= Buffer->MaxY) Coord.Y = Buffer->MaxY - 1;
return Coord;
}
static VOID FASTCALL
GuiConsoleLeftMouseDown(HWND hWnd, LPARAM lParam)
{
PCSRSS_CONSOLE Console;
PGUI_CONSOLE_DATA GuiData;
POINTS pt;
RECT rc;
GuiConsoleGetDataPointers(hWnd, &Console, &GuiData);
if (Console == NULL || GuiData == NULL) return;
pt = MAKEPOINTS(lParam);
rc.left = pt.x / GuiData->CharWidth;
rc.top = pt.y / GuiData->CharHeight;
rc.right = rc.left + 1;
rc.bottom = rc.top + 1;
GuiData->SelectionStart.x = rc.left;
GuiData->SelectionStart.y = rc.top;
Console->Selection.dwSelectionAnchor = PointToCoord(Console, lParam);
SetCapture(hWnd);
GuiData->MouseDown = TRUE;
Console->Selection.dwFlags |= CONSOLE_SELECTION_IN_PROGRESS | CONSOLE_MOUSE_SELECTION | CONSOLE_MOUSE_DOWN;
GuiConsoleUpdateSelection(hWnd, &rc, GuiData);
GuiConsoleUpdateSelection(Console, &Console->Selection.dwSelectionAnchor);
}
static VOID FASTCALL
@ -1395,39 +1339,17 @@ GuiConsoleLeftMouseUp(HWND hWnd, LPARAM lParam)
{
PCSRSS_CONSOLE Console;
PGUI_CONSOLE_DATA GuiData;
RECT rc;
POINTS pt;
COORD c;
GuiConsoleGetDataPointers(hWnd, &Console, &GuiData);
if (Console == NULL || GuiData == NULL) return;
if (GuiData->Selection.left == -1 || !GuiData->MouseDown) return;
if (!(Console->Selection.dwFlags & CONSOLE_MOUSE_DOWN)) return;
pt = MAKEPOINTS(lParam);
c = PointToCoord(Console, lParam);
rc.left = GuiData->SelectionStart.x;
rc.top = GuiData->SelectionStart.y;
rc.right = (pt.x >= 0 ? (pt.x / GuiData->CharWidth) + 1 : 0);
rc.bottom = (pt.y >= 0 ? (pt.y / GuiData->CharHeight) + 1 : 0);
Console->Selection.dwFlags &= ~CONSOLE_MOUSE_DOWN;
/* exchange left/top with right/bottom if required */
if(rc.left >= rc.right)
{
LONG tmp;
tmp = rc.left;
rc.left = max(rc.right - 1, 0);
rc.right = tmp + 1;
}
if(rc.top >= rc.bottom)
{
LONG tmp;
tmp = rc.top;
rc.top = max(rc.bottom - 1, 0);
rc.bottom = tmp + 1;
}
GuiData->MouseDown = FALSE;
GuiConsoleUpdateSelection(hWnd, &rc, GuiData);
GuiConsoleUpdateSelection(Console, &c);
ReleaseCapture();
}
@ -1437,46 +1359,17 @@ GuiConsoleMouseMove(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
PCSRSS_CONSOLE Console;
PGUI_CONSOLE_DATA GuiData;
RECT rc;
POINTS pt;
COORD c;
if (!(wParam & MK_LBUTTON)) return;
GuiConsoleGetDataPointers(hWnd, &Console, &GuiData);
if (Console == NULL || GuiData == NULL || !GuiData->MouseDown) return;
if (Console == NULL || GuiData == NULL) return;
if (!(Console->Selection.dwFlags & CONSOLE_MOUSE_DOWN)) return;
pt = MAKEPOINTS(lParam);
c = PointToCoord(Console, lParam); /* TODO: Scroll buffer to bring c into view */
rc.left = GuiData->SelectionStart.x;
rc.top = GuiData->SelectionStart.y;
rc.right = (pt.x >= 0 ? (pt.x / GuiData->CharWidth) + 1 : 0);
if (Console->Size.X < rc.right)
{
rc.right = Console->Size.X;
}
rc.bottom = (pt.y >= 0 ? (pt.y / GuiData->CharHeight) + 1 : 0);
if (Console->Size.Y < rc.bottom)
{
rc.bottom = Console->Size.Y;
}
/* exchange left/top with right/bottom if required */
if(rc.left >= rc.right)
{
LONG tmp;
tmp = rc.left;
rc.left = max(rc.right - 1, 0);
rc.right = tmp + 1;
}
if(rc.top >= rc.bottom)
{
LONG tmp;
tmp = rc.top;
rc.top = max(rc.bottom - 1, 0);
rc.bottom = tmp + 1;
}
GuiConsoleUpdateSelection(hWnd, &rc, GuiData);
GuiConsoleUpdateSelection(Console, &c);
}
static VOID FASTCALL
@ -1488,7 +1381,7 @@ GuiConsoleRightMouseDown(HWND hWnd)
GuiConsoleGetDataPointers(hWnd, &Console, &GuiData);
if (Console == NULL || GuiData == NULL) return;
if (GuiData->Selection.left == -1)
if (!(Console->Selection.dwFlags & CONSOLE_SELECTION_NOT_EMPTY))
{
/* FIXME - paste text from clipboard */
}
@ -1496,7 +1389,7 @@ GuiConsoleRightMouseDown(HWND hWnd)
{
/* FIXME - copy selection to clipboard */
GuiConsoleUpdateSelection(hWnd, NULL, GuiData);
GuiConsoleUpdateSelection(Console, NULL);
}
}