#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(x), static_cast(y)); } } void TextWindow::getPos(int& rel_x, int& rel_y) const { unsigned x; unsigned y; getPos(x, y); rel_x = static_cast(x); rel_y = static_cast(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, ' '); } }