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)
10 /* INCLUDES *******************************************************************/
14 #include "include/conio.h"
15 #include "include/term.h"
16 #include "conoutput.h"
23 /* PRIVATE FUNCTIONS **********************************************************/
26 TEXTMODE_BUFFER_Initialize(OUT PCONSOLE_SCREEN_BUFFER
* Buffer
,
27 IN OUT PCONSOLE Console
,
28 IN PTEXTMODE_BUFFER_INFO TextModeInfo
);
30 GRAPHICS_BUFFER_Initialize(OUT PCONSOLE_SCREEN_BUFFER
* Buffer
,
31 IN OUT PCONSOLE Console
,
32 IN PGRAPHICS_BUFFER_INFO GraphicsInfo
);
35 TEXTMODE_BUFFER_Destroy(IN OUT PCONSOLE_SCREEN_BUFFER Buffer
);
37 GRAPHICS_BUFFER_Destroy(IN OUT PCONSOLE_SCREEN_BUFFER Buffer
);
41 CONSOLE_SCREEN_BUFFER_Initialize(OUT PCONSOLE_SCREEN_BUFFER
* Buffer
,
42 IN OUT PCONSOLE Console
,
45 if (Buffer
== NULL
|| Console
== NULL
)
46 return STATUS_INVALID_PARAMETER
;
48 *Buffer
= ConsoleAllocHeap(HEAP_ZERO_MEMORY
, max(sizeof(CONSOLE_SCREEN_BUFFER
), Size
));
49 if (*Buffer
== NULL
) return STATUS_INSUFFICIENT_RESOURCES
;
51 /* Initialize the header with the default type */
52 ConSrvInitObject(&(*Buffer
)->Header
, SCREEN_BUFFER
, Console
);
53 (*Buffer
)->Vtbl
= NULL
;
54 return STATUS_SUCCESS
;
58 CONSOLE_SCREEN_BUFFER_Destroy(IN OUT PCONSOLE_SCREEN_BUFFER Buffer
)
60 if (Buffer
->Header
.Type
== TEXTMODE_BUFFER
)
62 TEXTMODE_BUFFER_Destroy(Buffer
);
64 else if (Buffer
->Header
.Type
== GRAPHICS_BUFFER
)
66 GRAPHICS_BUFFER_Destroy(Buffer
);
68 else if (Buffer
->Header
.Type
== SCREEN_BUFFER
)
70 // TODO: Free Buffer->Data
72 /* Free the palette handle */
73 if (Buffer
->PaletteHandle
!= NULL
) DeleteObject(Buffer
->PaletteHandle
);
75 /* Free the screen buffer memory */
76 ConsoleFreeHeap(Buffer
);
82 // ConDrvCreateConsoleScreenBuffer
84 ConDrvCreateScreenBuffer(OUT PCONSOLE_SCREEN_BUFFER
* Buffer
,
85 IN OUT PCONSOLE Console
,
87 IN PVOID ScreenBufferInfo
)
89 NTSTATUS Status
= STATUS_SUCCESS
;
91 if ( Console
== NULL
|| Buffer
== NULL
||
92 (BufferType
!= CONSOLE_TEXTMODE_BUFFER
&& BufferType
!= CONSOLE_GRAPHICS_BUFFER
) )
94 return STATUS_INVALID_PARAMETER
;
97 if (BufferType
== CONSOLE_TEXTMODE_BUFFER
)
99 Status
= TEXTMODE_BUFFER_Initialize(Buffer
, Console
,
100 (PTEXTMODE_BUFFER_INFO
)ScreenBufferInfo
);
102 else if (BufferType
== CONSOLE_GRAPHICS_BUFFER
)
104 Status
= GRAPHICS_BUFFER_Initialize(Buffer
, Console
,
105 (PGRAPHICS_BUFFER_INFO
)ScreenBufferInfo
);
109 /* Never ever go there!! */
113 /* Insert the newly created screen buffer into the list, if succeeded */
114 if (NT_SUCCESS(Status
)) InsertHeadList(&Console
->BufferList
, &(*Buffer
)->ListEntry
);
120 ConioSetActiveScreenBuffer(PCONSOLE_SCREEN_BUFFER Buffer
);
123 ConioDeleteScreenBuffer(PCONSOLE_SCREEN_BUFFER Buffer
)
125 PCONSOLE Console
= Buffer
->Header
.Console
;
126 PCONSOLE_SCREEN_BUFFER NewBuffer
;
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
135 TermReleaseScreenBuffer(Console
, Buffer
);
137 RemoveEntryList(&Buffer
->ListEntry
);
138 if (Buffer
== Console
->ActiveBuffer
)
140 /* Delete active buffer; switch to most recently created */
141 if (!IsListEmpty(&Console
->BufferList
))
143 NewBuffer
= CONTAINING_RECORD(Console
->BufferList
.Flink
,
144 CONSOLE_SCREEN_BUFFER
,
147 /* Tie console to new buffer and signal the change to the frontend */
148 ConioSetActiveScreenBuffer(NewBuffer
);
152 Console
->ActiveBuffer
= NULL
;
153 // InterlockedExchangePointer(&Console->ActiveBuffer, NULL);
157 CONSOLE_SCREEN_BUFFER_Destroy(Buffer
);
161 ConioDrawConsole(PCONSOLE Console
)
164 PCONSOLE_SCREEN_BUFFER ActiveBuffer
= Console
->ActiveBuffer
;
168 ConioInitRect(&Region
, 0, 0, ActiveBuffer
->ViewSize
.Y
- 1, ActiveBuffer
->ViewSize
.X
- 1);
169 TermDrawRegion(Console
, &Region
);
174 ConioSetActiveScreenBuffer(PCONSOLE_SCREEN_BUFFER Buffer
)
176 PCONSOLE Console
= Buffer
->Header
.Console
;
177 Console
->ActiveBuffer
= Buffer
;
178 // InterlockedExchangePointer(&Console->ActiveBuffer, Buffer);
179 TermSetActiveScreenBuffer(Console
);
183 ConDrvSetConsoleActiveScreenBuffer(IN PCONSOLE Console
,
184 IN PCONSOLE_SCREEN_BUFFER Buffer
)
186 if (Console
== NULL
|| Buffer
== NULL
)
187 return STATUS_INVALID_PARAMETER
;
190 ASSERT(Console
== Buffer
->Header
.Console
);
192 if (Buffer
== Console
->ActiveBuffer
) return STATUS_SUCCESS
;
194 /* If old buffer has no handles, it's now unreferenced */
195 if (Console
->ActiveBuffer
->Header
.HandleCount
== 0)
197 ConioDeleteScreenBuffer(Console
->ActiveBuffer
);
200 /* Tie console to new buffer and signal the change to the frontend */
201 ConioSetActiveScreenBuffer(Buffer
);
203 return STATUS_SUCCESS
;
206 PCONSOLE_SCREEN_BUFFER
207 ConDrvGetActiveScreenBuffer(IN PCONSOLE Console
)
209 return (Console
? Console
->ActiveBuffer
: NULL
);
212 /* PUBLIC DRIVER APIS *********************************************************/
215 ConDrvInvalidateBitMapRect(IN PCONSOLE Console
,
216 IN PCONSOLE_SCREEN_BUFFER Buffer
,
217 IN PSMALL_RECT Region
)
219 if (Console
== NULL
|| Buffer
== NULL
|| Region
== NULL
)
220 return STATUS_INVALID_PARAMETER
;
223 ASSERT(Console
== Buffer
->Header
.Console
);
225 /* If the output buffer is the current one, redraw the correct portion of the screen */
226 if (Buffer
== Console
->ActiveBuffer
) TermDrawRegion(Console
, Region
);
228 return STATUS_SUCCESS
;
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
)
241 * Parameters validation
243 if (Console
== NULL
|| Buffer
== NULL
)
244 return STATUS_INVALID_PARAMETER
;
246 if ( PaletteUsage
!= SYSPAL_STATIC
&&
247 PaletteUsage
!= SYSPAL_NOSTATIC
&&
248 PaletteUsage
!= SYSPAL_NOSTATIC256
)
250 return STATUS_INVALID_PARAMETER
;
254 ASSERT(Console
== Buffer
->Header
.Console
);
256 /* Change the palette */
257 Success
= TermSetPalette(Console
, PaletteHandle
, PaletteUsage
);
260 /* Free the old palette handle if there was already one set */
261 if ( Buffer
->PaletteHandle
!= NULL
&&
262 Buffer
->PaletteHandle
!= PaletteHandle
)
264 DeleteObject(Buffer
->PaletteHandle
);
267 /* Save the new palette in the screen buffer */
268 Buffer
->PaletteHandle
= PaletteHandle
;
269 Buffer
->PaletteUsage
= PaletteUsage
;
272 return (Success
? STATUS_SUCCESS
: STATUS_UNSUCCESSFUL
);
276 ConDrvGetConsoleCursorInfo(IN PCONSOLE Console
,
277 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
278 OUT PCONSOLE_CURSOR_INFO CursorInfo
)
280 if (Console
== NULL
|| Buffer
== NULL
|| CursorInfo
== NULL
)
281 return STATUS_INVALID_PARAMETER
;
284 ASSERT(Console
== Buffer
->Header
.Console
);
286 *CursorInfo
= Buffer
->CursorInfo
;
287 // CursorInfo->bVisible = Buffer->CursorInfo.bVisible;
288 // CursorInfo->dwSize = Buffer->CursorInfo.dwSize;
290 return STATUS_SUCCESS
;
294 ConDrvSetConsoleCursorInfo(IN PCONSOLE Console
,
295 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
296 IN PCONSOLE_CURSOR_INFO CursorInfo
)
299 BOOLEAN Visible
, Success
= TRUE
;
301 if (Console
== NULL
|| Buffer
== NULL
|| CursorInfo
== NULL
)
302 return STATUS_INVALID_PARAMETER
;
305 ASSERT(Console
== Buffer
->Header
.Console
);
307 Size
= min(max(CursorInfo
->dwSize
, 1), 100);
308 Visible
= CursorInfo
->bVisible
;
310 if ( (Size
!= Buffer
->CursorInfo
.dwSize
) ||
311 (Visible
&& !Buffer
->CursorInfo
.bVisible
) ||
312 (!Visible
&& Buffer
->CursorInfo
.bVisible
) )
314 Buffer
->CursorInfo
.dwSize
= Size
;
315 Buffer
->CursorInfo
.bVisible
= Visible
;
317 Success
= TermSetCursorInfo(Console
, (PCONSOLE_SCREEN_BUFFER
)Buffer
);
320 return (Success
? STATUS_SUCCESS
: STATUS_UNSUCCESSFUL
);
324 ConDrvSetConsoleCursorPosition(IN PCONSOLE Console
,
325 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
328 SHORT OldCursorX
, OldCursorY
;
330 if (Console
== NULL
|| Buffer
== NULL
|| Position
== NULL
)
331 return STATUS_INVALID_PARAMETER
;
334 ASSERT(Console
== Buffer
->Header
.Console
);
336 if ( Position
->X
< 0 || Position
->X
>= Buffer
->ScreenBufferSize
.X
||
337 Position
->Y
< 0 || Position
->Y
>= Buffer
->ScreenBufferSize
.Y
)
339 return STATUS_INVALID_PARAMETER
;
342 OldCursorX
= Buffer
->CursorPosition
.X
;
343 OldCursorY
= Buffer
->CursorPosition
.Y
;
344 Buffer
->CursorPosition
= *Position
;
345 // Buffer->CursorPosition.X = Position->X;
346 // Buffer->CursorPosition.Y = Position->Y;
347 if ( ((PCONSOLE_SCREEN_BUFFER
)Buffer
== Console
->ActiveBuffer
) &&
348 (!TermSetScreenInfo(Console
, (PCONSOLE_SCREEN_BUFFER
)Buffer
, OldCursorX
, OldCursorY
)) )
350 return STATUS_UNSUCCESSFUL
;
353 return STATUS_SUCCESS
;