[WIN32CSR]
authorJeffrey Morlan <mrnobo1024@yahoo.com>
Sun, 23 May 2010 22:38:16 +0000 (22:38 +0000)
committerJeffrey Morlan <mrnobo1024@yahoo.com>
Sun, 23 May 2010 22:38:16 +0000 (22:38 +0000)
- 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

reactos/dll/win32/kernel32/misc/console.c
reactos/include/reactos/subsys/csrss/csrss.h
reactos/subsystems/win32/csrss/win32csr/conio.c
reactos/subsystems/win32/csrss/win32csr/conio.h
reactos/subsystems/win32/csrss/win32csr/dllmain.c
reactos/subsystems/win32/csrss/win32csr/guiconsole.c

index 2d6d5ba..298f79b 100644 (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;
 }
 
 
index b1867e4..62fe387 100644 (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;
 
index 579e4fe..60b93cf 100644 (file)
 
 /* 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 */
index 8c85368..8645351 100644 (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)
index bd0409c..2e8947f 100644 (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 }
   };
 
index 3edccbc..0d063d8 100644 (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
+SmallRectToRect(PCSRSS_CONSOLE Console, PRECT Rect, PSMALL_RECT SmallRect)
+{
+    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;
+}
+
 static VOID FASTCALL
-GuiConsoleUpdateSelection(HWND hWnd, PRECT rc, PGUI_CONSOLE_DATA GuiData)
+GuiConsoleUpdateSelection(PCSRSS_CONSOLE Console, PCOORD coord)
 {
-  RECT oldRect = GuiData->Selection;
+  RECT oldRect, newRect;
+  HWND hWnd = Console->hWindow;
 
-  if(rc != NULL)
-  {
-    RECT changeRect = *rc;
+  SmallRectToRect(Console, &oldRect, &Console->Selection.srSelection);
 
-    GuiData->Selection = *rc;
+  if(coord != NULL)
+  {
+    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);
 
-    changeRect.left *= GuiData->CharWidth;
-    changeRect.top *= GuiData->CharHeight;
-    changeRect.right *= GuiData->CharWidth;
-    changeRect.bottom *= GuiData->CharHeight;
+    SmallRectToRect(Console, &newRect, &rc);
 
-    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;
-
-  pt = MAKEPOINTS(lParam);
-
-  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;
-  }
+  if (Console == NULL || GuiData == NULL) return;
+  if (!(Console->Selection.dwFlags & CONSOLE_MOUSE_DOWN)) return;
 
-  /* 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;
-  }
+  c = PointToCoord(Console, lParam); /* TODO: Scroll buffer to bring c into view */
 
-  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);
   }
 
 }