3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS system libraries
5 * FILE: subsys/csrss/win32csr/tuiconsole.c
6 * PURPOSE: Implementation of text-mode consoles
14 CRITICAL_SECTION ActiveConsoleLock
;
15 static COORD PhysicalConsoleSize
;
16 static HANDLE ConsoleDeviceHandle
;
17 static PCSRSS_CONSOLE ActiveConsole
;
19 static BOOL ConsInitialized
= FALSE
;
24 CONSOLE_SCREEN_BUFFER_INFO ScrInfo
;
27 ConsoleDeviceHandle
= CreateFileW(L
"\\\\.\\BlueScreen", FILE_ALL_ACCESS
, 0, NULL
,
28 OPEN_EXISTING
, 0, NULL
);
29 if (INVALID_HANDLE_VALUE
== ConsoleDeviceHandle
)
31 DPRINT1("Failed to open BlueScreen.\n");
36 InitializeCriticalSection(&ActiveConsoleLock
);
37 if (! DeviceIoControl(ConsoleDeviceHandle
, IOCTL_CONSOLE_GET_SCREEN_BUFFER_INFO
,
38 NULL
, 0, &ScrInfo
, sizeof(ScrInfo
), &BytesReturned
, NULL
))
40 DPRINT1("Failed to get console info\n");
43 PhysicalConsoleSize
= ScrInfo
.dwSize
;
49 TuiInitScreenBuffer(PCSRSS_CONSOLE Console
, PCSRSS_SCREEN_BUFFER Buffer
)
51 Buffer
->DefaultAttrib
= 0x17;
55 TuiCopyRect(char *Dest
, PCSRSS_SCREEN_BUFFER Buff
, RECT
*Region
)
57 UINT SrcDelta
, DestDelta
;
61 Src
= Buff
->Buffer
+ (((Region
->top
+ Buff
->ShowY
) % Buff
->MaxY
) * Buff
->MaxX
62 + Region
->left
+ Buff
->ShowX
) * 2;
63 SrcDelta
= Buff
->MaxX
* 2;
64 SrcEnd
= Buff
->Buffer
+ Buff
->MaxY
* Buff
->MaxX
* 2;
65 DestDelta
= ConioRectWidth(Region
) * 2;
66 for (i
= Region
->top
; i
<= Region
->bottom
; i
++)
68 memcpy(Dest
, Src
, DestDelta
);
72 Src
-= Buff
->MaxY
* Buff
->MaxX
* 2;
79 TuiDrawRegion(PCSRSS_CONSOLE Console
, RECT
*Region
)
82 PCSRSS_SCREEN_BUFFER Buff
= Console
->ActiveBuffer
;
83 LONG CursorX
, CursorY
;
84 PCONSOLE_DRAW ConsoleDraw
;
87 if (ActiveConsole
!= Console
)
92 ConsoleDrawSize
= sizeof(CONSOLE_DRAW
) +
93 (ConioRectWidth(Region
) * ConioRectHeight(Region
)) * 2;
94 ConsoleDraw
= HeapAlloc(Win32CsrApiHeap
, 0, ConsoleDrawSize
);
95 if (NULL
== ConsoleDraw
)
97 DPRINT1("HeapAlloc failed\n");
100 ConioPhysicalToLogical(Buff
, Buff
->CurrentX
, Buff
->CurrentY
, &CursorX
, &CursorY
);
101 ConsoleDraw
->X
= Region
->left
;
102 ConsoleDraw
->Y
= Region
->top
;
103 ConsoleDraw
->SizeX
= ConioRectWidth(Region
);
104 ConsoleDraw
->SizeY
= ConioRectHeight(Region
);
105 ConsoleDraw
->CursorX
= CursorX
;
106 ConsoleDraw
->CursorY
= CursorY
;
108 TuiCopyRect((char *) (ConsoleDraw
+ 1), Buff
, Region
);
110 if (! DeviceIoControl(ConsoleDeviceHandle
, IOCTL_CONSOLE_DRAW
,
111 NULL
, 0, ConsoleDraw
, ConsoleDrawSize
, &BytesReturned
, NULL
))
113 DPRINT1("Failed to draw console\n");
114 HeapFree(Win32CsrApiHeap
, 0, ConsoleDraw
);
118 HeapFree(Win32CsrApiHeap
, 0, ConsoleDraw
);
122 TuiWriteStream(PCSRSS_CONSOLE Console
, RECT
*Region
, LONG CursorStartX
, LONG CursorStartY
,
123 UINT ScrolledLines
, CHAR
*Buffer
, UINT Length
)
126 PCSRSS_SCREEN_BUFFER Buff
= Console
->ActiveBuffer
;
128 if (ActiveConsole
->ActiveBuffer
!= Buff
)
133 if (! WriteFile(ConsoleDeviceHandle
, Buffer
, Length
, &BytesWritten
, NULL
))
135 DPRINT1("Error writing to BlueScreen\n");
140 TuiSetCursorInfo(PCSRSS_CONSOLE Console
, PCSRSS_SCREEN_BUFFER Buff
)
144 if (ActiveConsole
->ActiveBuffer
!= Buff
)
149 if (! DeviceIoControl(ConsoleDeviceHandle
, IOCTL_CONSOLE_SET_CURSOR_INFO
,
150 &Buff
->CursorInfo
, sizeof(Buff
->CursorInfo
), NULL
, 0,
151 &BytesReturned
, NULL
))
153 DPRINT1( "Failed to set cursor info\n" );
161 TuiSetScreenInfo(PCSRSS_CONSOLE Console
, PCSRSS_SCREEN_BUFFER Buff
, UINT OldCursorX
, UINT OldCursorY
)
163 CONSOLE_SCREEN_BUFFER_INFO Info
;
164 LONG CursorX
, CursorY
;
167 if (ActiveConsole
->ActiveBuffer
!= Buff
)
172 ConioPhysicalToLogical(Buff
, Buff
->CurrentX
, Buff
->CurrentY
, &CursorX
, &CursorY
);
173 Info
.dwCursorPosition
.X
= CursorX
;
174 Info
.dwCursorPosition
.Y
= CursorY
;
175 Info
.wAttributes
= Buff
->DefaultAttrib
;
177 if (! DeviceIoControl(ConsoleDeviceHandle
, IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO
,
178 &Info
, sizeof(CONSOLE_SCREEN_BUFFER_INFO
), NULL
, 0,
179 &BytesReturned
, NULL
))
181 DPRINT1( "Failed to set cursor position\n" );
189 TuiChangeTitle(PCSRSS_CONSOLE Console
)
195 TuiCleanupConsole(PCSRSS_CONSOLE Console
)
197 EnterCriticalSection(&ActiveConsoleLock
);
199 /* Switch to next console */
200 if (ActiveConsole
== Console
)
202 ActiveConsole
= Console
->Next
!= Console
? Console
->Next
: NULL
;
205 if (Console
->Next
!= Console
)
207 Console
->Prev
->Next
= Console
->Next
;
208 Console
->Next
->Prev
= Console
->Prev
;
210 LeaveCriticalSection(&ActiveConsoleLock
);
212 if (NULL
!= ActiveConsole
)
214 ConioDrawConsole(ActiveConsole
);
218 static CSRSS_CONSOLE_VTBL TuiVtbl
=
230 TuiInitConsole(PCSRSS_CONSOLE Console
)
232 if (! ConsInitialized
)
234 ConsInitialized
= TRUE
;
237 ConsInitialized
= FALSE
;
238 return STATUS_UNSUCCESSFUL
;
242 Console
->Vtbl
= &TuiVtbl
;
243 Console
->hWindow
= (HWND
) NULL
;
244 Console
->Size
= PhysicalConsoleSize
;
246 EnterCriticalSection(&ActiveConsoleLock
);
247 if (NULL
!= ActiveConsole
)
249 Console
->Prev
= ActiveConsole
;
250 Console
->Next
= ActiveConsole
->Next
;
251 ActiveConsole
->Next
->Prev
= Console
;
252 ActiveConsole
->Next
= Console
;
256 Console
->Prev
= Console
;
257 Console
->Next
= Console
;
259 ActiveConsole
= Console
;
260 LeaveCriticalSection(&ActiveConsoleLock
);
262 return STATUS_SUCCESS
;
265 PCSRSS_CONSOLE FASTCALL
266 TuiGetFocusConsole(VOID
)
268 return ActiveConsole
;
272 TuiSwapConsole(int Next
)
274 static PCSRSS_CONSOLE SwapConsole
= NULL
; /* console we are thinking about swapping with */
282 /* alt-tab, swap consoles */
283 /* move SwapConsole to next console, and print its title */
284 EnterCriticalSection(&ActiveConsoleLock
);
287 SwapConsole
= ActiveConsole
;
290 SwapConsole
= (0 < Next
? SwapConsole
->Next
: SwapConsole
->Prev
);
291 Title
.MaximumLength
= RtlUnicodeStringToAnsiSize(&SwapConsole
->Title
);
293 Buffer
= HeapAlloc(Win32CsrApiHeap
,
295 sizeof(COORD
) + Title
.MaximumLength
);
296 pos
= (COORD
*)Buffer
;
297 Title
.Buffer
= (PVOID
)((ULONG_PTR
)Buffer
+ sizeof( COORD
));
299 RtlUnicodeStringToAnsiString(&Title
, &SwapConsole
->Title
, FALSE
);
300 pos
->Y
= PhysicalConsoleSize
.Y
/ 2;
301 pos
->X
= (PhysicalConsoleSize
.X
- Title
.Length
) / 2;
302 /* redraw the console to clear off old title */
303 ConioDrawConsole(ActiveConsole
);
304 if (! DeviceIoControl(ConsoleDeviceHandle
, IOCTL_CONSOLE_WRITE_OUTPUT_CHARACTER
,
305 NULL
, 0, Buffer
, sizeof(COORD
) + Title
.Length
,
306 &BytesReturned
, NULL
))
308 DPRINT1( "Error writing to console\n" );
310 HeapFree(Win32CsrApiHeap
, 0, Buffer
);
311 LeaveCriticalSection(&ActiveConsoleLock
);
315 else if (NULL
!= SwapConsole
)
317 EnterCriticalSection(&ActiveConsoleLock
);
318 if (SwapConsole
!= ActiveConsole
)
320 /* first remove swapconsole from the list */
321 SwapConsole
->Prev
->Next
= SwapConsole
->Next
;
322 SwapConsole
->Next
->Prev
= SwapConsole
->Prev
;
323 /* now insert before activeconsole */
324 SwapConsole
->Next
= ActiveConsole
;
325 SwapConsole
->Prev
= ActiveConsole
->Prev
;
326 ActiveConsole
->Prev
->Next
= SwapConsole
;
327 ActiveConsole
->Prev
= SwapConsole
;
329 ActiveConsole
= SwapConsole
;
331 ConioDrawConsole(ActiveConsole
);
332 LeaveCriticalSection(&ActiveConsoleLock
);