[win32csr] Implement routines to allow copy, paste and select all on console windows
[reactos.git] / reactos / subsystems / win32 / csrss / win32csr / guiconsole.c
index ca7388d..e54e4dd 100644 (file)
@@ -1370,6 +1370,109 @@ GuiConsoleMouseMove(HWND hWnd, WPARAM wParam, LPARAM lParam)
     GuiConsoleUpdateSelection(Console, &c);
 }
 
+static VOID
+GuiConsoleCopy(HWND hWnd, PCSRSS_CONSOLE Console)
+{
+    if (OpenClipboard(hWnd) == TRUE)
+    {
+        HANDLE hData;
+        PBYTE ptr;
+        LPSTR data, dstPos;
+        ULONG selWidth, selHeight;
+        ULONG xPos, yPos, size;
+
+        selWidth = Console->Selection.srSelection.Right - Console->Selection.srSelection.Left + 1;
+        selHeight = Console->Selection.srSelection.Bottom - Console->Selection.srSelection.Top + 1;
+        DPRINT("Selection is (%d|%d) to (%d|%d)\n",
+               Console->Selection.srSelection.Left,
+               Console->Selection.srSelection.Top,
+               Console->Selection.srSelection.Right,
+               Console->Selection.srSelection.Bottom);
+
+        /* Basic size for one line and termination */
+        size = selWidth + 1;
+        if (selHeight > 0)
+        {
+            /* Multiple line selections have to get \r\n appended */
+            size += ((selWidth + 2) * (selHeight - 1));
+        }
+
+        /* Allocate memory, it will be passed to the system and may not be freed here */
+        hData = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, size);
+        if (hData == NULL)
+        {
+            CloseClipboard();
+            return;
+        }
+        data = GlobalLock(hData);
+        if (data == NULL)
+        {
+            CloseClipboard();
+            return;
+        }
+
+        DPRINT("Copying %dx%d selection\n", selWidth, selHeight);
+        dstPos = data;
+
+        for (yPos = 0; yPos < selHeight; yPos++)
+        {
+            ptr = ConioCoordToPointer(Console->ActiveBuffer, 
+                                      Console->Selection.srSelection.Left,
+                                      yPos + Console->Selection.srSelection.Top);
+            /* Copy only the characters, leave attributes alone */
+            for (xPos = 0; xPos < selWidth; xPos++)
+            {
+                dstPos[xPos] = ptr[xPos * 2];
+            }
+            dstPos += selWidth;
+            if (yPos != (selHeight - 1))
+            {
+                strcat(data, "\r\n");
+                dstPos += 2;
+            }
+        }
+
+        DPRINT("Setting data <%s> to clipboard\n", data);
+        GlobalUnlock(hData);
+
+        EmptyClipboard();
+        SetClipboardData(CF_TEXT, hData);
+        CloseClipboard();
+    }
+}
+
+static VOID
+GuiConsolePaste(HWND hWnd, PCSRSS_CONSOLE Console)
+{
+    if (OpenClipboard(hWnd) == TRUE)
+    {
+        HANDLE hData;
+        LPSTR str;
+        size_t len;
+
+        hData = GetClipboardData(CF_TEXT);
+        if (hData == NULL)
+        {
+            CloseClipboard();
+            return;
+        }
+
+        str = GlobalLock(hData);
+        if (str == NULL)
+        {
+            CloseClipboard();
+            return;
+        }
+        DPRINT("Got data <%s> from clipboard\n", str);
+        len = strlen(str);
+
+        ConioWriteConsole(Console, Console->ActiveBuffer, str, len, TRUE);
+
+        GlobalUnlock(hData);
+        CloseClipboard();
+    }
+}
+
 static VOID
 GuiConsoleRightMouseDown(HWND hWnd)
 {
@@ -1381,12 +1484,13 @@ GuiConsoleRightMouseDown(HWND hWnd)
 
     if (!(Console->Selection.dwFlags & CONSOLE_SELECTION_NOT_EMPTY))
     {
-        /* FIXME - paste text from clipboard */
+        GuiConsolePaste(hWnd, Console);
     }
     else
     {
-        /* FIXME - copy selection to clipboard */
+        GuiConsoleCopy(hWnd, Console);
 
+        /* Clear the selection */
         GuiConsoleUpdateSelection(Console, NULL);
     }
 
@@ -1466,18 +1570,41 @@ GuiConsoleShowConsoleProperties(HWND hWnd, BOOL Defaults, PGUI_CONSOLE_DATA GuiD
     CPLFunc(hWnd, CPL_DBLCLK, (LPARAM)&SharedInfo, Defaults);
 }
 static LRESULT
-GuiConsoleHandleSysMenuCommand(HWND hWnd, WPARAM wParam, LPARAM lParam, PGUI_CONSOLE_DATA GuiData)
+GuiConsoleHandleSysMenuCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
 {
     LRESULT Ret = TRUE;
+    PCSRSS_CONSOLE Console;
+    PGUI_CONSOLE_DATA GuiData;
+    COORD bottomRight = { 0, 0 };
+
+    GuiConsoleGetDataPointers(hWnd, &Console, &GuiData);
 
     switch(wParam)
     {
     case ID_SYSTEM_EDIT_MARK:
+        DPRINT1("Marking not handled yet\n");
+        break;
+
     case ID_SYSTEM_EDIT_COPY:
+        GuiConsoleCopy(hWnd, Console);
+        break;
+
     case ID_SYSTEM_EDIT_PASTE:
+        GuiConsolePaste(hWnd, Console);
+        break;
+
     case ID_SYSTEM_EDIT_SELECTALL:
+        bottomRight.X = Console->Size.X - 1;
+        bottomRight.Y = Console->Size.Y - 1;
+        GuiConsoleUpdateSelection(Console, &bottomRight);
+        break;
+
     case ID_SYSTEM_EDIT_SCROLL:
+        DPRINT1("Scrolling is not handled yet\n");
+        break;
+
     case ID_SYSTEM_EDIT_FIND:
+        DPRINT1("Finding is not handled yet\n");
         break;
 
     case ID_SYSTEM_DEFAULTS:
@@ -1500,11 +1627,13 @@ GuiConsoleGetMinMaxInfo(HWND hWnd, PMINMAXINFO minMaxInfo)
 {
     PCSRSS_CONSOLE Console;
     PGUI_CONSOLE_DATA GuiData;
+    DWORD windx, windy;
+
     GuiConsoleGetDataPointers(hWnd, &Console, &GuiData);
     if((Console == NULL)|| (GuiData == NULL)) return;
 
-    DWORD windx = CONGUI_MIN_WIDTH * GuiData->CharWidth + 2 * (GetSystemMetrics(SM_CXFRAME) + GetSystemMetrics(SM_CXEDGE));
-    DWORD windy = CONGUI_MIN_HEIGHT * GuiData->CharHeight + 2 * (GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYEDGE)) + GetSystemMetrics(SM_CYCAPTION);
+    windx = CONGUI_MIN_WIDTH * GuiData->CharWidth + 2 * (GetSystemMetrics(SM_CXFRAME) + GetSystemMetrics(SM_CXEDGE));
+    windy = CONGUI_MIN_HEIGHT * GuiData->CharHeight + 2 * (GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYEDGE)) + GetSystemMetrics(SM_CYCAPTION);
 
     minMaxInfo->ptMinTrackSize.x = windx;
     minMaxInfo->ptMinTrackSize.y = windy;
@@ -1529,18 +1658,19 @@ GuiConsoleResize(HWND hWnd, WPARAM wParam, LPARAM lParam)
     if ((GuiData->WindowSizeLock == FALSE) && (wParam == SIZE_RESTORED || wParam == SIZE_MAXIMIZED || wParam == SIZE_MINIMIZED))
     {
         PCSRSS_SCREEN_BUFFER Buff = Console->ActiveBuffer;
+        DWORD windx, windy, charx, chary;
 
         GuiData->WindowSizeLock = TRUE;
 
-        DWORD windx = LOWORD(lParam);
-        DWORD windy = HIWORD(lParam);
+        windx = LOWORD(lParam);
+        windy = HIWORD(lParam);
 
         // Compensate for existing scroll bars (because lParam values do not accommodate scroll bar)
         if(Console->Size.X < Buff->MaxX) windy += GetSystemMetrics(SM_CYHSCROLL);    // window currently has a horizontal scrollbar
         if(Console->Size.Y < Buff->MaxY) windx += GetSystemMetrics(SM_CXVSCROLL);    // window currently has a vertical scrollbar
 
-        DWORD charx = windx / GuiData->CharWidth;
-        DWORD chary = windy / GuiData->CharHeight;
+        charx = windx / GuiData->CharWidth;
+        chary = windy / GuiData->CharHeight;
 
         // Character alignment (round size up or down)
         if((windx % GuiData->CharWidth) >= (GuiData->CharWidth / 2)) ++charx;
@@ -1892,7 +2022,7 @@ GuiConsoleWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
         GuiConsoleMouseMove(hWnd, wParam, lParam);
         break;
     case WM_SYSCOMMAND:
-        Result = GuiConsoleHandleSysMenuCommand(hWnd, wParam, lParam, GuiData);
+        Result = GuiConsoleHandleSysMenuCommand(hWnd, wParam, lParam);
         break;
     case WM_HSCROLL:
     case WM_VSCROLL: