8f05b0411f101280ff4e05f6859e98fb159c0db9
[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 #include "console.h"
14 #include "include/conio.h"
15 #include "include/term.h"
16 #include "conoutput.h"
17 #include "handle.h"
18
19 #define NDEBUG
20 #include <debug.h>
21
22
23 /* PRIVATE FUNCTIONS **********************************************************/
24
25 NTSTATUS
26 TEXTMODE_BUFFER_Initialize(OUT PCONSOLE_SCREEN_BUFFER* Buffer,
27 IN OUT PCONSOLE Console,
28 IN PTEXTMODE_BUFFER_INFO TextModeInfo);
29 NTSTATUS
30 GRAPHICS_BUFFER_Initialize(OUT PCONSOLE_SCREEN_BUFFER* Buffer,
31 IN OUT PCONSOLE Console,
32 IN PGRAPHICS_BUFFER_INFO GraphicsInfo);
33
34 VOID
35 TEXTMODE_BUFFER_Destroy(IN OUT PCONSOLE_SCREEN_BUFFER Buffer);
36 VOID
37 GRAPHICS_BUFFER_Destroy(IN OUT PCONSOLE_SCREEN_BUFFER Buffer);
38
39
40 NTSTATUS
41 CONSOLE_SCREEN_BUFFER_Initialize(OUT PCONSOLE_SCREEN_BUFFER* Buffer,
42 IN OUT PCONSOLE Console,
43 IN SIZE_T Size)
44 {
45 if (Buffer == NULL || Console == NULL)
46 return STATUS_INVALID_PARAMETER;
47
48 *Buffer = ConsoleAllocHeap(HEAP_ZERO_MEMORY, max(sizeof(CONSOLE_SCREEN_BUFFER), Size));
49 if (*Buffer == NULL) return STATUS_INSUFFICIENT_RESOURCES;
50
51 /* Initialize the header with the default type */
52 ConSrvInitObject(&(*Buffer)->Header, SCREEN_BUFFER, Console);
53 (*Buffer)->Vtbl = NULL;
54 return STATUS_SUCCESS;
55 }
56
57 VOID
58 CONSOLE_SCREEN_BUFFER_Destroy(IN OUT PCONSOLE_SCREEN_BUFFER Buffer)
59 {
60 if (Buffer->Header.Type == TEXTMODE_BUFFER)
61 {
62 TEXTMODE_BUFFER_Destroy(Buffer);
63 }
64 else if (Buffer->Header.Type == GRAPHICS_BUFFER)
65 {
66 GRAPHICS_BUFFER_Destroy(Buffer);
67 }
68 else if (Buffer->Header.Type == SCREEN_BUFFER)
69 {
70 // TODO: Free Buffer->Data
71
72 /* Free the palette handle */
73 if (Buffer->PaletteHandle != NULL) DeleteObject(Buffer->PaletteHandle);
74
75 /* Free the screen buffer memory */
76 ConsoleFreeHeap(Buffer);
77 }
78 // else
79 // do_nothing;
80 }
81
82 // ConDrvCreateConsoleScreenBuffer
83 NTSTATUS FASTCALL
84 ConDrvCreateScreenBuffer(OUT PCONSOLE_SCREEN_BUFFER* Buffer,
85 IN OUT PCONSOLE Console,
86 IN ULONG BufferType,
87 IN PVOID ScreenBufferInfo)
88 {
89 NTSTATUS Status = STATUS_SUCCESS;
90
91 if ( Console == NULL || Buffer == NULL ||
92 (BufferType != CONSOLE_TEXTMODE_BUFFER && BufferType != CONSOLE_GRAPHICS_BUFFER) )
93 {
94 return STATUS_INVALID_PARAMETER;
95 }
96
97 if (BufferType == CONSOLE_TEXTMODE_BUFFER)
98 {
99 Status = TEXTMODE_BUFFER_Initialize(Buffer, Console,
100 (PTEXTMODE_BUFFER_INFO)ScreenBufferInfo);
101 }
102 else if (BufferType == CONSOLE_GRAPHICS_BUFFER)
103 {
104 Status = GRAPHICS_BUFFER_Initialize(Buffer, Console,
105 (PGRAPHICS_BUFFER_INFO)ScreenBufferInfo);
106 }
107 else
108 {
109 /* Never ever go there!! */
110 ASSERT(FALSE);
111 }
112
113 /* Insert the newly created screen buffer into the list, if succeeded */
114 if (NT_SUCCESS(Status)) InsertHeadList(&Console->BufferList, &(*Buffer)->ListEntry);
115
116 return Status;
117 }
118
119 static VOID
120 ConioSetActiveScreenBuffer(PCONSOLE_SCREEN_BUFFER Buffer);
121
122 VOID NTAPI
123 ConioDeleteScreenBuffer(PCONSOLE_SCREEN_BUFFER Buffer)
124 {
125 PCONSOLE Console = Buffer->Header.Console;
126 PCONSOLE_SCREEN_BUFFER NewBuffer;
127
128 /*
129 * We should notify temporarily the frontend because we are susceptible
130 * to delete the screen buffer it is using (which may be different from
131 * the active screen buffer in some cases), and because, if it actually
132 * uses the active screen buffer, we are going to nullify its pointer to
133 * change it.
134 */
135 TermReleaseScreenBuffer(Console, Buffer);
136
137 RemoveEntryList(&Buffer->ListEntry);
138 if (Buffer == Console->ActiveBuffer)
139 {
140 /* Delete active buffer; switch to most recently created */
141 if (!IsListEmpty(&Console->BufferList))
142 {
143 NewBuffer = CONTAINING_RECORD(Console->BufferList.Flink,
144 CONSOLE_SCREEN_BUFFER,
145 ListEntry);
146
147 /* Tie console to new buffer and signal the change to the frontend */
148 ConioSetActiveScreenBuffer(NewBuffer);
149 }
150 else
151 {
152 Console->ActiveBuffer = NULL;
153 // InterlockedExchangePointer(&Console->ActiveBuffer, NULL);
154 }
155 }
156
157 CONSOLE_SCREEN_BUFFER_Destroy(Buffer);
158 }
159
160 VOID FASTCALL
161 ConioDrawConsole(PCONSOLE Console)
162 {
163 SMALL_RECT Region;
164 PCONSOLE_SCREEN_BUFFER ActiveBuffer = Console->ActiveBuffer;
165
166 if (ActiveBuffer)
167 {
168 ConioInitRect(&Region, 0, 0, ActiveBuffer->ViewSize.Y - 1, ActiveBuffer->ViewSize.X - 1);
169 TermDrawRegion(Console, &Region);
170 }
171 }
172
173 static VOID
174 ConioSetActiveScreenBuffer(PCONSOLE_SCREEN_BUFFER Buffer)
175 {
176 PCONSOLE Console = Buffer->Header.Console;
177 Console->ActiveBuffer = Buffer;
178 // InterlockedExchangePointer(&Console->ActiveBuffer, Buffer);
179 TermSetActiveScreenBuffer(Console);
180 }
181
182 NTSTATUS NTAPI
183 ConDrvSetConsoleActiveScreenBuffer(IN PCONSOLE Console,
184 IN PCONSOLE_SCREEN_BUFFER Buffer)
185 {
186 if (Console == NULL || Buffer == NULL)
187 return STATUS_INVALID_PARAMETER;
188
189 /* Validity check */
190 ASSERT(Console == Buffer->Header.Console);
191
192 if (Buffer == Console->ActiveBuffer) return STATUS_SUCCESS;
193
194 /* If old buffer has no handles, it's now unreferenced */
195 if (Console->ActiveBuffer->Header.HandleCount == 0)
196 {
197 ConioDeleteScreenBuffer(Console->ActiveBuffer);
198 }
199
200 /* Tie console to new buffer and signal the change to the frontend */
201 ConioSetActiveScreenBuffer(Buffer);
202
203 return STATUS_SUCCESS;
204 }
205
206 PCONSOLE_SCREEN_BUFFER
207 ConDrvGetActiveScreenBuffer(IN PCONSOLE Console)
208 {
209 return (Console ? Console->ActiveBuffer : NULL);
210 }
211
212 /* PUBLIC DRIVER APIS *********************************************************/
213
214 NTSTATUS NTAPI
215 ConDrvInvalidateBitMapRect(IN PCONSOLE Console,
216 IN PCONSOLE_SCREEN_BUFFER Buffer,
217 IN PSMALL_RECT Region)
218 {
219 if (Console == NULL || Buffer == NULL || Region == NULL)
220 return STATUS_INVALID_PARAMETER;
221
222 /* Validity check */
223 ASSERT(Console == Buffer->Header.Console);
224
225 /* If the output buffer is the current one, redraw the correct portion of the screen */
226 if (Buffer == Console->ActiveBuffer) TermDrawRegion(Console, Region);
227
228 return STATUS_SUCCESS;
229 }
230
231 NTSTATUS NTAPI
232 ConDrvSetConsolePalette(IN PCONSOLE Console,
233 // IN PGRAPHICS_SCREEN_BUFFER Buffer,
234 IN PCONSOLE_SCREEN_BUFFER Buffer,
235 IN HPALETTE PaletteHandle,
236 IN UINT PaletteUsage)
237 {
238 BOOL Success;
239
240 /******************************************************************************\
241 |************** HACK! HACK! HACK! HACK! HACK! HACK! HACK! HACK! ***************|
242 \******************************************************************************/
243
244 #define PALETTESIZE 256
245
246 UINT i;
247 LPLOGPALETTE LogPalette; /* Pointer to logical palette */
248
249 PALETTEENTRY MyPalette[] =
250 { {0, 0, 0x80,0} , // 1
251 {0, 0x80,0, 0} , // 2
252 {0, 0, 0, 0} , // 0
253 {0, 0x80,0x80,0} , // 3
254 {0x80,0, 0, 0} , // 4
255 {0x80,0, 0x80,0} , // 5
256 {0x80,0x80,0, 0} , // 6
257 {0xC0,0xC0,0xC0,0} , // 7
258 {0x80,0x80,0x80,0} , // 8
259 {0, 0, 0xFF,0} , // 9
260 {0, 0xFF,0, 0} , // 10
261 {0, 0xFF,0xFF,0} , // 11
262 {0xFF,0, 0, 0} , // 12
263 {0xFF,0, 0xFF,0} , // 13
264 {0xFF,0xFF,0, 0} , // 14
265 {0xFF,0xFF,0xFF,0} }; // 15
266
267 /******************************************************************************\
268 |************** HACK! HACK! HACK! HACK! HACK! HACK! HACK! HACK! ***************|
269 \******************************************************************************/
270
271 DPRINT1("ConDrvSetConsolePalette checkpt 0\n");
272
273 if (Console == NULL || Buffer == NULL)
274 return STATUS_INVALID_PARAMETER;
275
276 DPRINT1("ConDrvSetConsolePalette checkpt 1\n");
277
278 // FIXME: Is it useful ?
279 if ( PaletteUsage != SYSPAL_STATIC &&
280 PaletteUsage != SYSPAL_NOSTATIC &&
281 PaletteUsage != SYSPAL_NOSTATIC256 )
282 {
283 return STATUS_INVALID_PARAMETER;
284 }
285
286 DPRINT1("ConDrvSetConsolePalette checkpt 2\n");
287
288 /* Validity check */
289 ASSERT(Console == Buffer->Header.Console);
290
291
292
293 /******************************************************************************\
294 |************** HACK! HACK! HACK! HACK! HACK! HACK! HACK! HACK! ***************|
295 \******************************************************************************/
296
297 DPRINT1("HACK: FIXME: ConDrvSetConsolePalette - Use hacked palette for testing purposes!!\n");
298
299 LogPalette = (LPLOGPALETTE)ConsoleAllocHeap(HEAP_ZERO_MEMORY,
300 (sizeof(LOGPALETTE) +
301 (sizeof(PALETTEENTRY) * PALETTESIZE)));
302
303 if (LogPalette)
304 {
305 LogPalette->palVersion = 0x300;
306 LogPalette->palNumEntries = PALETTESIZE;
307
308 for(i=0; i < PALETTESIZE;i++)
309 {
310 LogPalette->palPalEntry[i] = MyPalette[i % sizeof(MyPalette)/sizeof(MyPalette[0])];
311 }
312
313 PaletteHandle = CreatePalette(LogPalette);
314 PaletteUsage = SYSPAL_NOSTATIC256;
315 ConsoleFreeHeap(LogPalette);
316 }
317 else
318 {
319 DPRINT1("ConDrvSetConsolePalette - Hacked LogPalette is NULL\n");
320 }
321
322 /******************************************************************************\
323 |************** HACK! HACK! HACK! HACK! HACK! HACK! HACK! HACK! ***************|
324 \******************************************************************************/
325
326
327
328
329 /* Change the palette */
330 DPRINT1("ConDrvSetConsolePalette calling TermSetPalette\n");
331 Success = TermSetPalette(Console, PaletteHandle, PaletteUsage);
332 if (Success)
333 {
334 DPRINT1("TermSetPalette succeeded\n");
335 /* Free the old palette handle if there was already one set */
336 if ( Buffer->PaletteHandle != NULL &&
337 Buffer->PaletteHandle != PaletteHandle )
338 {
339 DeleteObject(Buffer->PaletteHandle);
340 }
341
342 /* Save the new palette in the screen buffer */
343 Buffer->PaletteHandle = PaletteHandle;
344 Buffer->PaletteUsage = PaletteUsage;
345 }
346 else
347 {
348 DPRINT1("TermSetPalette failed\n");
349 }
350
351 return (Success ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
352 }
353
354 NTSTATUS NTAPI
355 ConDrvGetConsoleCursorInfo(IN PCONSOLE Console,
356 IN PTEXTMODE_SCREEN_BUFFER Buffer,
357 OUT PCONSOLE_CURSOR_INFO CursorInfo)
358 {
359 if (Console == NULL || Buffer == NULL || CursorInfo == NULL)
360 return STATUS_INVALID_PARAMETER;
361
362 /* Validity check */
363 ASSERT(Console == Buffer->Header.Console);
364
365 *CursorInfo = Buffer->CursorInfo;
366 // CursorInfo->bVisible = Buffer->CursorInfo.bVisible;
367 // CursorInfo->dwSize = Buffer->CursorInfo.dwSize;
368
369 return STATUS_SUCCESS;
370 }
371
372 NTSTATUS NTAPI
373 ConDrvSetConsoleCursorInfo(IN PCONSOLE Console,
374 IN PTEXTMODE_SCREEN_BUFFER Buffer,
375 IN PCONSOLE_CURSOR_INFO CursorInfo)
376 {
377 ULONG Size;
378 BOOLEAN Visible, Success = TRUE;
379
380 if (Console == NULL || Buffer == NULL || CursorInfo == NULL)
381 return STATUS_INVALID_PARAMETER;
382
383 /* Validity check */
384 ASSERT(Console == Buffer->Header.Console);
385
386 Size = min(max(CursorInfo->dwSize, 1), 100);
387 Visible = CursorInfo->bVisible;
388
389 if ( (Size != Buffer->CursorInfo.dwSize) ||
390 (Visible && !Buffer->CursorInfo.bVisible) ||
391 (!Visible && Buffer->CursorInfo.bVisible) )
392 {
393 Buffer->CursorInfo.dwSize = Size;
394 Buffer->CursorInfo.bVisible = Visible;
395
396 Success = TermSetCursorInfo(Console, (PCONSOLE_SCREEN_BUFFER)Buffer);
397 }
398
399 return (Success ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
400 }
401
402 NTSTATUS NTAPI
403 ConDrvSetConsoleCursorPosition(IN PCONSOLE Console,
404 IN PTEXTMODE_SCREEN_BUFFER Buffer,
405 IN PCOORD Position)
406 {
407 SHORT OldCursorX, OldCursorY;
408
409 if (Console == NULL || Buffer == NULL || Position == NULL)
410 return STATUS_INVALID_PARAMETER;
411
412 /* Validity check */
413 ASSERT(Console == Buffer->Header.Console);
414
415 if ( Position->X < 0 || Position->X >= Buffer->ScreenBufferSize.X ||
416 Position->Y < 0 || Position->Y >= Buffer->ScreenBufferSize.Y )
417 {
418 return STATUS_INVALID_PARAMETER;
419 }
420
421 OldCursorX = Buffer->CursorPosition.X;
422 OldCursorY = Buffer->CursorPosition.Y;
423 Buffer->CursorPosition = *Position;
424 // Buffer->CursorPosition.X = Position->X;
425 // Buffer->CursorPosition.Y = Position->Y;
426 if ( ((PCONSOLE_SCREEN_BUFFER)Buffer == Console->ActiveBuffer) &&
427 (!TermSetScreenInfo(Console, (PCONSOLE_SCREEN_BUFFER)Buffer, OldCursorX, OldCursorY)) )
428 {
429 return STATUS_UNSUCCESSFUL;
430 }
431
432 return STATUS_SUCCESS;
433 }
434
435 /* EOF */