+VOID
+GetSelectionBeginEnd(PCOORD Begin, PCOORD End,
+ PCOORD SelectionAnchor,
+ PSMALL_RECT SmallRect)
+{
+ if (Begin == NULL || End == NULL) return;
+
+ *Begin = *SelectionAnchor;
+ End->X = (SelectionAnchor->X == SmallRect->Left) ? SmallRect->Right
+ /* Case X != Left, must be == Right */ : SmallRect->Left;
+ End->Y = (SelectionAnchor->Y == SmallRect->Top ) ? SmallRect->Bottom
+ /* Case Y != Top, must be == Bottom */ : SmallRect->Top;
+
+ /* Exchange Begin / End if Begin > End lexicographically */
+ if (Begin->Y > End->Y || (Begin->Y == End->Y && Begin->X > End->X))
+ {
+ End->X = _InterlockedExchange16(&Begin->X, End->X);
+ End->Y = _InterlockedExchange16(&Begin->Y, End->Y);
+ }
+}
+
+static HRGN
+CreateSelectionRgn(PGUI_CONSOLE_DATA GuiData,
+ BOOL LineSelection,
+ PCOORD SelectionAnchor,
+ PSMALL_RECT SmallRect)
+{
+ if (!LineSelection)
+ {
+ RECT rect;
+ SmallRectToRect(GuiData, &rect, SmallRect);
+ return CreateRectRgnIndirect(&rect);
+ }
+ else
+ {
+ HRGN SelRgn;
+ COORD Begin, End;
+
+ GetSelectionBeginEnd(&Begin, &End, SelectionAnchor, SmallRect);
+
+ if (Begin.Y == End.Y)
+ {
+ SMALL_RECT sr;
+ RECT r ;
+
+ sr.Left = Begin.X;
+ sr.Top = Begin.Y;
+ sr.Right = End.X;
+ sr.Bottom = End.Y;
+
+ // Debug thingie to see whether I can put this corner case
+ // together with the previous one.
+ if (SmallRect->Left != sr.Left ||
+ SmallRect->Top != sr.Top ||
+ SmallRect->Right != sr.Right ||
+ SmallRect->Bottom != sr.Bottom)
+ {
+ DPRINT1("\n"
+ "SmallRect = (%d, %d, %d, %d)\n"
+ "sr = (%d, %d, %d, %d)\n"
+ "\n",
+ SmallRect->Left, SmallRect->Top, SmallRect->Right, SmallRect->Bottom,
+ sr.Left, sr.Top, sr.Right, sr.Bottom);
+ }
+
+ SmallRectToRect(GuiData, &r, &sr);
+ SelRgn = CreateRectRgnIndirect(&r);
+ }
+ else
+ {
+ PCONSOLE_SCREEN_BUFFER ActiveBuffer = GuiData->ActiveBuffer;
+
+ HRGN rg1, rg2, rg3;
+ SMALL_RECT sr1, sr2, sr3;
+ RECT r1 , r2 , r3 ;
+
+ sr1.Left = Begin.X;
+ sr1.Top = Begin.Y;
+ sr1.Right = ActiveBuffer->ScreenBufferSize.X - 1;
+ sr1.Bottom = Begin.Y;
+
+ sr2.Left = 0;
+ sr2.Top = Begin.Y + 1;
+ sr2.Right = ActiveBuffer->ScreenBufferSize.X - 1;
+ sr2.Bottom = End.Y - 1;
+
+ sr3.Left = 0;
+ sr3.Top = End.Y;
+ sr3.Right = End.X;
+ sr3.Bottom = End.Y;
+
+ SmallRectToRect(GuiData, &r1, &sr1);
+ SmallRectToRect(GuiData, &r2, &sr2);
+ SmallRectToRect(GuiData, &r3, &sr3);
+
+ rg1 = CreateRectRgnIndirect(&r1);
+ rg2 = CreateRectRgnIndirect(&r2);
+ rg3 = CreateRectRgnIndirect(&r3);
+
+ CombineRgn(rg1, rg1, rg2, RGN_XOR);
+ CombineRgn(rg1, rg1, rg3, RGN_XOR);
+ DeleteObject(rg3);
+ DeleteObject(rg2);
+
+ SelRgn = rg1;
+ }
+
+ return SelRgn;
+ }
+}
+
+static VOID
+PaintSelectionRect(PGUI_CONSOLE_DATA GuiData, PPAINTSTRUCT pps)
+{
+ HRGN rgnPaint = CreateRectRgnIndirect(&pps->rcPaint);
+ HRGN rgnSel = CreateSelectionRgn(GuiData, GuiData->LineSelection,
+ &GuiData->Selection.dwSelectionAnchor,
+ &GuiData->Selection.srSelection);
+
+ /* Invert the selection */
+
+ int ErrorCode = CombineRgn(rgnPaint, rgnPaint, rgnSel, RGN_AND);
+ if (ErrorCode != ERROR && ErrorCode != NULLREGION)
+ {
+ InvertRgn(pps->hdc, rgnPaint);
+ }
+
+ DeleteObject(rgnSel);
+ DeleteObject(rgnPaint);
+}
+