[CONSRV-WINSRV]
[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/conio2.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 TEXTMODE_BUFFER_Destroy(Buffer);
62 else if (Buffer->Header.Type == GRAPHICS_BUFFER)
63 GRAPHICS_BUFFER_Destroy(Buffer);
64 else if (Buffer->Header.Type == SCREEN_BUFFER)
65 ConsoleFreeHeap(Buffer);
66 // else
67 // do_nothing;
68 }
69
70 // ConDrvCreateConsoleScreenBuffer
71 NTSTATUS FASTCALL
72 ConDrvCreateScreenBuffer(OUT PCONSOLE_SCREEN_BUFFER* Buffer,
73 IN OUT PCONSOLE Console,
74 IN ULONG BufferType,
75 IN PVOID ScreenBufferInfo)
76 {
77 NTSTATUS Status = STATUS_SUCCESS;
78
79 if ( Console == NULL || Buffer == NULL ||
80 (BufferType != CONSOLE_TEXTMODE_BUFFER && BufferType != CONSOLE_GRAPHICS_BUFFER) )
81 {
82 return STATUS_INVALID_PARAMETER;
83 }
84
85 if (BufferType == CONSOLE_TEXTMODE_BUFFER)
86 {
87 Status = TEXTMODE_BUFFER_Initialize(Buffer,
88 Console,
89 (PTEXTMODE_BUFFER_INFO)ScreenBufferInfo);
90 }
91 else if (BufferType == CONSOLE_GRAPHICS_BUFFER)
92 {
93 Status = GRAPHICS_BUFFER_Initialize(Buffer,
94 Console,
95 (PGRAPHICS_BUFFER_INFO)ScreenBufferInfo);
96 }
97 else
98 {
99 /* Never ever go there!! */
100 ASSERT(FALSE);
101 }
102
103 /* Insert the newly created screen buffer into the list, if succeeded */
104 if (NT_SUCCESS(Status)) InsertHeadList(&Console->BufferList, &(*Buffer)->ListEntry);
105
106 return Status;
107 }
108
109 static VOID
110 ConioSetActiveScreenBuffer(PCONSOLE_SCREEN_BUFFER Buffer);
111
112 VOID WINAPI
113 ConioDeleteScreenBuffer(PCONSOLE_SCREEN_BUFFER Buffer)
114 {
115 PCONSOLE Console = Buffer->Header.Console;
116 PCONSOLE_SCREEN_BUFFER NewBuffer;
117
118 RemoveEntryList(&Buffer->ListEntry);
119 if (Buffer == Console->ActiveBuffer)
120 {
121 /* Delete active buffer; switch to most recently created */
122 Console->ActiveBuffer = NULL;
123 if (!IsListEmpty(&Console->BufferList))
124 {
125 NewBuffer = CONTAINING_RECORD(Console->BufferList.Flink,
126 CONSOLE_SCREEN_BUFFER,
127 ListEntry);
128 ConioSetActiveScreenBuffer(NewBuffer);
129 }
130 }
131
132 CONSOLE_SCREEN_BUFFER_Destroy(Buffer);
133 }
134
135 VOID FASTCALL
136 ConioDrawConsole(PCONSOLE Console)
137 {
138 SMALL_RECT Region;
139 PCONSOLE_SCREEN_BUFFER ActiveBuffer = Console->ActiveBuffer;
140
141 if (ActiveBuffer)
142 {
143 ConioInitRect(&Region, 0, 0, ActiveBuffer->ViewSize.Y - 1, ActiveBuffer->ViewSize.X - 1);
144 ConioDrawRegion(Console, &Region);
145 }
146 }
147
148 static VOID
149 ConioSetActiveScreenBuffer(PCONSOLE_SCREEN_BUFFER Buffer)
150 {
151 PCONSOLE Console = Buffer->Header.Console;
152 Console->ActiveBuffer = Buffer;
153 ConioResizeTerminal(Console);
154 // ConioDrawConsole(Console);
155 }
156
157 NTSTATUS NTAPI
158 ConDrvSetConsoleActiveScreenBuffer(IN PCONSOLE Console,
159 IN PCONSOLE_SCREEN_BUFFER Buffer)
160 {
161 if (Console == NULL || Buffer == NULL)
162 return STATUS_INVALID_PARAMETER;
163
164 /* Validity check */
165 ASSERT(Console == Buffer->Header.Console);
166
167 if (Buffer == Console->ActiveBuffer) return STATUS_SUCCESS;
168
169 /* If old buffer has no handles, it's now unreferenced */
170 if (Console->ActiveBuffer->Header.HandleCount == 0)
171 {
172 ConioDeleteScreenBuffer(Console->ActiveBuffer);
173 }
174
175 /* Tie console to new buffer */
176 ConioSetActiveScreenBuffer(Buffer);
177
178 return STATUS_SUCCESS;
179 }
180
181 PCONSOLE_SCREEN_BUFFER
182 ConDrvGetActiveScreenBuffer(IN PCONSOLE Console)
183 {
184 return (Console ? Console->ActiveBuffer : NULL);
185 }
186
187 /* PUBLIC DRIVER APIS *********************************************************/
188
189 NTSTATUS NTAPI
190 ConDrvInvalidateBitMapRect(IN PCONSOLE Console,
191 IN PCONSOLE_SCREEN_BUFFER Buffer,
192 IN PSMALL_RECT Region)
193 {
194 if (Console == NULL || Buffer == NULL || Region == NULL)
195 return STATUS_INVALID_PARAMETER;
196
197 /* Validity check */
198 ASSERT(Console == Buffer->Header.Console);
199
200 /* If the output buffer is the current one, redraw the correct portion of the screen */
201 if (Buffer == Console->ActiveBuffer) ConioDrawRegion(Console, Region);
202
203 return STATUS_SUCCESS;
204 }
205
206 NTSTATUS NTAPI
207 ConDrvGetConsoleCursorInfo(IN PCONSOLE Console,
208 IN PTEXTMODE_SCREEN_BUFFER Buffer,
209 OUT PCONSOLE_CURSOR_INFO CursorInfo)
210 {
211 if (Console == NULL || Buffer == NULL || CursorInfo == NULL)
212 return STATUS_INVALID_PARAMETER;
213
214 /* Validity check */
215 ASSERT(Console == Buffer->Header.Console);
216
217 *CursorInfo = Buffer->CursorInfo;
218 // CursorInfo->bVisible = Buffer->CursorInfo.bVisible;
219 // CursorInfo->dwSize = Buffer->CursorInfo.dwSize;
220
221 return STATUS_SUCCESS;
222 }
223
224 NTSTATUS NTAPI
225 ConDrvSetConsoleCursorInfo(IN PCONSOLE Console,
226 IN PTEXTMODE_SCREEN_BUFFER Buffer,
227 IN PCONSOLE_CURSOR_INFO CursorInfo)
228 {
229 ULONG Size;
230 BOOLEAN Visible, Success = TRUE;
231
232 if (Console == NULL || Buffer == NULL || CursorInfo == NULL)
233 return STATUS_INVALID_PARAMETER;
234
235 /* Validity check */
236 ASSERT(Console == Buffer->Header.Console);
237
238 Size = min(max(CursorInfo->dwSize, 1), 100);
239 Visible = CursorInfo->bVisible;
240
241 if ( (Size != Buffer->CursorInfo.dwSize) ||
242 (Visible && !Buffer->CursorInfo.bVisible) ||
243 (!Visible && Buffer->CursorInfo.bVisible) )
244 {
245 Buffer->CursorInfo.dwSize = Size;
246 Buffer->CursorInfo.bVisible = Visible;
247
248 Success = ConioSetCursorInfo(Console, (PCONSOLE_SCREEN_BUFFER)Buffer);
249 }
250
251 return (Success ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
252 }
253
254 NTSTATUS NTAPI
255 ConDrvSetConsoleCursorPosition(IN PCONSOLE Console,
256 IN PTEXTMODE_SCREEN_BUFFER Buffer,
257 IN PCOORD Position)
258 {
259 SHORT OldCursorX, OldCursorY;
260
261 if (Console == NULL || Buffer == NULL || Position == NULL)
262 return STATUS_INVALID_PARAMETER;
263
264 /* Validity check */
265 ASSERT(Console == Buffer->Header.Console);
266
267 if ( Position->X < 0 || Position->X >= Buffer->ScreenBufferSize.X ||
268 Position->Y < 0 || Position->Y >= Buffer->ScreenBufferSize.Y )
269 {
270 return STATUS_INVALID_PARAMETER;
271 }
272
273 OldCursorX = Buffer->CursorPosition.X;
274 OldCursorY = Buffer->CursorPosition.Y;
275 Buffer->CursorPosition = *Position;
276 // Buffer->CursorPosition.X = Position->X;
277 // Buffer->CursorPosition.Y = Position->Y;
278 if ( ((PCONSOLE_SCREEN_BUFFER)Buffer == Console->ActiveBuffer) &&
279 (!ConioSetScreenInfo(Console, (PCONSOLE_SCREEN_BUFFER)Buffer, OldCursorX, OldCursorY)) )
280 {
281 return STATUS_UNSUCCESSFUL;
282 }
283
284 return STATUS_SUCCESS;
285 }
286
287 /* EOF */