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 
24 LocalIO::LocalIO(Vga *pVga, Keyboard *pKeyboard)
25  : m_nWidth(80), m_nHeight(25), m_UpperCliLimit(0), m_LowerCliLimit(0),
26  m_CursorX(0), m_CursorY(0), m_pVga(pVga), m_pKeyboard(pKeyboard)
27 {
28  initialise();
29 }
30 
31 LocalIO::~LocalIO()
32 {
33 }
34 
35 void LocalIO::initialise()
36 {
37  m_nWidth = 80;
38  m_nHeight = 25;
39  m_UpperCliLimit = 0;
40  m_LowerCliLimit = 0;
41  m_CursorX = 0;
42  m_CursorY = 0;
43  // Clear the framebuffer.
44  for (size_t i = 0; i < MAX_CONSOLE_WIDTH * MAX_CONSOLE_HEIGHT; i++)
45  {
46  uint8_t attributeByte =
47  (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  // Save the current mode.
55  // Copy the current screen contents into our old frame buffer.
57  reinterpret_cast<uint8_t *>(m_pOldFramebuffer),
58  MAX_CONSOLE_WIDTH * MAX_CONSOLE_HEIGHT * 2);
59  // Set a nice big text mode.
61 
62  // Set our width and height variables.
63  m_nWidth = m_pVga->getNumCols();
64  m_nHeight = m_pVga->getNumRows();
65 }
66 
67 void LocalIO::destroy()
68 {
69  // Copy our old frame buffer to the screen.
71  reinterpret_cast<uint8_t *>(m_pOldFramebuffer),
72  MAX_CONSOLE_WIDTH * MAX_CONSOLE_HEIGHT * 2);
74 }
75 
76 void LocalIO::setCliUpperLimit(size_t nlines)
77 {
78  // Do a quick sanity check.
79  if (nlines < m_nHeight)
80  m_UpperCliLimit = nlines;
81 
82  // If the cursor is now in an invalid area, move it back.
83  if (m_CursorY < m_UpperCliLimit)
84  m_CursorY = m_UpperCliLimit;
85 }
86 
87 void LocalIO::setCliLowerLimit(size_t nlines)
88 {
89  // Do a quick sanity check.
90  if (nlines < m_nHeight)
91  m_LowerCliLimit = nlines;
92 
93  // If the cursor is now in an invalid area, move it back.
94  if (m_CursorY >= m_nHeight - m_LowerCliLimit)
95  m_CursorY = m_LowerCliLimit;
96 }
97 
99 {
100  // Clear the framebuffer.
101  for (size_t i = 0; i < m_nWidth * m_nHeight; i++)
102  {
103  uint8_t attributeByte =
104  (DebuggerIO::Black << 4) | (DebuggerIO::White & 0x0F);
105  uint16_t blank = ' ' | (attributeByte << 8);
106  m_pFramebuffer[i] = blank;
107  }
108  m_pCommand[0] = '\0';
109 
110  // Reposition the cursor.
111  m_CursorX = 0;
112  m_CursorY = m_UpperCliLimit;
113 
114  // We've enabled the CLI, so let's make sure the screen is ready.
115  forceRefresh();
116 }
117 
118 void LocalIO::disableCli()
119 {
120  // Clear the framebuffer.
121  for (size_t i = 0; i < m_nWidth * m_nHeight; i++)
122  {
123  uint8_t attributeByte =
124  (DebuggerIO::Black << 4) | (DebuggerIO::White & 0x0F);
125  uint16_t blank = ' ' | (attributeByte << 8);
126  m_pFramebuffer[i] = blank;
127  }
128 
129  // Reposition the cursor.
130  m_CursorX = 0;
131  m_CursorY = m_UpperCliLimit;
132 
133  forceRefresh();
134 }
135 
136 char LocalIO::getCharNonBlock()
137 {
138  return m_pKeyboard->getCharNonBlock();
139 }
140 
142 {
143  return m_pKeyboard->getChar();
144 }
145 
147  char c, size_t row, size_t colStart, size_t colEnd,
148  DebuggerIO::Colour foreColour, DebuggerIO::Colour backColour)
149 {
150  // colEnd must be bigger than colStart.
151  if (colStart > colEnd)
152  {
153  size_t tmp = colStart;
154  colStart = colEnd;
155  colEnd = tmp;
156  }
157 
158  if (colEnd >= m_nWidth)
159  colEnd = m_nWidth - 1;
160  if (static_cast<int32_t>(colStart) < 0)
161  colStart = 0;
162  if (row >= m_nHeight)
163  row = m_nHeight - 1;
164  if (static_cast<int32_t>(row) < 0)
165  row = 0;
166 
167  uint8_t attributeByte = (backColour << 4) | (foreColour & 0x0F);
168  for (size_t i = colStart; i <= colEnd; i++)
169  {
170  m_pFramebuffer[row * m_nWidth + i] = c | (attributeByte << 8);
171  }
172 
174  forceRefresh();
175 }
176 
177 void LocalIO::drawVerticalLine(
178  char c, size_t col, size_t rowStart, size_t rowEnd,
179  DebuggerIO::Colour foreColour, DebuggerIO::Colour backColour)
180 {
181  // rowEnd must be bigger than rowStart.
182  if (rowStart > rowEnd)
183  {
184  size_t tmp = rowStart;
185  rowStart = rowEnd;
186  rowEnd = tmp;
187  }
188 
189  if (rowEnd >= m_nHeight)
190  rowEnd = m_nHeight - 1;
191  if (static_cast<int32_t>(rowStart) < 0)
192  rowStart = 0;
193  if (col >= m_nWidth)
194  col = m_nWidth - 1;
195  if (static_cast<int32_t>(col) < 0)
196  col = 0;
197 
198  uint8_t attributeByte = (backColour << 4) | (foreColour & 0x0F);
199  for (size_t i = rowStart; i <= rowEnd; i++)
200  {
201  m_pFramebuffer[i * m_nWidth + col] = c | (attributeByte << 8);
202  }
203 
205  forceRefresh();
206 }
207 
209  const char *str, size_t row, size_t col, DebuggerIO::Colour foreColour,
210  DebuggerIO::Colour backColour)
211 {
212  // Now then, this is a lesson in cheating. Listen up.
213  // Firstly we save the current cursorX and cursorY positions.
214  size_t savedX = m_CursorX;
215  size_t savedY = m_CursorY;
216 
217  // Then, we change cursorX and Y to be row, col.
218  m_CursorX = col;
219  m_CursorY = row;
220 
221  bool bRefreshWasEnabled = false;
223  {
224  bRefreshWasEnabled = true;
225  m_bRefreshesEnabled = false;
226  }
227 
228  // Then, we just call putChar to put the string out for us! :)
229  while (*str)
230  putChar(*str++, foreColour, backColour);
231 
232  if (bRefreshWasEnabled)
233  {
234  m_bRefreshesEnabled = true;
235  forceRefresh();
236  }
237 
238  // And restore the cursor.
239  m_CursorX = savedX;
240  m_CursorY = savedY;
241 
242  // Ensure the cursor is correct in hardware.
243  moveCursor();
244 }
245 
247 {
248  m_bRefreshesEnabled = true;
249  forceRefresh();
250 }
251 
252 void LocalIO::disableRefreshes()
253 {
254  m_bRefreshesEnabled = false;
255 }
256 
257 void LocalIO::forceRefresh()
258 {
260  reinterpret_cast<uint8_t *>(m_pFramebuffer), m_nWidth * m_nHeight * 2);
261  moveCursor();
262 }
263 
265 {
266  // Get a space character with the default colour attributes.
267  uint8_t attributeByte =
268  (DebuggerIO::Black << 4) | (DebuggerIO::White & 0x0F);
269  uint16_t blank = ' ' | (attributeByte << 8);
270  if (m_CursorY >= m_nHeight - m_LowerCliLimit)
271  {
272  for (size_t i = m_UpperCliLimit * m_nWidth;
273  i < (m_nHeight - m_LowerCliLimit - 1) * m_nWidth; i++)
274  m_pFramebuffer[i] = m_pFramebuffer[i + m_nWidth];
275 
276  for (size_t i = (m_nHeight - m_LowerCliLimit - 1) * m_nWidth;
277  i < (m_nHeight - m_LowerCliLimit) * m_nWidth; i++)
278  m_pFramebuffer[i] = blank;
279 
280  m_CursorY = m_nHeight - m_LowerCliLimit - 1;
281  }
282 }
283 
285 {
286  m_pVga->moveCursor(m_CursorX, m_CursorY);
287 }
288 
289 void LocalIO::putChar(
290  char c, DebuggerIO::Colour foreColour, DebuggerIO::Colour backColour)
291 {
292  // Backspace?
293  if (c == 0x08)
294  {
295  // Can we just move backwards? or do we have to go up?
296  if (m_CursorX)
297  m_CursorX--;
298  else
299  {
300  m_CursorX = m_nWidth - 1;
301  m_CursorY--;
302  }
303 
304  // Erase the contents of the cell currently.
305  uint8_t attributeByte = (backColour << 4) | (foreColour & 0x0F);
306  m_pFramebuffer[m_CursorY * m_nWidth + m_CursorX] =
307  ' ' | (attributeByte << 8);
308  }
309 
310  // Tab?
311  else if (c == 0x09 && (((m_CursorX + 8) & ~(8 - 1)) < m_nWidth))
312  m_CursorX = (m_CursorX + 8) & ~(8 - 1);
313 
314  // Carriage return?
315  else if (c == '\r')
316  m_CursorX = 0;
317 
318  // Newline?
319  else if (c == '\n')
320  {
321  m_CursorX = 0;
322  m_CursorY++;
323  }
324 
325  // Normal character?
326  else if (c >= ' ')
327  {
328  uint8_t attributeByte = (backColour << 4) | (foreColour & 0x0F);
329  m_pFramebuffer[m_CursorY * m_nWidth + m_CursorX] =
330  c | (attributeByte << 8);
331 
332  // Increment the cursor.
333  m_CursorX++;
334  }
335 
336  // Do we need to wrap?
337  if (m_CursorX >= m_nWidth)
338  {
339  m_CursorX = 0;
340  m_CursorY++;
341  }
342 }
343 
344 void LocalIO::cls()
345 {
346  // Clear the framebuffer.
347  for (size_t i = 0; i < m_nWidth * m_nHeight; i++)
348  {
349  unsigned char attributeByte =
350  (DebuggerIO::Black << 4) | (DebuggerIO::White & 0x0F);
351  unsigned short blank = ' ' | (attributeByte << 8);
352  m_pFramebuffer[i] = blank;
353  }
354 }
LocalIO(Vga *pVga, Keyboard *pKeyboard)
Definition: LocalIO.cc:24
void moveCursor()
Definition: LocalIO.cc:284
virtual void moveCursor(size_t nX, size_t nY)=0
virtual void restoreMode()=0
void scroll()
Definition: LocalIO.cc:264
virtual char getChar()=0
void setCliUpperLimit(size_t nlines)
Definition: LocalIO.cc:76
virtual void rememberMode()=0
size_t m_CursorX
Definition: LocalIO.h:168
virtual char getCharNonBlock()=0
virtual void pokeBuffer(uint8_t *pBuffer, size_t nBufLen)=0
char m_pCommand[COMMAND_MAX]
Definition: DebuggerIO.h:187
void drawString(const char *str, size_t row, size_t col, DebuggerIO::Colour foreColour, DebuggerIO::Colour backColour)
Definition: LocalIO.cc:208
void enableRefreshes()
Definition: LocalIO.cc:246
size_t m_LowerCliLimit
Definition: LocalIO.h:162
char getChar()
Definition: LocalIO.cc:141
void enableCli()
Definition: LocalIO.cc:98
void drawHorizontalLine(char c, size_t row, size_t colStart, size_t colEnd, DebuggerIO::Colour foreColour, DebuggerIO::Colour backColour)
Definition: LocalIO.cc:146
size_t m_UpperCliLimit
Definition: LocalIO.h:160
uint16_t m_pFramebuffer[MAX_CONSOLE_WIDTH *MAX_CONSOLE_HEIGHT]
Definition: LocalIO.h:147
Keyboard * m_pKeyboard
Definition: LocalIO.h:178
uint16_t m_pOldFramebuffer[MAX_CONSOLE_WIDTH *MAX_CONSOLE_HEIGHT]
Definition: LocalIO.h:152
virtual void peekBuffer(uint8_t *pBuffer, size_t nBufLen)=0
bool m_bRefreshesEnabled
Definition: DebuggerIO.h:192
virtual bool setLargestTextMode()=0
Vga * m_pVga
Definition: LocalIO.h:173
virtual size_t getNumRows()=0
virtual size_t getNumCols()=0