Reactos
1/*
2 * PROJECT: ReactOS Boot Video Driver
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: Platform-independent console functionality
5 * COPYRIGHT: Copyright 2010 Gregor Schneider <gregor.schneider@reactos.org>
6 * Copyright 2011 Rafal Harabien <rafalh@reactos.org>
7 * Copyright 2020 Stanislav Motylkov <x86corez@gmail.com>
8 */
9
10#include "precomp.h"
11
12/* GLOBALS ********************************************************************/
13
14UCHAR VidpTextColor = BV_COLOR_WHITE;
15ULONG VidpCurrentX = 0;
16ULONG VidpCurrentY = 0;
17URECT VidpScrollRegion = {0, 0, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1};
18
19static BOOLEAN ClearRow = FALSE;
20
21/* PUBLIC FUNCTIONS ***********************************************************/
22
23VOID
24NTAPI
25VidResetDisplay(
26 _In_ BOOLEAN SetMode)
27{
28 /* Clear the current position */
29 VidpCurrentX = 0;
30 VidpCurrentY = 0;
31
32 /* Invoke the hardware-specific routine */
33 ResetDisplay(SetMode);
34}
35
36ULONG
37NTAPI
38VidSetTextColor(
39 _In_ ULONG Color)
40{
41 ULONG OldColor;
42
43 /* Save the old color and set the new one */
44 OldColor = VidpTextColor;
45 VidpTextColor = Color;
46 return OldColor;
47}
48
49VOID
50NTAPI
51VidSetScrollRegion(
52 _In_ ULONG Left,
53 _In_ ULONG Top,
54 _In_ ULONG Right,
55 _In_ ULONG Bottom)
56{
57 /* Assert alignment */
58 ASSERT((Left % BOOTCHAR_WIDTH) == 0);
59 ASSERT((Right % BOOTCHAR_WIDTH) == BOOTCHAR_WIDTH - 1);
60
61 /* Set the scroll region */
62 VidpScrollRegion.Left = Left;
63 VidpScrollRegion.Top = Top;
64 VidpScrollRegion.Right = Right;
65 VidpScrollRegion.Bottom = Bottom;
66
67 /* Set the current X and Y */
68 VidpCurrentX = Left;
69 VidpCurrentY = Top;
70}
71
72VOID
73NTAPI
74VidDisplayStringXY(
75 _In_ PCSTR String,
76 _In_ ULONG Left,
77 _In_ ULONG Top,
78 _In_ BOOLEAN Transparent)
79{
80 ULONG BackColor;
81
82 /*
83 * If the caller wanted transparent, then send the special value (16),
84 * else use our default and call the helper routine.
85 */
86 BackColor = Transparent ? BV_COLOR_NONE : BV_COLOR_LIGHT_CYAN;
87
88 /* Loop every character and adjust the position */
89 for (; *String; ++String, Left += BOOTCHAR_WIDTH)
90 {
91 /* Display a character */
92 DisplayCharacter(*String, Left, Top, BV_COLOR_LIGHT_BLUE, BackColor);
93 }
94}
95
96VOID
97NTAPI
98VidDisplayString(
99 _In_ PCSTR String)
100{
101 /* Start looping the string */
102 for (; *String; ++String)
103 {
104 /* Treat new-line separately */
105 if (*String == '\n')
106 {
107 /* Modify Y position */
108 VidpCurrentY += BOOTCHAR_HEIGHT + 1;
109 if (VidpCurrentY + BOOTCHAR_HEIGHT > VidpScrollRegion.Bottom)
110 {
111 /* Scroll the view and clear the current row */
112 DoScroll(BOOTCHAR_HEIGHT + 1);
113 VidpCurrentY -= BOOTCHAR_HEIGHT + 1;
114 PreserveRow(VidpCurrentY, BOOTCHAR_HEIGHT + 1, TRUE);
115 }
116 else
117 {
118 /* Preserve the current row */
119 PreserveRow(VidpCurrentY, BOOTCHAR_HEIGHT + 1, FALSE);
120 }
121
122 /* Update current X */
123 VidpCurrentX = VidpScrollRegion.Left;
124
125 /* No need to clear this row */
126 ClearRow = FALSE;
127 }
128 else if (*String == '\r')
129 {
130 /* Update current X */
131 VidpCurrentX = VidpScrollRegion.Left;
132
133 /* If a new-line does not follow we will clear the current row */
134 if (String[1] != '\n')
135 ClearRow = TRUE;
136 }
137 else
138 {
139 /* Clear the current row if we had a return-carriage without a new-line */
140 if (ClearRow)
141 {
142 PreserveRow(VidpCurrentY, BOOTCHAR_HEIGHT + 1, TRUE);
143 ClearRow = FALSE;
144 }
145
146 /* Display this character */
147 DisplayCharacter(*String, VidpCurrentX, VidpCurrentY, VidpTextColor, BV_COLOR_NONE);
148 VidpCurrentX += BOOTCHAR_WIDTH;
149
150 /* Check if we should scroll */
151 if (VidpCurrentX + BOOTCHAR_WIDTH - 1 > VidpScrollRegion.Right)
152 {
153 /* Update Y position and check if we should scroll it */
154 VidpCurrentY += BOOTCHAR_HEIGHT + 1;
155 if (VidpCurrentY + BOOTCHAR_HEIGHT > VidpScrollRegion.Bottom)
156 {
157 /* Scroll the view and clear the current row */
158 DoScroll(BOOTCHAR_HEIGHT + 1);
159 VidpCurrentY -= BOOTCHAR_HEIGHT + 1;
160 PreserveRow(VidpCurrentY, BOOTCHAR_HEIGHT + 1, TRUE);
161 }
162 else
163 {
164 /* Preserve the current row */
165 PreserveRow(VidpCurrentY, BOOTCHAR_HEIGHT + 1, FALSE);
166 }
167
168 /* Update current X */
169 VidpCurrentX = VidpScrollRegion.Left;
170 }
171 }
172 }
173}