#include "tty.h"
#include "alloc.h"
Tty* createTty(uint16 lineCount, uint16 columnCount, TtyFlushScreenFunction flushFunction) {
Tty* tty = kmalloc(sizeof(Tty));
memset((uint8*)tty, 0, sizeof(Tty));
tty->lineCount = lineCount;
tty->columnCount = columnCount;
tty->buffer = kmalloc(tty->lineCount * tty->columnCount * 2);
tty->currentColumn = 0;
tty->currentLine = 0;
tty->color = 0x0A;
memset(tty->lineBuffer, 0, TTY_LINEBUFFER_SIZE);
tty->lineBufferIndex = 0;
tty->keyBuffer = FifoBuffer_create(64);
tty->flushScreen = flushFunction;
tty->term.c_cc[VMIN] = 1;
tty->term.c_lflag |= ECHO;
tty->term.c_lflag |= ICANON;
Tty_Clear(tty);
return tty;
}
void destroyTty(Tty* tty) {
FifoBuffer_destroy(tty->keyBuffer);
kfree(tty->buffer);
kfree(tty);
}
void Tty_Print(Tty* tty, int row, int column, const char* text) {
unsigned char * video = tty->buffer;
video += (row * tty->columnCount + column) * 2;
while(*text != 0) {
*video++ = *text++;
*video++ = tty->color;
}
}
//One line
void Tty_ScrollUp(Tty* tty) {
unsigned char * videoLine = tty->buffer;
unsigned char * videoLineNext = tty->buffer;
int line = 0;
int column = 0;
for (line = 0; line < tty->lineCount - 1; ++line) {
for (column = 0; column < tty->columnCount; ++column) {
videoLine = tty->buffer + (line * tty->columnCount + column) * 2;
videoLineNext = tty->buffer + ((line + 1) * tty->columnCount + column) * 2;
videoLine[0] = videoLineNext[0];
videoLine[1] = videoLineNext[1];
}
}
//Last line should be empty.
unsigned char * lastLine = tty->buffer + ((tty->lineCount - 1) * tty->columnCount) * 2;
for (int i = 0; i < tty->columnCount * 2; i += 2) {
lastLine[i] = 0;
lastLine[i + 1] = tty->color;
}
}
void Tty_Clear(Tty* tty) {
unsigned char * video = tty->buffer;
int i = 0;
for (i = 0; i < tty->lineCount * tty->columnCount; ++i) {
*video++ = 0;
*video++ = tty->color;
}
tty->currentLine = 0;
tty->currentColumn = 0;
}
void Tty_PutChar(Tty* tty, char c) {
unsigned char * video = tty->buffer;
if ('\n' == c || '\r' == c) {
++tty->currentLine;
tty->currentColumn = 0;
if (tty->currentLine >= tty->lineCount - 0) {
--tty->currentLine;
Tty_ScrollUp(tty);
}
Tty_MoveCursor(tty, tty->currentLine, tty->currentColumn);
return;
}
else if ('\b' == c) {
if (tty->currentColumn > 0) {
--tty->currentColumn;
c = '\0';
video = tty->buffer + (tty->currentLine * tty->columnCount + tty->currentColumn) * 2;
video[0] = c;
video[1] = tty->color;
Tty_MoveCursor(tty, tty->currentLine, tty->currentColumn);
return;
}
else if (tty->currentColumn == 0) {
if (tty->currentLine > 0) {
--tty->currentLine;
tty->currentColumn = tty->columnCount - 1;
c = '\0';
video = tty->buffer + (tty->currentLine * tty->columnCount + tty->currentColumn) * 2;
video[0] = c;
video[1] = tty->color;
Tty_MoveCursor(tty, tty->currentLine, tty->currentColumn);
return;
}
}
}
if (tty->currentColumn >= tty->columnCount) {
++tty->currentLine;
tty->currentColumn = 0;
}
if (tty->currentLine >= tty->lineCount - 0) {
--tty->currentLine;
Tty_ScrollUp(tty);
}
video += (tty->currentLine * tty->columnCount + tty->currentColumn) * 2;
video[0] = c;
video[1] = tty->color;
++tty->currentColumn;
Tty_MoveCursor(tty, tty->currentLine, tty->currentColumn);
}
void Tty_PutText(Tty* tty, const char* text) {
const char* c = text;
while (*c) {
Tty_PutChar(tty, *c);
++c;
}
}
void Tty_MoveCursor(Tty* tty, uint16 line, uint16 column) {
tty->currentLine = line;
tty->currentColumn = column;
}