The Pedigree Project 0.1
LocalIO.cc
1/*
2 * Copyright (c) 2008-2014, Pedigree Developers
3 *
4 * Please see the CONTRIB file in the root of the source tree for a full
5 * list of contributors.
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20#include "pedigree/kernel/debugger/LocalIO.h"
21#include "pedigree/kernel/machine/Keyboard.h"
22#include "pedigree/kernel/machine/Vga.h"
23
24LocalIO::LocalIO(Vga* pVga, Keyboard* pKeyboard)
25 : m_nWidth(80),
26 m_nHeight(25),
27 m_UpperCliLimit(0),
28 m_LowerCliLimit(0),
29 m_CursorX(0),
30 m_CursorY(0),
31 m_pVga(pVga),
32 m_pKeyboard(pKeyboard) {
33 initialise();
34}
35
36LocalIO::~LocalIO() {}
37
38void LocalIO::initialise() {
39 m_nWidth = 80;
40 m_nHeight = 25;
43 m_CursorX = 0;
44 m_CursorY = 0;
45 // Clear the framebuffer.
46 for (size_t i = 0; i < MAX_CONSOLE_WIDTH * MAX_CONSOLE_HEIGHT; i++) {
47 uint8_t attributeByte = (DebuggerIO::Black << 4) | (DebuggerIO::White & 0x0F);
48 uint16_t blank = ' ' | (attributeByte << 8);
49 m_pFramebuffer[i] = blank;
50 }
51 m_pCommand[0] = '\0';
52
53 // Copy the current screen contents into our old frame buffer.
54 m_pVga->peekBuffer(reinterpret_cast<uint8_t*>(m_pOldFramebuffer),
55 MAX_CONSOLE_WIDTH * MAX_CONSOLE_HEIGHT * 2);
56 // Set a nice big text mode.
58
59 // Set our width and height variables.
60 m_nWidth = m_pVga->getNumCols();
61 m_nHeight = m_pVga->getNumRows();
62}
63
64void LocalIO::destroy() {
65 // Copy our old frame buffer to the screen.
66 m_pVga->pokeBuffer(reinterpret_cast<uint8_t*>(m_pOldFramebuffer),
67 MAX_CONSOLE_WIDTH * MAX_CONSOLE_HEIGHT * 2);
68}
69
70void LocalIO::setCliUpperLimit(size_t nlines) {
71 // Do a quick sanity check.
72 if (nlines < m_nHeight)
73 m_UpperCliLimit = nlines;
74
75 // If the cursor is now in an invalid area, move it back.
76 if (m_CursorY < m_UpperCliLimit)
77 m_CursorY = m_UpperCliLimit;
78}
79
80void LocalIO::setCliLowerLimit(size_t nlines) {
81 // Do a quick sanity check.
82 if (nlines < m_nHeight)
83 m_LowerCliLimit = nlines;
84
85 // If the cursor is now in an invalid area, move it back.
86 if (m_CursorY >= m_nHeight - m_LowerCliLimit)
87 m_CursorY = m_LowerCliLimit;
88}
89
91 // Clear the framebuffer.
92 for (size_t i = 0; i < m_nWidth * m_nHeight; i++) {
93 uint8_t attributeByte = (DebuggerIO::Black << 4) | (DebuggerIO::White & 0x0F);
94 uint16_t blank = ' ' | (attributeByte << 8);
95 m_pFramebuffer[i] = blank;
96 }
97 m_pCommand[0] = '\0';
98
99 // Reposition the cursor.
100 m_CursorX = 0;
101 m_CursorY = m_UpperCliLimit;
102
103 // We've enabled the CLI, so let's make sure the screen is ready.
104 forceRefresh();
105}
106
107void LocalIO::disableCli() {
108 // Clear the framebuffer.
109 for (size_t i = 0; i < m_nWidth * m_nHeight; i++) {
110 uint8_t attributeByte = (DebuggerIO::Black << 4) | (DebuggerIO::White & 0x0F);
111 uint16_t blank = ' ' | (attributeByte << 8);
112 m_pFramebuffer[i] = blank;
113 }
114
115 // Reposition the cursor.
116 m_CursorX = 0;
117 m_CursorY = m_UpperCliLimit;
118
119 forceRefresh();
120}
121
122char LocalIO::getCharNonBlock() {
124}
125
127 return m_pKeyboard->getChar();
128}
129
130void LocalIO::drawHorizontalLine(char c, size_t row, size_t colStart, size_t colEnd,
131 DebuggerIO::Colour foreColour, DebuggerIO::Colour backColour) {
132 // colEnd must be bigger than colStart.
133 if (colStart > colEnd) {
134 size_t tmp = colStart;
135 colStart = colEnd;
136 colEnd = tmp;
137 }
138
139 if (colEnd >= m_nWidth)
140 colEnd = m_nWidth - 1;
141 if (static_cast<int32_t>(colStart) < 0)
142 colStart = 0;
143 if (row >= m_nHeight)
144 row = m_nHeight - 1;
145 if (static_cast<int32_t>(row) < 0)
146 row = 0;
147
148 uint8_t attributeByte = (backColour << 4) | (foreColour & 0x0F);
149 for (size_t i = colStart; i <= colEnd; i++) {
150 m_pFramebuffer[row * m_nWidth + i] = c | (attributeByte << 8);
151 }
152
154 forceRefresh();
155}
156
157void LocalIO::drawVerticalLine(char c, size_t col, size_t rowStart, size_t rowEnd,
158 DebuggerIO::Colour foreColour, DebuggerIO::Colour backColour) {
159 // rowEnd must be bigger than rowStart.
160 if (rowStart > rowEnd) {
161 size_t tmp = rowStart;
162 rowStart = rowEnd;
163 rowEnd = tmp;
164 }
165
166 if (rowEnd >= m_nHeight)
167 rowEnd = m_nHeight - 1;
168 if (static_cast<int32_t>(rowStart) < 0)
169 rowStart = 0;
170 if (col >= m_nWidth)
171 col = m_nWidth - 1;
172 if (static_cast<int32_t>(col) < 0)
173 col = 0;
174
175 uint8_t attributeByte = (backColour << 4) | (foreColour & 0x0F);
176 for (size_t i = rowStart; i <= rowEnd; i++) {
177 m_pFramebuffer[i * m_nWidth + col] = c | (attributeByte << 8);
178 }
179
181 forceRefresh();
182}
183
184void LocalIO::drawString(const char* str, size_t row, size_t col, DebuggerIO::Colour foreColour,
185 DebuggerIO::Colour backColour) {
186 // Now then, this is a lesson in cheating. Listen up.
187 // Firstly we save the current cursorX and cursorY positions.
188 size_t savedX = m_CursorX;
189 size_t savedY = m_CursorY;
190
191 // Then, we change cursorX and Y to be row, col.
192 m_CursorX = col;
193 m_CursorY = row;
194
195 bool bRefreshWasEnabled = false;
197 bRefreshWasEnabled = true;
198 m_bRefreshesEnabled = false;
199 }
200
201 // Then, we just call putChar to put the string out for us! :)
202 while (*str)
203 putChar(*str++, foreColour, backColour);
204
205 if (bRefreshWasEnabled) {
206 m_bRefreshesEnabled = true;
207 forceRefresh();
208 }
209
210 // And restore the cursor.
211 m_CursorX = savedX;
212 m_CursorY = savedY;
213
214 // Ensure the cursor is correct in hardware.
215 moveCursor();
216}
217
219 m_bRefreshesEnabled = true;
220 forceRefresh();
221}
222
223void LocalIO::disableRefreshes() {
224 m_bRefreshesEnabled = false;
225}
226
227void LocalIO::forceRefresh() {
228 m_pVga->pokeBuffer(reinterpret_cast<uint8_t*>(m_pFramebuffer), m_nWidth * m_nHeight * 2);
229 moveCursor();
230}
231
233 // Get a space character with the default colour attributes.
234 uint8_t attributeByte = (DebuggerIO::Black << 4) | (DebuggerIO::White & 0x0F);
235 uint16_t blank = ' ' | (attributeByte << 8);
236 if (m_CursorY >= m_nHeight - m_LowerCliLimit) {
237 for (size_t i = m_UpperCliLimit * m_nWidth; i < (m_nHeight - m_LowerCliLimit - 1) * m_nWidth;
238 i++)
239 m_pFramebuffer[i] = m_pFramebuffer[i + m_nWidth];
240
241 for (size_t i = (m_nHeight - m_LowerCliLimit - 1) * m_nWidth;
242 i < (m_nHeight - m_LowerCliLimit) * m_nWidth; i++)
243 m_pFramebuffer[i] = blank;
244
245 m_CursorY = m_nHeight - m_LowerCliLimit - 1;
246 }
247}
248
250 m_pVga->moveCursor(m_CursorX, m_CursorY);
251}
252
253void LocalIO::putChar(char c, DebuggerIO::Colour foreColour, DebuggerIO::Colour backColour) {
254 // Backspace?
255 if (c == 0x08) {
256 // Can we just move backwards? or do we have to go up?
257 if (m_CursorX)
258 m_CursorX--;
259 else {
260 m_CursorX = m_nWidth - 1;
261 m_CursorY--;
262 }
263
264 // Erase the contents of the cell currently.
265 uint8_t attributeByte = (backColour << 4) | (foreColour & 0x0F);
266 m_pFramebuffer[m_CursorY * m_nWidth + m_CursorX] = ' ' | (attributeByte << 8);
267 }
268
269 // Tab?
270 else if (c == 0x09 && (((m_CursorX + 8) & ~(8 - 1)) < m_nWidth))
271 m_CursorX = (m_CursorX + 8) & ~(8 - 1);
272
273 // Carriage return?
274 else if (c == '\r')
275 m_CursorX = 0;
276
277 // Newline?
278 else if (c == '\n') {
279 m_CursorX = 0;
280 m_CursorY++;
281 }
282
283 // Normal character?
284 else if (c >= ' ') {
285 uint8_t attributeByte = (backColour << 4) | (foreColour & 0x0F);
286 m_pFramebuffer[m_CursorY * m_nWidth + m_CursorX] = c | (attributeByte << 8);
287
288 // Increment the cursor.
289 m_CursorX++;
290 }
291
292 // Do we need to wrap?
293 if (m_CursorX >= m_nWidth) {
294 m_CursorX = 0;
295 m_CursorY++;
296 }
297}
298
299void LocalIO::cls() {
300 // Clear the framebuffer.
301 for (size_t i = 0; i < m_nWidth * m_nHeight; i++) {
302 unsigned char attributeByte = (DebuggerIO::Black << 4) | (DebuggerIO::White & 0x0F);
303 unsigned short blank = ' ' | (attributeByte << 8);
304 m_pFramebuffer[i] = blank;
305 }
306}
char m_pCommand[COMMAND_MAX]
Definition DebuggerIO.h:175
bool m_bRefreshesEnabled
Definition DebuggerIO.h:180
virtual char getCharNonBlock()=0
virtual char getChar()=0
uint16_t m_pFramebuffer[MAX_CONSOLE_WIDTH *MAX_CONSOLE_HEIGHT]
Definition LocalIO.h:133
LocalIO(Vga *pVga, Keyboard *pKeyboard)
Definition LocalIO.cc:24
size_t m_LowerCliLimit
Definition LocalIO.h:148
char getChar()
Definition LocalIO.cc:126
void enableRefreshes()
Definition LocalIO.cc:218
void enableCli()
Definition LocalIO.cc:90
size_t m_UpperCliLimit
Definition LocalIO.h:146
void moveCursor()
Definition LocalIO.cc:249
Keyboard * m_pKeyboard
Definition LocalIO.h:164
uint16_t m_pOldFramebuffer[MAX_CONSOLE_WIDTH *MAX_CONSOLE_HEIGHT]
Definition LocalIO.h:138
void setCliUpperLimit(size_t nlines)
Definition LocalIO.cc:70
void drawString(const char *str, size_t row, size_t col, DebuggerIO::Colour foreColour, DebuggerIO::Colour backColour)
Definition LocalIO.cc:184
void scroll()
Definition LocalIO.cc:232
size_t m_CursorX
Definition LocalIO.h:154
void drawHorizontalLine(char c, size_t row, size_t colStart, size_t colEnd, DebuggerIO::Colour foreColour, DebuggerIO::Colour backColour)
Definition LocalIO.cc:130
Vga * m_pVga
Definition LocalIO.h:159
virtual void moveCursor(size_t nX, size_t nY)=0
virtual bool setLargestTextMode()=0
virtual size_t getNumRows()=0
virtual void pokeBuffer(uint8_t *pBuffer, size_t nBufLen)=0
virtual size_t getNumCols()=0
virtual void peekBuffer(uint8_t *pBuffer, size_t nBufLen)=0