1 /*
2  * COPYRIGHT:       See COPYING in the top level directory
3  * PROJECT:         ReactOS Console Server DLL
4  * FILE:            win32ss/user/winsrv/consrv/frontends/gui/graphics.c
5  * PURPOSE:         GUI Terminal Front-End - Support for graphics-mode screen-buffers
6  * PROGRAMMERS:     Hermes Belusca-Maito (hermes.belusca@sfr.fr)
7  */
8 
9 /* INCLUDES *******************************************************************/
10 
11 #include <consrv.h>
12 
13 #define NDEBUG
14 #include <debug.h>
15 
16 #include "guiterm.h"
17 
18 /* FUNCTIONS ******************************************************************/
19 
20 VOID
21 GuiCopyFromGraphicsBuffer(PGRAPHICS_SCREEN_BUFFER Buffer,
22                           PGUI_CONSOLE_DATA GuiData)
23 {
24     /*
25      * This function supposes that the system clipboard was opened.
26      */
27 
28     HDC hMemDC;
29     HBITMAP  hBitmapTarget, hBitmapOld;
30     HPALETTE hPalette, hPaletteOld;
31     ULONG selWidth, selHeight;
32 
33     if (Buffer->BitMap == NULL) return;
34 
35     selWidth  = ConioRectWidth(&GuiData->Selection.srSelection);
36     selHeight = ConioRectHeight(&GuiData->Selection.srSelection);
37     DPRINT("Selection is (%d|%d) to (%d|%d)\n",
38            GuiData->Selection.srSelection.Left,
39            GuiData->Selection.srSelection.Top,
40            GuiData->Selection.srSelection.Right,
41            GuiData->Selection.srSelection.Bottom);
42 
43     hMemDC = CreateCompatibleDC(GuiData->hMemDC);
44     if (hMemDC == NULL) return;
45 
46     /* Allocate a bitmap to be given to the clipboard, so it will not be freed here */
47     hBitmapTarget = CreateCompatibleBitmap(GuiData->hMemDC, selWidth, selHeight);
48     if (hBitmapTarget == NULL)
49     {
50         DeleteDC(hMemDC);
51         return;
52     }
53 
54     /* Select the new bitmap */
55     hBitmapOld = SelectObject(hMemDC, hBitmapTarget);
56 
57     /* Change the palette in hMemDC if the current palette does exist */
58     if (Buffer->PaletteHandle == NULL)
59         hPalette = GuiData->hSysPalette;
60     else
61         hPalette = Buffer->PaletteHandle;
62 
63     if (hPalette) hPaletteOld = SelectPalette(hMemDC, hPalette, FALSE);
64 
65     /* Grab the mutex */
66     NtWaitForSingleObject(Buffer->Mutex, FALSE, NULL);
67 
68     // The equivalent of a SetDIBitsToDevice call...
69     // It seems to be broken: it does not copy the tail of the bitmap.
70     // http://wiki.allegro.cc/index.php?title=StretchDIBits
71 #if 0
72     StretchDIBits(hMemDC,
73                   0, 0,
74                   selWidth, selHeight,
75                   GuiData->Selection.srSelection.Left,
76                   GuiData->Selection.srSelection.Top,
77                   selWidth, selHeight,
78                   Buffer->BitMap,
79                   Buffer->BitMapInfo,
80                   Buffer->BitMapUsage,
81                   SRCCOPY);
82 #else
83     SetDIBitsToDevice(hMemDC,
84                       /* Coordinates / size of the repainted rectangle, in the framebuffer's frame */
85                       0, 0,
86                       selWidth, selHeight,
87                       /* Coordinates / size of the corresponding image portion, in the graphics screen-buffer's frame */
88                       GuiData->Selection.srSelection.Left,
89                       GuiData->Selection.srSelection.Top,
90                       0,
91                       Buffer->ScreenBufferSize.Y, // == Buffer->BitMapInfo->bmiHeader.biHeight
92                       Buffer->BitMap,
93                       Buffer->BitMapInfo,
94                       Buffer->BitMapUsage);
95 #endif
96 
97     /* Release the mutex */
98     NtReleaseMutant(Buffer->Mutex, NULL);
99 
100     /* Restore the palette and the old bitmap */
101     if (hPalette) SelectPalette(hMemDC, hPaletteOld, FALSE);
102     SelectObject(hMemDC, hBitmapOld);
103 
104     EmptyClipboard();
105     SetClipboardData(CF_BITMAP, hBitmapTarget);
106 
107     DeleteDC(hMemDC);
108 }
109 
110 VOID
111 GuiPasteToGraphicsBuffer(PGRAPHICS_SCREEN_BUFFER Buffer,
112                          PGUI_CONSOLE_DATA GuiData)
113 {
114     /*
115      * This function supposes that the system clipboard was opened.
116      */
117 
118     // PCONSRV_CONSOLE Console = Buffer->Header.Console;
119 
120     UNIMPLEMENTED;
121 }
122 
123 VOID
124 GuiPaintGraphicsBuffer(PGRAPHICS_SCREEN_BUFFER Buffer,
125                        PGUI_CONSOLE_DATA GuiData,
126                        PRECT rcView,
127                        PRECT rcFramebuffer)
128 {
129     PCONSRV_CONSOLE Console = (PCONSRV_CONSOLE)Buffer->Header.Console;
130     // ASSERT(Console == GuiData->Console);
131 
132     ConioInitLongRect(rcFramebuffer, 0, 0, 0, 0);
133 
134     if (Buffer->BitMap == NULL)
135         return;
136 
137     if (!ConDrvValidateConsoleUnsafe((PCONSOLE)Console, CONSOLE_RUNNING, TRUE))
138         return;
139 
140     ConioInitLongRect(rcFramebuffer,
141                       Buffer->ViewOrigin.Y * 1 + rcView->top,
142                       Buffer->ViewOrigin.X * 1 + rcView->left,
143                       Buffer->ViewOrigin.Y * 1 + rcView->bottom,
144                       Buffer->ViewOrigin.X * 1 + rcView->right);
145 
146     /* Grab the mutex */
147     NtWaitForSingleObject(Buffer->Mutex, FALSE, NULL);
148 
149     /*
150      * The seventh parameter (YSrc) of SetDIBitsToDevice always designates
151      * the Y-coordinate of the "lower-left corner" of the image, be the DIB
152      * in bottom-up or top-down mode.
153      */
154     SetDIBitsToDevice(GuiData->hMemDC,
155                       /* Coordinates / size of the repainted rectangle, in the framebuffer's frame */
156                       rcFramebuffer->left,
157                       rcFramebuffer->top,
158                       rcFramebuffer->right  - rcFramebuffer->left,
159                       rcFramebuffer->bottom - rcFramebuffer->top,
160                       /* Coordinates / size of the corresponding image portion, in the graphics screen-buffer's frame */
161                       rcFramebuffer->left,
162                       rcFramebuffer->top,
163                       0,
164                       Buffer->ScreenBufferSize.Y, // == Buffer->BitMapInfo->bmiHeader.biHeight
165                       Buffer->BitMap,
166                       Buffer->BitMapInfo,
167                       Buffer->BitMapUsage);
168 
169     /* Release the mutex */
170     NtReleaseMutant(Buffer->Mutex, NULL);
171 
172     LeaveCriticalSection(&Console->Lock);
173 }
174 
175 /* EOF */
176