Commit in reactos/subsys/csrss/win32csr on MAIN
guiconsole.c+231-11.15 -> 1.16
allow selecting text with the mouse in gui consoles

reactos/subsys/csrss/win32csr
guiconsole.c 1.15 -> 1.16
diff -u -r1.15 -r1.16
--- guiconsole.c	3 Jul 2004 17:17:05 -0000	1.15
+++ guiconsole.c	28 Jul 2004 22:28:50 -0000	1.16
@@ -1,4 +1,4 @@
-/* $Id: guiconsole.c,v 1.15 2004/07/03 17:17:05 hbirr Exp $
+/* $Id: guiconsole.c,v 1.16 2004/07/28 22:28:50 weiden Exp $
  *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS system libraries
@@ -32,6 +32,8 @@
   CRITICAL_SECTION Lock;
   HDC MemoryDC;
   HBITMAP MemoryBitmap;
+  RECT Selection;
+  POINT SelectionStart;
 } GUI_CONSOLE_DATA, *PGUI_CONSOLE_DATA;
 
 #ifndef WM_APP
@@ -134,6 +136,8 @@
   GuiData->CursorBlinkOn = TRUE;
   GuiData->ForceCursorOff = FALSE;
 
+  GuiData->Selection.left = -1;
+  
   Console->PrivateData = GuiData;
   SetWindowLongW(hWnd, GWL_USERDATA, (LONG) Console);
 
@@ -181,6 +185,71 @@
     }
 }
 
+
+static VOID FASTCALL
+GuiConsoleUpdateSelection(HWND hWnd, PRECT rc, PGUI_CONSOLE_DATA GuiData)
+{
+  RECT oldRect = GuiData->Selection;
+  
+  if(rc != NULL)
+  {
+    RECT changeRect = *rc;
+
+    GuiData->Selection = *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(oldRect.left != -1)
+      {
+        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(CombineRgn(rgn1, rgn2, rgn1, RGN_XOR) != ERROR)
+            {
+              InvalidateRgn(hWnd, rgn1, FALSE);
+            }
+
+            DeleteObject(rgn2);
+          }
+          DeleteObject(rgn1);
+        }
+      }
+      else
+      {
+        InvalidateRect(hWnd, &changeRect, FALSE);
+      }
+    }
+  }
+  else if(oldRect.left != -1)
+  {
+    /* 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);
+  }
+}
+
+
 VOID FASTCALL
 GuiConsoleUpdateBitmap(HWND hWnd, RECT rc)
 {
@@ -303,6 +372,22 @@
              Ps.rcPaint.right - Ps.rcPaint.left + 1,
              Ps.rcPaint.bottom - Ps.rcPaint.top + 1, GuiData->MemoryDC,
              Ps.rcPaint.left, Ps.rcPaint.top, SRCCOPY);
+      
+      if (GuiData->Selection.left != -1)
+      {
+        RECT rc = GuiData->Selection;
+        
+        rc.left *= GuiData->CharWidth;
+        rc.top *= GuiData->CharHeight;
+        rc.right *= GuiData->CharWidth;
+        rc.bottom *= GuiData->CharHeight;
+
+        if (IntersectRect(&rc, &Ps.rcPaint, &rc))
+        {                 
+          PatBlt(Dc, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, DSTINVERT);
+        } 
+      }                   
+      
       EndPaint (hWnd, &Ps);
       LeaveCriticalSection(&GuiData->Lock);
     }
@@ -325,6 +410,12 @@
   Message.message = msg;
   Message.wParam = wParam;
   Message.lParam = lParam;
+  
+  if(msg == WM_CHAR || msg == WM_SYSKEYDOWN)
+  {
+    /* clear the selection */
+    GuiConsoleUpdateSelection(hWnd, NULL, GuiData);
+  }
 
   ConioProcessKey(&Message, Console, FALSE);
 }
@@ -525,6 +616,133 @@
   HeapFree(Win32CsrApiHeap, 0, GuiData);
 }
 
+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;
+  
+  SetCapture(hWnd);
+  
+  GuiConsoleUpdateSelection(hWnd, &rc, GuiData);
+}
+
+static VOID FASTCALL
+GuiConsoleLeftMouseUp(HWND hWnd, LPARAM lParam)
+{
+  PCSRSS_CONSOLE Console;
+  PGUI_CONSOLE_DATA GuiData;
+  RECT rc;
+  POINTS pt;
+  
+  GuiConsoleGetDataPointers(hWnd, &Console, &GuiData);
+  if (Console == NULL || GuiData == NULL) return;
+  if (GuiData->Selection.left == -1) return;
+  
+  pt = MAKEPOINTS(lParam);
+  
+  rc.left = GuiData->SelectionStart.x;
+  rc.top = GuiData->SelectionStart.y;
+  rc.right = (pt.x >= 0 ? (pt.x + GuiData->CharWidth - 1) / GuiData->CharWidth : 0);
+  rc.bottom = (pt.y >= 0 ? (pt.y + GuiData->CharHeight - 1) / GuiData->CharHeight : 0);
+
+  /* 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);
+  
+  ReleaseCapture();
+}
+
+static VOID FASTCALL
+GuiConsoleMouseMove(HWND hWnd, WPARAM wParam, LPARAM lParam)
+{
+  PCSRSS_CONSOLE Console;
+  PGUI_CONSOLE_DATA GuiData;
+  RECT rc;
+  POINTS pt;
+  
+  if (!(wParam & MK_LBUTTON)) return;
+  
+  GuiConsoleGetDataPointers(hWnd, &Console, &GuiData);
+  if (Console == NULL || GuiData == NULL) return;
+  
+  pt = MAKEPOINTS(lParam);
+
+  rc.left = GuiData->SelectionStart.x;
+  rc.top = GuiData->SelectionStart.y;
+  rc.right = (pt.x >= 0 ? (pt.x + GuiData->CharWidth - 1) / GuiData->CharWidth : 0);
+  rc.bottom = (pt.y >= 0 ? (pt.y + GuiData->CharHeight - 1) / GuiData->CharHeight : 0);
+
+  /* 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);
+}    
+
+static VOID FASTCALL
+GuiConsoleRightMouseDown(HWND hWnd)
+{
+  PCSRSS_CONSOLE Console;
+  PGUI_CONSOLE_DATA GuiData;
+  
+  GuiConsoleGetDataPointers(hWnd, &Console, &GuiData);
+  if (Console == NULL || GuiData == NULL) return;
+
+  if (GuiData->Selection.left == -1)
+  {
+    /* FIXME - paste text from clipboard */
+  }
+  else
+  {
+    /* FIXME - copy selection to clipboard */
+    
+    GuiConsoleUpdateSelection(hWnd, NULL, GuiData);
+  }
+
+}    
+
 static LRESULT CALLBACK
 GuiConsoleWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
 {
@@ -559,6 +777,18 @@
         GuiConsoleHandleNcDestroy(hWnd);
         Result = 0;
         break;
+      case WM_LBUTTONDOWN:
+          GuiConsoleLeftMouseDown(hWnd, lParam);
+        break;
+      case WM_LBUTTONUP:
+          GuiConsoleLeftMouseUp(hWnd, lParam);
+        break;
+      case WM_RBUTTONDOWN:
+          GuiConsoleRightMouseDown(hWnd);
+        break;
+      case WM_MOUSEMOVE:
+          GuiConsoleMouseMove(hWnd, wParam, lParam);
+        break;
       default:
         Result = DefWindowProcW(hWnd, msg, wParam, lParam);
         break;
CVSspam 0.2.8