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 *******************************************************************/
17 /* PRIVATE FUNCTIONS **********************************************************/
20 TEXTMODE_BUFFER_Initialize(OUT PCONSOLE_SCREEN_BUFFER
* Buffer
,
21 IN OUT PCONSOLE Console
,
22 IN PTEXTMODE_BUFFER_INFO TextModeInfo
);
24 GRAPHICS_BUFFER_Initialize(OUT PCONSOLE_SCREEN_BUFFER
* Buffer
,
25 IN OUT PCONSOLE Console
,
26 IN PGRAPHICS_BUFFER_INFO GraphicsInfo
);
29 TEXTMODE_BUFFER_Destroy(IN OUT PCONSOLE_SCREEN_BUFFER Buffer
);
31 GRAPHICS_BUFFER_Destroy(IN OUT PCONSOLE_SCREEN_BUFFER Buffer
);
35 CONSOLE_SCREEN_BUFFER_Initialize(OUT PCONSOLE_SCREEN_BUFFER
* Buffer
,
36 IN OUT PCONSOLE Console
,
37 IN PCONSOLE_SCREEN_BUFFER_VTBL Vtbl
,
40 if (Buffer
== NULL
|| Console
== NULL
)
41 return STATUS_INVALID_PARAMETER
;
43 *Buffer
= ConsoleAllocHeap(HEAP_ZERO_MEMORY
, max(sizeof(CONSOLE_SCREEN_BUFFER
), Size
));
44 if (*Buffer
== NULL
) return STATUS_INSUFFICIENT_RESOURCES
;
46 /* Initialize the header with the default type */
47 ConSrvInitObject(&(*Buffer
)->Header
, SCREEN_BUFFER
, Console
);
48 (*Buffer
)->Vtbl
= Vtbl
;
49 return STATUS_SUCCESS
;
53 CONSOLE_SCREEN_BUFFER_Destroy(IN OUT PCONSOLE_SCREEN_BUFFER Buffer
)
55 if (Buffer
->Header
.Type
== TEXTMODE_BUFFER
)
57 TEXTMODE_BUFFER_Destroy(Buffer
);
59 else if (Buffer
->Header
.Type
== GRAPHICS_BUFFER
)
61 GRAPHICS_BUFFER_Destroy(Buffer
);
63 else if (Buffer
->Header
.Type
== SCREEN_BUFFER
)
65 // TODO: Free Buffer->Data
67 /* Free the palette handle */
68 if (Buffer
->PaletteHandle
!= NULL
) DeleteObject(Buffer
->PaletteHandle
);
70 /* Free the screen buffer memory */
71 ConsoleFreeHeap(Buffer
);
77 // ConDrvCreateConsoleScreenBuffer
79 ConDrvCreateScreenBuffer(OUT PCONSOLE_SCREEN_BUFFER
* Buffer
,
80 IN OUT PCONSOLE Console
,
82 IN PVOID ScreenBufferInfo
)
84 NTSTATUS Status
= STATUS_SUCCESS
;
86 if ( Console
== NULL
|| Buffer
== NULL
||
87 (BufferType
!= CONSOLE_TEXTMODE_BUFFER
&& BufferType
!= CONSOLE_GRAPHICS_BUFFER
) )
89 return STATUS_INVALID_PARAMETER
;
92 if (BufferType
== CONSOLE_TEXTMODE_BUFFER
)
94 Status
= TEXTMODE_BUFFER_Initialize(Buffer
, Console
,
95 (PTEXTMODE_BUFFER_INFO
)ScreenBufferInfo
);
97 else if (BufferType
== CONSOLE_GRAPHICS_BUFFER
)
99 Status
= GRAPHICS_BUFFER_Initialize(Buffer
, Console
,
100 (PGRAPHICS_BUFFER_INFO
)ScreenBufferInfo
);
104 /* Never ever go there!! */
108 /* Insert the newly created screen buffer into the list, if succeeded */
109 if (NT_SUCCESS(Status
)) InsertHeadList(&Console
->BufferList
, &(*Buffer
)->ListEntry
);
115 ConioSetActiveScreenBuffer(PCONSOLE_SCREEN_BUFFER Buffer
);
118 ConioDeleteScreenBuffer(PCONSOLE_SCREEN_BUFFER Buffer
)
120 PCONSOLE Console
= Buffer
->Header
.Console
;
121 PCONSOLE_SCREEN_BUFFER NewBuffer
;
124 * We should notify temporarily the frontend because we are susceptible
125 * to delete the screen buffer it is using (which may be different from
126 * the active screen buffer in some cases), and because, if it actually
127 * uses the active screen buffer, we are going to nullify its pointer to
130 TermReleaseScreenBuffer(Console
, Buffer
);
132 RemoveEntryList(&Buffer
->ListEntry
);
133 if (Buffer
== Console
->ActiveBuffer
)
135 /* Delete active buffer; switch to most recently created */
136 if (!IsListEmpty(&Console
->BufferList
))
138 NewBuffer
= CONTAINING_RECORD(Console
->BufferList
.Flink
,
139 CONSOLE_SCREEN_BUFFER
,
142 /* Tie console to new buffer and signal the change to the frontend */
143 ConioSetActiveScreenBuffer(NewBuffer
);
147 Console
->ActiveBuffer
= NULL
;
148 // InterlockedExchangePointer(&Console->ActiveBuffer, NULL);
152 CONSOLE_SCREEN_BUFFER_Destroy(Buffer
);
156 ConioDrawConsole(PCONSOLE Console
)
159 PCONSOLE_SCREEN_BUFFER ActiveBuffer
= Console
->ActiveBuffer
;
163 ConioInitRect(&Region
, 0, 0,
164 ActiveBuffer
->ViewSize
.Y
- 1, ActiveBuffer
->ViewSize
.X
- 1);
165 TermDrawRegion(Console
, &Region
);
170 ConioSetActiveScreenBuffer(PCONSOLE_SCREEN_BUFFER Buffer
)
172 PCONSOLE Console
= Buffer
->Header
.Console
;
173 Console
->ActiveBuffer
= Buffer
;
174 // InterlockedExchangePointer(&Console->ActiveBuffer, Buffer);
175 TermSetActiveScreenBuffer(Console
);
179 ConDrvSetConsoleActiveScreenBuffer(IN PCONSOLE Console
,
180 IN PCONSOLE_SCREEN_BUFFER Buffer
)
182 if (Console
== NULL
|| Buffer
== NULL
)
183 return STATUS_INVALID_PARAMETER
;
186 ASSERT(Console
== Buffer
->Header
.Console
);
188 if (Buffer
== Console
->ActiveBuffer
) return STATUS_SUCCESS
;
190 /* If old buffer has no handles, it's now unreferenced */
191 if (Console
->ActiveBuffer
->Header
.ReferenceCount
== 0)
193 ConioDeleteScreenBuffer(Console
->ActiveBuffer
);
196 /* Tie console to new buffer and signal the change to the frontend */
197 ConioSetActiveScreenBuffer(Buffer
);
199 return STATUS_SUCCESS
;
202 PCONSOLE_SCREEN_BUFFER
203 ConDrvGetActiveScreenBuffer(IN PCONSOLE Console
)
205 return (Console
? Console
->ActiveBuffer
: NULL
);
208 /* PUBLIC DRIVER APIS *********************************************************/
211 ConDrvWriteConsoleOutputVDM(IN PCONSOLE Console
,
212 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
213 IN PCHAR_CELL CharInfo
/*Buffer*/,
214 IN COORD CharInfoSize
,
215 IN OUT PSMALL_RECT WriteRegion
,
216 IN BOOLEAN DrawRegion
);
218 ConDrvInvalidateBitMapRect(IN PCONSOLE Console
,
219 IN PCONSOLE_SCREEN_BUFFER Buffer
,
220 IN PSMALL_RECT Region
)
222 if (Console
== NULL
|| Buffer
== NULL
|| Region
== NULL
)
223 return STATUS_INVALID_PARAMETER
;
226 ASSERT(Console
== Buffer
->Header
.Console
);
228 /* In text-mode only, draw the VDM buffer if present */
229 if (GetType(Buffer
) == TEXTMODE_BUFFER
)
231 PTEXTMODE_SCREEN_BUFFER TextBuffer
= (PTEXTMODE_SCREEN_BUFFER
)Buffer
;
233 /*Status =*/ ConDrvWriteConsoleOutputVDM(Buffer
->Header
.Console
,
236 Console
->VDMBufferSize
,
241 /* If the output buffer is the current one, redraw the correct portion of the screen */
242 if (Buffer
== Console
->ActiveBuffer
) TermDrawRegion(Console
, Region
);
244 return STATUS_SUCCESS
;
248 ConDrvSetConsolePalette(IN PCONSOLE Console
,
249 // IN PGRAPHICS_SCREEN_BUFFER Buffer,
250 IN PCONSOLE_SCREEN_BUFFER Buffer
,
251 IN HPALETTE PaletteHandle
,
252 IN UINT PaletteUsage
)
257 * Parameters validation
259 if (Console
== NULL
|| Buffer
== NULL
)
260 return STATUS_INVALID_PARAMETER
;
262 if ( PaletteUsage
!= SYSPAL_STATIC
&&
263 PaletteUsage
!= SYSPAL_NOSTATIC
&&
264 PaletteUsage
!= SYSPAL_NOSTATIC256
)
266 return STATUS_INVALID_PARAMETER
;
270 ASSERT(Console
== Buffer
->Header
.Console
);
272 /* Change the palette */
273 Success
= TermSetPalette(Console
, PaletteHandle
, PaletteUsage
);
276 /* Free the old palette handle if there was already one set */
277 if ( Buffer
->PaletteHandle
!= NULL
&&
278 Buffer
->PaletteHandle
!= PaletteHandle
)
280 DeleteObject(Buffer
->PaletteHandle
);
283 /* Save the new palette in the screen buffer */
284 Buffer
->PaletteHandle
= PaletteHandle
;
285 Buffer
->PaletteUsage
= PaletteUsage
;
288 return (Success
? STATUS_SUCCESS
: STATUS_UNSUCCESSFUL
);
292 ConDrvGetConsoleCursorInfo(IN PCONSOLE Console
,
293 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
294 OUT PCONSOLE_CURSOR_INFO CursorInfo
)
296 if (Console
== NULL
|| Buffer
== NULL
|| CursorInfo
== NULL
)
297 return STATUS_INVALID_PARAMETER
;
300 ASSERT(Console
== Buffer
->Header
.Console
);
302 *CursorInfo
= Buffer
->CursorInfo
;
303 // CursorInfo->bVisible = Buffer->CursorInfo.bVisible;
304 // CursorInfo->dwSize = Buffer->CursorInfo.dwSize;
306 return STATUS_SUCCESS
;
310 ConDrvSetConsoleCursorInfo(IN PCONSOLE Console
,
311 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
312 IN PCONSOLE_CURSOR_INFO CursorInfo
)
315 BOOLEAN Visible
, Success
= TRUE
;
317 if (Console
== NULL
|| Buffer
== NULL
|| CursorInfo
== NULL
)
318 return STATUS_INVALID_PARAMETER
;
321 ASSERT(Console
== Buffer
->Header
.Console
);
323 Size
= min(max(CursorInfo
->dwSize
, 1), 100);
324 Visible
= CursorInfo
->bVisible
;
326 if ( (Size
!= Buffer
->CursorInfo
.dwSize
) ||
327 (Visible
&& !Buffer
->CursorInfo
.bVisible
) ||
328 (!Visible
&& Buffer
->CursorInfo
.bVisible
) )
330 Buffer
->CursorInfo
.dwSize
= Size
;
331 Buffer
->CursorInfo
.bVisible
= Visible
;
333 Success
= TermSetCursorInfo(Console
, (PCONSOLE_SCREEN_BUFFER
)Buffer
);
336 return (Success
? STATUS_SUCCESS
: STATUS_UNSUCCESSFUL
);
340 ConDrvSetConsoleCursorPosition(IN PCONSOLE Console
,
341 IN PTEXTMODE_SCREEN_BUFFER Buffer
,
344 SHORT OldCursorX
, OldCursorY
;
346 if (Console
== NULL
|| Buffer
== NULL
|| Position
== NULL
)
347 return STATUS_INVALID_PARAMETER
;
350 ASSERT(Console
== Buffer
->Header
.Console
);
352 if ( Position
->X
< 0 || Position
->X
>= Buffer
->ScreenBufferSize
.X
||
353 Position
->Y
< 0 || Position
->Y
>= Buffer
->ScreenBufferSize
.Y
)
355 return STATUS_INVALID_PARAMETER
;
358 OldCursorX
= Buffer
->CursorPosition
.X
;
359 OldCursorY
= Buffer
->CursorPosition
.Y
;
360 Buffer
->CursorPosition
= *Position
;
361 // Buffer->CursorPosition.X = Position->X;
362 // Buffer->CursorPosition.Y = Position->Y;
363 if ( ((PCONSOLE_SCREEN_BUFFER
)Buffer
== Console
->ActiveBuffer
) &&
364 (!TermSetScreenInfo(Console
, (PCONSOLE_SCREEN_BUFFER
)Buffer
, OldCursorX
, OldCursorY
)) )
366 return STATUS_UNSUCCESSFUL
;
369 return STATUS_SUCCESS
;