[CONSRV]
[reactos.git] / reactos / win32ss / user / winsrv / consrv / condrv / conoutput.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Console Driver DLL
4 * FILE: win32ss/user/winsrv/consrv/condrv/conoutput.c
5 * PURPOSE: General Console Output Functions
6 * PROGRAMMERS: Jeffrey Morlan
7 * Hermes Belusca-Maito (hermes.belusca@sfr.fr)
8 */
9
10 /* INCLUDES *******************************************************************/
11
12 #include <consrv.h>
13
14 #define NDEBUG
15 #include <debug.h>
16
17 /* PRIVATE FUNCTIONS **********************************************************/
18
19 NTSTATUS
20 TEXTMODE_BUFFER_Initialize(OUT PCONSOLE_SCREEN_BUFFER* Buffer,
21 IN OUT PCONSOLE Console,
22 IN PTEXTMODE_BUFFER_INFO TextModeInfo);
23 NTSTATUS
24 GRAPHICS_BUFFER_Initialize(OUT PCONSOLE_SCREEN_BUFFER* Buffer,
25 IN OUT PCONSOLE Console,
26 IN PGRAPHICS_BUFFER_INFO GraphicsInfo);
27
28 VOID
29 TEXTMODE_BUFFER_Destroy(IN OUT PCONSOLE_SCREEN_BUFFER Buffer);
30 VOID
31 GRAPHICS_BUFFER_Destroy(IN OUT PCONSOLE_SCREEN_BUFFER Buffer);
32
33
34 NTSTATUS
35 CONSOLE_SCREEN_BUFFER_Initialize(OUT PCONSOLE_SCREEN_BUFFER* Buffer,
36 IN OUT PCONSOLE Console,
37 IN SIZE_T Size)
38 {
39 if (Buffer == NULL || Console == NULL)
40 return STATUS_INVALID_PARAMETER;
41
42 *Buffer = ConsoleAllocHeap(HEAP_ZERO_MEMORY, max(sizeof(CONSOLE_SCREEN_BUFFER), Size));
43 if (*Buffer == NULL) return STATUS_INSUFFICIENT_RESOURCES;
44
45 /* Initialize the header with the default type */
46 ConSrvInitObject(&(*Buffer)->Header, SCREEN_BUFFER, Console);
47 (*Buffer)->Vtbl = NULL;
48 return STATUS_SUCCESS;
49 }
50
51 VOID
52 CONSOLE_SCREEN_BUFFER_Destroy(IN OUT PCONSOLE_SCREEN_BUFFER Buffer)
53 {
54 if (Buffer->Header.Type == TEXTMODE_BUFFER)
55 {
56 TEXTMODE_BUFFER_Destroy(Buffer);
57 }
58 else if (Buffer->Header.Type == GRAPHICS_BUFFER)
59 {
60 GRAPHICS_BUFFER_Destroy(Buffer);
61 }
62 else if (Buffer->Header.Type == SCREEN_BUFFER)
63 {
64 // TODO: Free Buffer->Data
65
66 /* Free the palette handle */
67 if (Buffer->PaletteHandle != NULL) DeleteObject(Buffer->PaletteHandle);
68
69 /* Free the screen buffer memory */
70 ConsoleFreeHeap(Buffer);
71 }
72 // else
73 // do_nothing;
74 }
75
76 // ConDrvCreateConsoleScreenBuffer
77 NTSTATUS FASTCALL
78 ConDrvCreateScreenBuffer(OUT PCONSOLE_SCREEN_BUFFER* Buffer,
79 IN OUT PCONSOLE Console,
80 IN ULONG BufferType,
81 IN PVOID ScreenBufferInfo)
82 {
83 NTSTATUS Status = STATUS_SUCCESS;
84
85 if ( Console == NULL || Buffer == NULL ||
86 (BufferType != CONSOLE_TEXTMODE_BUFFER && BufferType != CONSOLE_GRAPHICS_BUFFER) )
87 {
88 return STATUS_INVALID_PARAMETER;
89 }
90
91 if (BufferType == CONSOLE_TEXTMODE_BUFFER)
92 {
93 Status = TEXTMODE_BUFFER_Initialize(Buffer, Console,
94 (PTEXTMODE_BUFFER_INFO)ScreenBufferInfo);
95 }
96 else if (BufferType == CONSOLE_GRAPHICS_BUFFER)
97 {
98 Status = GRAPHICS_BUFFER_Initialize(Buffer, Console,
99 (PGRAPHICS_BUFFER_INFO)ScreenBufferInfo);
100 }
101 else
102 {
103 /* Never ever go there!! */
104 ASSERT(FALSE);
105 }
106
107 /* Insert the newly created screen buffer into the list, if succeeded */
108 if (NT_SUCCESS(Status)) InsertHeadList(&Console->BufferList, &(*Buffer)->ListEntry);
109
110 return Status;
111 }
112
113 static VOID
114 ConioSetActiveScreenBuffer(PCONSOLE_SCREEN_BUFFER Buffer);
115
116 VOID NTAPI
117 ConioDeleteScreenBuffer(PCONSOLE_SCREEN_BUFFER Buffer)
118 {
119 PCONSOLE Console = Buffer->Header.Console;
120 PCONSOLE_SCREEN_BUFFER NewBuffer;
121
122 /*
123 * We should notify temporarily the frontend because we are susceptible
124 * to delete the screen buffer it is using (which may be different from
125 * the active screen buffer in some cases), and because, if it actually
126 * uses the active screen buffer, we are going to nullify its pointer to
127 * change it.
128 */
129 TermReleaseScreenBuffer(Console, Buffer);
130
131 RemoveEntryList(&Buffer->ListEntry);
132 if (Buffer == Console->ActiveBuffer)
133 {
134 /* Delete active buffer; switch to most recently created */
135 if (!IsListEmpty(&Console->BufferList))
136 {
137 NewBuffer = CONTAINING_RECORD(Console->BufferList.Flink,
138 CONSOLE_SCREEN_BUFFER,
139 ListEntry);
140
141 /* Tie console to new buffer and signal the change to the frontend */
142 ConioSetActiveScreenBuffer(NewBuffer);
143 }
144 else
145 {
146 Console->ActiveBuffer = NULL;
147 // InterlockedExchangePointer(&Console->ActiveBuffer, NULL);
148 }
149 }
150
151 CONSOLE_SCREEN_BUFFER_Destroy(Buffer);
152 }
153
154 VOID FASTCALL
155 ConioDrawConsole(PCONSOLE Console)
156 {
157 SMALL_RECT Region;
158 PCONSOLE_SCREEN_BUFFER ActiveBuffer = Console->ActiveBuffer;
159
160 if (ActiveBuffer)
161 {
162 ConioInitRect(&Region, 0, 0, ActiveBuffer->ViewSize.Y - 1, ActiveBuffer->ViewSize.X - 1);
163 TermDrawRegion(Console, &Region);
164 }
165 }
166
167 static VOID
168 ConioSetActiveScreenBuffer(PCONSOLE_SCREEN_BUFFER Buffer)
169 {
170 PCONSOLE Console = Buffer->Header.Console;
171 Console->ActiveBuffer = Buffer;
172 // InterlockedExchangePointer(&Console->ActiveBuffer, Buffer);
173 TermSetActiveScreenBuffer(Console);
174 }
175
176 NTSTATUS NTAPI
177 ConDrvSetConsoleActiveScreenBuffer(IN PCONSOLE Console,
178 IN PCONSOLE_SCREEN_BUFFER Buffer)
179 {
180 if (Console == NULL || Buffer == NULL)
181 return STATUS_INVALID_PARAMETER;
182
183 /* Validity check */
184 ASSERT(Console == Buffer->Header.Console);
185
186 if (Buffer == Console->ActiveBuffer) return STATUS_SUCCESS;
187
188 /* If old buffer has no handles, it's now unreferenced */
189 if (Console->ActiveBuffer->Header.HandleCount == 0)
190 {
191 ConioDeleteScreenBuffer(Console->ActiveBuffer);
192 }
193
194 /* Tie console to new buffer and signal the change to the frontend */
195 ConioSetActiveScreenBuffer(Buffer);
196
197 return STATUS_SUCCESS;
198 }
199
200 PCONSOLE_SCREEN_BUFFER
201 ConDrvGetActiveScreenBuffer(IN PCONSOLE Console)
202 {
203 return (Console ? Console->ActiveBuffer : NULL);
204 }
205
206 /* PUBLIC DRIVER APIS *********************************************************/
207
208 NTSTATUS NTAPI
209 ConDrvInvalidateBitMapRect(IN PCONSOLE Console,
210 IN PCONSOLE_SCREEN_BUFFER Buffer,
211 IN PSMALL_RECT Region)
212 {
213 if (Console == NULL || Buffer == NULL || Region == NULL)
214 return STATUS_INVALID_PARAMETER;
215
216 /* Validity check */
217 ASSERT(Console == Buffer->Header.Console);
218
219 /* If the output buffer is the current one, redraw the correct portion of the screen */
220 if (Buffer == Console->ActiveBuffer) TermDrawRegion(Console, Region);
221
222 return STATUS_SUCCESS;
223 }
224
225 NTSTATUS NTAPI
226 ConDrvSetConsolePalette(IN PCONSOLE Console,
227 // IN PGRAPHICS_SCREEN_BUFFER Buffer,
228 IN PCONSOLE_SCREEN_BUFFER Buffer,
229 IN HPALETTE PaletteHandle,
230 IN UINT PaletteUsage)
231 {
232 BOOL Success;
233
234 /*
235 * Parameters validation
236 */
237 if (Console == NULL || Buffer == NULL)
238 return STATUS_INVALID_PARAMETER;
239
240 if ( PaletteUsage != SYSPAL_STATIC &&
241 PaletteUsage != SYSPAL_NOSTATIC &&
242 PaletteUsage != SYSPAL_NOSTATIC256 )
243 {
244 return STATUS_INVALID_PARAMETER;
245 }
246
247 /* Validity check */
248 ASSERT(Console == Buffer->Header.Console);
249
250 /* Change the palette */
251 Success = TermSetPalette(Console, PaletteHandle, PaletteUsage);
252 if (Success)
253 {
254 /* Free the old palette handle if there was already one set */
255 if ( Buffer->PaletteHandle != NULL &&
256 Buffer->PaletteHandle != PaletteHandle )
257 {
258 DeleteObject(Buffer->PaletteHandle);
259 }
260
261 /* Save the new palette in the screen buffer */
262 Buffer->PaletteHandle = PaletteHandle;
263 Buffer->PaletteUsage = PaletteUsage;
264 }
265
266 return (Success ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
267 }
268
269 NTSTATUS NTAPI
270 ConDrvGetConsoleCursorInfo(IN PCONSOLE Console,
271 IN PTEXTMODE_SCREEN_BUFFER Buffer,
272 OUT PCONSOLE_CURSOR_INFO CursorInfo)
273 {
274 if (Console == NULL || Buffer == NULL || CursorInfo == NULL)
275 return STATUS_INVALID_PARAMETER;
276
277 /* Validity check */
278 ASSERT(Console == Buffer->Header.Console);
279
280 *CursorInfo = Buffer->CursorInfo;
281 // CursorInfo->bVisible = Buffer->CursorInfo.bVisible;
282 // CursorInfo->dwSize = Buffer->CursorInfo.dwSize;
283
284 return STATUS_SUCCESS;
285 }
286
287 NTSTATUS NTAPI
288 ConDrvSetConsoleCursorInfo(IN PCONSOLE Console,
289 IN PTEXTMODE_SCREEN_BUFFER Buffer,
290 IN PCONSOLE_CURSOR_INFO CursorInfo)
291 {
292 ULONG Size;
293 BOOLEAN Visible, Success = TRUE;
294
295 if (Console == NULL || Buffer == NULL || CursorInfo == NULL)
296 return STATUS_INVALID_PARAMETER;
297
298 /* Validity check */
299 ASSERT(Console == Buffer->Header.Console);
300
301 Size = min(max(CursorInfo->dwSize, 1), 100);
302 Visible = CursorInfo->bVisible;
303
304 if ( (Size != Buffer->CursorInfo.dwSize) ||
305 (Visible && !Buffer->CursorInfo.bVisible) ||
306 (!Visible && Buffer->CursorInfo.bVisible) )
307 {
308 Buffer->CursorInfo.dwSize = Size;
309 Buffer->CursorInfo.bVisible = Visible;
310
311 Success = TermSetCursorInfo(Console, (PCONSOLE_SCREEN_BUFFER)Buffer);
312 }
313
314 return (Success ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
315 }
316
317 NTSTATUS NTAPI
318 ConDrvSetConsoleCursorPosition(IN PCONSOLE Console,
319 IN PTEXTMODE_SCREEN_BUFFER Buffer,
320 IN PCOORD Position)
321 {
322 SHORT OldCursorX, OldCursorY;
323
324 if (Console == NULL || Buffer == NULL || Position == NULL)
325 return STATUS_INVALID_PARAMETER;
326
327 /* Validity check */
328 ASSERT(Console == Buffer->Header.Console);
329
330 if ( Position->X < 0 || Position->X >= Buffer->ScreenBufferSize.X ||
331 Position->Y < 0 || Position->Y >= Buffer->ScreenBufferSize.Y )
332 {
333 return STATUS_INVALID_PARAMETER;
334 }
335
336 OldCursorX = Buffer->CursorPosition.X;
337 OldCursorY = Buffer->CursorPosition.Y;
338 Buffer->CursorPosition = *Position;
339 // Buffer->CursorPosition.X = Position->X;
340 // Buffer->CursorPosition.Y = Position->Y;
341 if ( ((PCONSOLE_SCREEN_BUFFER)Buffer == Console->ActiveBuffer) &&
342 (!TermSetScreenInfo(Console, (PCONSOLE_SCREEN_BUFFER)Buffer, OldCursorX, OldCursorY)) )
343 {
344 return STATUS_UNSUCCESSFUL;
345 }
346
347 return STATUS_SUCCESS;
348 }
349
350 /* EOF */