Handout
This commit is contained in:
129
kernel/arch/textwindow.cc
Normal file
129
kernel/arch/textwindow.cc
Normal file
@@ -0,0 +1,129 @@
|
||||
#include "textwindow.h"
|
||||
|
||||
#include "../utils/math.h"
|
||||
|
||||
TextWindow::TextWindow(unsigned from_col, unsigned to_col, unsigned from_row,
|
||||
unsigned to_row, bool use_cursor)
|
||||
: from_col(from_col),
|
||||
to_col(to_col),
|
||||
from_row(from_row),
|
||||
to_row(to_row),
|
||||
use_cursor(use_cursor),
|
||||
pos_x(from_col),
|
||||
pos_y(from_row) {
|
||||
if (to_col > from_col && to_row > from_row) {
|
||||
reset();
|
||||
}
|
||||
}
|
||||
|
||||
void TextWindow::setPos(unsigned rel_x, unsigned rel_y) {
|
||||
unsigned abs_x = rel_x + from_col;
|
||||
unsigned abs_y = rel_y + from_row;
|
||||
|
||||
// Check if visible
|
||||
if (abs_x < to_col && abs_y < to_row) {
|
||||
if (use_cursor) {
|
||||
CGA::setCursor(abs_x, abs_y);
|
||||
} else {
|
||||
pos_x = abs_x;
|
||||
pos_y = abs_y;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TextWindow::getPos(unsigned& rel_x, unsigned& rel_y) const {
|
||||
unsigned abs_x = pos_x;
|
||||
unsigned abs_y = pos_y;
|
||||
|
||||
if (use_cursor) {
|
||||
CGA::getCursor(abs_x, abs_y);
|
||||
}
|
||||
|
||||
rel_x = Math::min(Math::max(abs_x, from_col), to_col - 1) - from_col;
|
||||
rel_y = Math::min(Math::max(abs_y, from_row), to_row - 1) - from_row;
|
||||
}
|
||||
|
||||
void TextWindow::setPos(int rel_x, int rel_y) {
|
||||
int x = rel_x < 0 ? rel_x + to_col - from_col : rel_x;
|
||||
int y = rel_y < 0 ? rel_y + to_row - from_row : rel_y;
|
||||
|
||||
if (x >= 0 && y >= 0) {
|
||||
setPos(static_cast<unsigned>(x), static_cast<unsigned>(y));
|
||||
}
|
||||
}
|
||||
|
||||
void TextWindow::getPos(int& rel_x, int& rel_y) const {
|
||||
unsigned x;
|
||||
unsigned y;
|
||||
getPos(x, y);
|
||||
rel_x = static_cast<int>(x);
|
||||
rel_y = static_cast<int>(y);
|
||||
}
|
||||
|
||||
void TextWindow::print(const char* str, size_t length, CGA::Attribute attrib) {
|
||||
// Get position
|
||||
unsigned abs_x = pos_x;
|
||||
unsigned abs_y = pos_y;
|
||||
|
||||
if (use_cursor) {
|
||||
CGA::getCursor(abs_x, abs_y);
|
||||
}
|
||||
|
||||
// Print each character
|
||||
while (length > 0) {
|
||||
switch (*str) {
|
||||
case '\n':
|
||||
abs_x = from_col;
|
||||
abs_y++;
|
||||
break;
|
||||
|
||||
case '\r':
|
||||
abs_x = from_col;
|
||||
break;
|
||||
|
||||
default:
|
||||
show(abs_x, abs_y, *str, attrib);
|
||||
abs_x++;
|
||||
if (abs_x >= to_col) {
|
||||
abs_x = from_col;
|
||||
abs_y++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
str++;
|
||||
if (abs_y >= to_row) {
|
||||
scrollUp();
|
||||
abs_y--;
|
||||
}
|
||||
length--;
|
||||
}
|
||||
// Write position back
|
||||
if (use_cursor) {
|
||||
CGA::setCursor(abs_x, abs_y);
|
||||
} else {
|
||||
pos_x = abs_x;
|
||||
pos_y = abs_y;
|
||||
}
|
||||
}
|
||||
|
||||
void TextWindow::reset(char character, CGA::Attribute attrib) {
|
||||
for (unsigned abs_y = from_row; abs_y < to_row; ++abs_y) {
|
||||
for (unsigned abs_x = from_col; abs_x < to_col; ++abs_x) {
|
||||
show(abs_x, abs_y, character, attrib);
|
||||
}
|
||||
}
|
||||
setPos(0, 0);
|
||||
}
|
||||
|
||||
void TextWindow::scrollUp() const {
|
||||
for (unsigned y = from_row + 1; y < to_row; ++y) {
|
||||
for (unsigned x = from_col; x < to_col; ++x) {
|
||||
unsigned pos = (y * CGA::COLUMNS) + x;
|
||||
show(x, y - 1, CGA::TEXT_BUFFER_BASE[pos].character,
|
||||
CGA::TEXT_BUFFER_BASE[pos].attribute);
|
||||
}
|
||||
}
|
||||
for (unsigned x = from_col; x < to_col; ++x) {
|
||||
CGA::show(x, to_row - 1, ' ');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user