From 2b427f2fba439b1554cce5c7b1b3a86df951e261 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Herm=C3=A8s=20B=C3=A9lusca-Ma=C3=AFto?= Date: Sun, 16 Mar 2014 02:15:53 +0000 Subject: [PATCH] [CONSRV] - 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 --- .../winsrv/consrv/frontends/gui/graphics.c | 89 ++++++++++++++++++- .../winsrv/consrv/frontends/gui/guiterm.c | 26 ++++-- .../user/winsrv/consrv/frontends/gui/text.c | 14 ++- 3 files changed, 113 insertions(+), 16 deletions(-) diff --git a/reactos/win32ss/user/winsrv/consrv/frontends/gui/graphics.c b/reactos/win32ss/user/winsrv/consrv/frontends/gui/graphics.c index 3ac9cc24b66..69808518b94 100644 --- a/reactos/win32ss/user/winsrv/consrv/frontends/gui/graphics.c +++ b/reactos/win32ss/user/winsrv/consrv/frontends/gui/graphics.c @@ -16,19 +16,100 @@ /* 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. diff --git a/reactos/win32ss/user/winsrv/consrv/frontends/gui/guiterm.c b/reactos/win32ss/user/winsrv/consrv/frontends/gui/guiterm.c index acc870b40eb..e01dbdade3f 100644 --- a/reactos/win32ss/user/winsrv/consrv/frontends/gui/guiterm.c +++ b/reactos/win32ss/user/winsrv/consrv/frontends/gui/guiterm.c @@ -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)); diff --git a/reactos/win32ss/user/winsrv/consrv/frontends/gui/text.c b/reactos/win32ss/user/winsrv/consrv/frontends/gui/text.c index 79d5d9b46ff..d39fe614553 100644 --- a/reactos/win32ss/user/winsrv/consrv/frontends/gui/text.c +++ b/reactos/win32ss/user/winsrv/consrv/frontends/gui/text.c @@ -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. -- 2.17.1