Files
bsb2/kernel/arch/textwindow.cc
Niklas Gollenstede 174fe17e89 Handout
2025-10-31 22:37:36 +01:00

130 lines
2.7 KiB
C++

#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, ' ');
}
}