[CONSRV]
authorHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Sun, 16 Mar 2014 02:15:53 +0000 (02:15 +0000)
committerHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Sun, 16 Mar 2014 02:15:53 +0000 (02:15 +0000)
- Free allocated memory in case GlobalLock fails.
- Implement bitmap copy of graphics screen buffers. It seems that the call to StretchDIBits doesn't work correctly (it copies the image but removes a band of height == Console->Selection.srSelection.Top at the bottom of the copied image), so in the meantime I call SetDIBitsToDevice which does correctly the job. It would be nice that some win32k guy has a look at this... :D
Have fun!

svn path=/trunk/; revision=62513

reactos/win32ss/user/winsrv/consrv/frontends/gui/graphics.c
reactos/win32ss/user/winsrv/consrv/frontends/gui/guiterm.c
reactos/win32ss/user/winsrv/consrv/frontends/gui/text.c

index 3ac9cc2..6980851 100644 (file)
 /* FUNCTIONS ******************************************************************/
 
 VOID
-GuiCopyFromGraphicsBuffer(PGRAPHICS_SCREEN_BUFFER Buffer)
+GuiCopyFromGraphicsBuffer(PGRAPHICS_SCREEN_BUFFER Buffer,
+                          PGUI_CONSOLE_DATA GuiData)
 {
     /*
      * This function supposes that the system clipboard was opened.
      */
 
-    // PCONSOLE Console = Buffer->Header.Console;
+    PCONSOLE Console = Buffer->Header.Console;
 
-    UNIMPLEMENTED;
+    HDC hMemDC;
+    HBITMAP  hBitmapTarget, hBitmapOld;
+    HPALETTE hPalette, hPaletteOld;
+    ULONG selWidth, selHeight;
+
+    if (Buffer->BitMap == NULL) return;
+
+    selWidth  = Console->Selection.srSelection.Right - Console->Selection.srSelection.Left + 1;
+    selHeight = Console->Selection.srSelection.Bottom - Console->Selection.srSelection.Top + 1;
+    DPRINT1("Selection is (%d|%d) to (%d|%d)\n",
+           Console->Selection.srSelection.Left,
+           Console->Selection.srSelection.Top,
+           Console->Selection.srSelection.Right,
+           Console->Selection.srSelection.Bottom);
+
+    hMemDC = CreateCompatibleDC(GuiData->hMemDC);
+    if (hMemDC == NULL) return;
+
+    /* Allocate a bitmap to be given to the clipboard, so it will not be freed here */
+    hBitmapTarget = CreateCompatibleBitmap(GuiData->hMemDC, selWidth, selHeight);
+    if (hBitmapTarget == NULL)
+    {
+        DeleteDC(hMemDC);
+        return;
+    }
+
+    /* Select the new bitmap */
+    hBitmapOld = SelectObject(hMemDC, hBitmapTarget);
+
+    /* Change the palette in hMemDC if the current palette does exist */
+    if (Buffer->PaletteHandle == NULL)
+        hPalette = GuiData->hSysPalette;
+    else
+        hPalette = Buffer->PaletteHandle;
+
+    if (hPalette) hPaletteOld = SelectPalette(hMemDC, hPalette, FALSE);
+
+    /* Grab the mutex */
+    NtWaitForSingleObject(Buffer->Mutex, FALSE, NULL);
+
+    // The equivalent of a SetDIBitsToDevice call...
+    // It seems to be broken: it does not copy the tail of the bitmap.
+    // http://wiki.allegro.cc/index.php?title=StretchDIBits
+#if 0
+    StretchDIBits(hMemDC,
+                  0, 0,
+                  selWidth, selHeight,
+                  Console->Selection.srSelection.Left,
+                  Console->Selection.srSelection.Top,
+                  selWidth, selHeight,
+                  Buffer->BitMap,
+                  Buffer->BitMapInfo,
+                  Buffer->BitMapUsage,
+                  SRCCOPY);
+#else
+    SetDIBitsToDevice(hMemDC,
+                      /* Coordinates / size of the repainted rectangle, in the framebuffer's frame */
+                      0, 0,
+                      selWidth, selHeight,
+                      /* Coordinates / size of the corresponding image portion, in the graphics screen-buffer's frame */
+                      Console->Selection.srSelection.Left,
+                      Console->Selection.srSelection.Top,
+                      0,
+                      Buffer->ScreenBufferSize.Y, // == Buffer->BitMapInfo->bmiHeader.biHeight
+                      Buffer->BitMap,
+                      Buffer->BitMapInfo,
+                      Buffer->BitMapUsage);
+#endif
+
+    /* Release the mutex */
+    NtReleaseMutant(Buffer->Mutex, NULL);
+
+    /* Restore the palette and the old bitmap */
+    if (hPalette) SelectPalette(hMemDC, hPaletteOld, FALSE);
+    SelectObject(hMemDC, hBitmapOld);
+
+    EmptyClipboard();
+    SetClipboardData(CF_BITMAP, hBitmapTarget);
+
+    DeleteDC(hMemDC);
 }
 
 VOID
-GuiPasteToGraphicsBuffer(PGRAPHICS_SCREEN_BUFFER Buffer)
+GuiPasteToGraphicsBuffer(PGRAPHICS_SCREEN_BUFFER Buffer,
+                         PGUI_CONSOLE_DATA GuiData)
 {
     /*
      * This function supposes that the system clipboard was opened.
index acc870b..e01dbda 100644 (file)
@@ -1333,8 +1333,12 @@ Quit:
         return 0;
 }
 
-VOID GuiCopyFromTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer);
-VOID GuiCopyFromGraphicsBuffer(PGRAPHICS_SCREEN_BUFFER Buffer);
+VOID
+GuiCopyFromTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer,
+                          PGUI_CONSOLE_DATA GuiData);
+VOID
+GuiCopyFromGraphicsBuffer(PGRAPHICS_SCREEN_BUFFER Buffer,
+                          PGUI_CONSOLE_DATA GuiData);
 
 static VOID
 GuiConsoleCopy(PGUI_CONSOLE_DATA GuiData)
@@ -1346,11 +1350,11 @@ GuiConsoleCopy(PGUI_CONSOLE_DATA GuiData)
 
         if (GetType(Buffer) == TEXTMODE_BUFFER)
         {
-            GuiCopyFromTextModeBuffer((PTEXTMODE_SCREEN_BUFFER)Buffer);
+            GuiCopyFromTextModeBuffer((PTEXTMODE_SCREEN_BUFFER)Buffer, GuiData);
         }
         else /* if (GetType(Buffer) == GRAPHICS_BUFFER) */
         {
-            GuiCopyFromGraphicsBuffer((PGRAPHICS_SCREEN_BUFFER)Buffer);
+            GuiCopyFromGraphicsBuffer((PGRAPHICS_SCREEN_BUFFER)Buffer, GuiData);
         }
 
         CloseClipboard();
@@ -1361,8 +1365,12 @@ GuiConsoleCopy(PGUI_CONSOLE_DATA GuiData)
     }
 }
 
-VOID GuiPasteToTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer);
-VOID GuiPasteToGraphicsBuffer(PGRAPHICS_SCREEN_BUFFER Buffer);
+VOID
+GuiPasteToTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer,
+                         PGUI_CONSOLE_DATA GuiData);
+VOID
+GuiPasteToGraphicsBuffer(PGRAPHICS_SCREEN_BUFFER Buffer,
+                         PGUI_CONSOLE_DATA GuiData);
 
 static VOID
 GuiConsolePaste(PGUI_CONSOLE_DATA GuiData)
@@ -1373,11 +1381,11 @@ GuiConsolePaste(PGUI_CONSOLE_DATA GuiData)
 
         if (GetType(Buffer) == TEXTMODE_BUFFER)
         {
-            GuiPasteToTextModeBuffer((PTEXTMODE_SCREEN_BUFFER)Buffer);
+            GuiPasteToTextModeBuffer((PTEXTMODE_SCREEN_BUFFER)Buffer, GuiData);
         }
         else /* if (GetType(Buffer) == GRAPHICS_BUFFER) */
         {
-            GuiPasteToGraphicsBuffer((PGRAPHICS_SCREEN_BUFFER)Buffer);
+            GuiPasteToGraphicsBuffer((PGRAPHICS_SCREEN_BUFFER)Buffer, GuiData);
         }
 
         CloseClipboard();
@@ -1909,6 +1917,8 @@ GuiConsoleWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
                 EnableMenuItem(hMenu, ID_SYSTEM_EDIT_COPY , MF_BYCOMMAND |
                                ((Console->Selection.dwFlags & CONSOLE_SELECTION_IN_PROGRESS) &&
                                 (Console->Selection.dwFlags & CONSOLE_SELECTION_NOT_EMPTY) ? MF_ENABLED : MF_GRAYED));
+                // FIXME: Following whether the active screen buffer is text-mode
+                // or graphics-mode, search for CF_UNICODETEXT or CF_BITMAP formats.
                 EnableMenuItem(hMenu, ID_SYSTEM_EDIT_PASTE, MF_BYCOMMAND |
                                (!(Console->Selection.dwFlags & CONSOLE_SELECTION_IN_PROGRESS) &&
                                 IsClipboardFormatAvailable(CF_UNICODETEXT) ? MF_ENABLED : MF_GRAYED));
index 79d5d9b..d39fe61 100644 (file)
@@ -30,7 +30,8 @@ COLORREF RGBFromAttrib2(PCONSOLE Console, WORD Attribute)
 }
 
 VOID
-GuiCopyFromTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer)
+GuiCopyFromTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer,
+                          PGUI_CONSOLE_DATA GuiData)
 {
     /*
      * This function supposes that the system clipboard was opened.
@@ -72,12 +73,16 @@ GuiCopyFromTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer)
     size += 1; /* Null-termination */
     size *= sizeof(WCHAR);
 
-    /* Allocate memory, it will be passed to the system and may not be freed here */
+    /* Allocate some memory area to be given to the clipboard, so it will not be freed here */
     hData = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, size);
     if (hData == NULL) return;
 
     data = GlobalLock(hData);
-    if (data == NULL) return;
+    if (data == NULL)
+    {
+        GlobalFree(hData);
+        return;
+    }
 
     DPRINT("Copying %dx%d selection\n", selWidth, selHeight);
     dstPos = data;
@@ -121,7 +126,8 @@ GuiCopyFromTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer)
 }
 
 VOID
-GuiPasteToTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer)
+GuiPasteToTextModeBuffer(PTEXTMODE_SCREEN_BUFFER Buffer,
+                         PGUI_CONSOLE_DATA GuiData)
 {
     /*
      * This function supposes that the system clipboard was opened.