[KERNEL32]
[reactos.git] / 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
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
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,
163 ActiveBuffer->ViewSize.Y - 1, ActiveBuffer->ViewSize.X - 1);
164 TermDrawRegion(Console, &Region);
165 }
166 }
167
168 static VOID
169 ConioSetActiveScreenBuffer(PCONSOLE_SCREEN_BUFFER Buffer)
170 {
171 PCONSOLE Console = Buffer->Header.Console;
172 Console->ActiveBuffer = Buffer;
173 // InterlockedExchangePointer(&Console->ActiveBuffer, Buffer);
174 TermSetActiveScreenBuffer(Console);
175 }
176
177 NTSTATUS NTAPI
178 ConDrvSetConsoleActiveScreenBuffer(IN PCONSOLE Console,
179 IN PCONSOLE_SCREEN_BUFFER Buffer)
180 {
181 if (Console == NULL || Buffer == NULL)
182 return STATUS_INVALID_PARAMETER;
183
184 /* Validity check */
185 ASSERT(Console == Buffer->Header.Console);
186
187 if (Buffer == Console->ActiveBuffer) return STATUS_SUCCESS;
188
189 /* If old buffer has no handles, it's now unreferenced */
190 if (Console->ActiveBuffer->Header.HandleCount == 0)
191 {
192 ConioDeleteScreenBuffer(Console->ActiveBuffer);
193 }
194
195 /* Tie console to new buffer and signal the change to the frontend */
196 ConioSetActiveScreenBuffer(Buffer);
197
198 return STATUS_SUCCESS;
199 }
200
201 PCONSOLE_SCREEN_BUFFER
202 ConDrvGetActiveScreenBuffer(IN PCONSOLE Console)
203 {
204 return (Console ? Console->ActiveBuffer : NULL);
205 }
206
207 /* PUBLIC DRIVER APIS *********************************************************/
208
209 NTSTATUS NTAPI
210 ConDrvInvalidateBitMapRect(IN PCONSOLE Console,
211 IN PCONSOLE_SCREEN_BUFFER Buffer,
212 IN PSMALL_RECT Region)
213 {
214 if (Console == NULL || Buffer == NULL || Region == NULL)
215 return STATUS_INVALID_PARAMETER;
216
217 /* Validity check */
218 ASSERT(Console == Buffer->Header.Console);
219
220 /* If the output buffer is the current one, redraw the correct portion of the screen */
221 if (Buffer == Console->ActiveBuffer) TermDrawRegion(Console, Region);
222
223 return STATUS_SUCCESS;
224 }
225
226 NTSTATUS NTAPI
227 ConDrvSetConsolePalette(IN PCONSOLE Console,
228 // IN PGRAPHICS_SCREEN_BUFFER Buffer,
229 IN PCONSOLE_SCREEN_BUFFER Buffer,
230 IN HPALETTE PaletteHandle,
231 IN UINT PaletteUsage)
232 {
233 BOOL Success;
234
235 /*
236 * Parameters validation
237 */
238 if (Console == NULL || Buffer == NULL)
239 return STATUS_INVALID_PARAMETER;
240
241 if ( PaletteUsage != SYSPAL_STATIC &&
242 PaletteUsage != SYSPAL_NOSTATIC &&
243 PaletteUsage != SYSPAL_NOSTATIC256 )
244 {
245 return STATUS_INVALID_PARAMETER;
246 }
247
248 /* Validity check */
249 ASSERT(Console == Buffer->Header.Console);
250
251 /* Change the palette */
252 Success = TermSetPalette(Console, PaletteHandle, PaletteUsage);
253 if (Success)
254 {
255 /* Free the old palette handle if there was already one set */
256 if ( Buffer->PaletteHandle != NULL &&
257 Buffer->PaletteHandle != PaletteHandle )
258 {
259 DeleteObject(Buffer->PaletteHandle);
260 }
261
262 /* Save the new palette in the screen buffer */
263 Buffer->PaletteHandle = PaletteHandle;
264 Buffer->PaletteUsage = PaletteUsage;
265 }
266
267 return (Success ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
268 }
269
270 NTSTATUS NTAPI
271 ConDrvGetConsoleCursorInfo(IN PCONSOLE Console,
272 IN PTEXTMODE_SCREEN_BUFFER Buffer,
273 OUT PCONSOLE_CURSOR_INFO CursorInfo)
274 {
275 if (Console == NULL || Buffer == NULL || CursorInfo == NULL)
276 return STATUS_INVALID_PARAMETER;
277
278 /* Validity check */
279 ASSERT(Console == Buffer->Header.Console);
280
281 *CursorInfo = Buffer->CursorInfo;
282 // CursorInfo->bVisible = Buffer->CursorInfo.bVisible;
283 // CursorInfo->dwSize = Buffer->CursorInfo.dwSize;
284
285 return STATUS_SUCCESS;
286 }
287
288 NTSTATUS NTAPI
289 ConDrvSetConsoleCursorInfo(IN PCONSOLE Console,
290 IN PTEXTMODE_SCREEN_BUFFER Buffer,
291 IN PCONSOLE_CURSOR_INFO CursorInfo)
292 {
293 ULONG Size;
294 BOOLEAN Visible, Success = TRUE;
295
296 if (Console == NULL || Buffer == NULL || CursorInfo == NULL)
297 return STATUS_INVALID_PARAMETER;
298
299 /* Validity check */
300 ASSERT(Console == Buffer->Header.Console);
301
302 Size = min(max(CursorInfo->dwSize, 1), 100);
303 Visible = CursorInfo->bVisible;
304
305 if ( (Size != Buffer->CursorInfo.dwSize) ||
306 (Visible && !Buffer->CursorInfo.bVisible) ||
307 (!Visible && Buffer->CursorInfo.bVisible) )
308 {
309 Buffer->CursorInfo.dwSize = Size;
310 Buffer->CursorInfo.bVisible = Visible;
311
312 Success = TermSetCursorInfo(Console, (PCONSOLE_SCREEN_BUFFER)Buffer);
313 }
314
315 return (Success ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
316 }
317
318 NTSTATUS NTAPI
319 ConDrvSetConsoleCursorPosition(IN PCONSOLE Console,
320 IN PTEXTMODE_SCREEN_BUFFER Buffer,
321 IN PCOORD Position)
322 {
323 SHORT OldCursorX, OldCursorY;
324
325 if (Console == NULL || Buffer == NULL || Position == NULL)
326 return STATUS_INVALID_PARAMETER;
327
328 /* Validity check */
329 ASSERT(Console == Buffer->Header.Console);
330
331 if ( Position->X < 0 || Position->X >= Buffer->ScreenBufferSize.X ||
332 Position->Y < 0 || Position->Y >= Buffer->ScreenBufferSize.Y )
333 {
334 return STATUS_INVALID_PARAMETER;
335 }
336
337 OldCursorX = Buffer->CursorPosition.X;
338 OldCursorY = Buffer->CursorPosition.Y;
339 Buffer->CursorPosition = *Position;
340 // Buffer->CursorPosition.X = Position->X;
341 // Buffer->CursorPosition.Y = Position->Y;
342 if ( ((PCONSOLE_SCREEN_BUFFER)Buffer == Console->ActiveBuffer) &&
343 (!TermSetScreenInfo(Console, (PCONSOLE_SCREEN_BUFFER)Buffer, OldCursorX, OldCursorY)) )
344 {
345 return STATUS_UNSUCCESSFUL;
346 }
347
348 return STATUS_SUCCESS;
349 }
350
351 /* EOF */