#include "vt.h"
#include <dev/display.h>
vt *ke_vt = 0;
vt::vt(node* parent, int ww, int hh) : node(parent, FT_TERMINAL) {
w = ww; h = hh;
fgcolor = TC_LIGHTGRAY;
bgcolor = TC_BLACK;
output = 0;
cursor_visible = true;
text = 0;
if (w != 0 && h != 0) {
text = (vt_char*)kmalloc(w * h * sizeof(vt_char));
clear();
}
}
void vt::put_at(int l, int c, int ch) {
text[l * w + c].fgcolor = fgcolor;
text[l * w + c].bgcolor = bgcolor;
text[l * w + c].ch = ch;
if (output != 0) output->text_put(l, c, ch, fgcolor, bgcolor);
}
void vt::put(int c) {
if (text == 0) return;
if (c == '\b' && csr_c != 0) {
csr_c--;
put_at(csr_l, csr_c, ' ');
} else if (c == '\t') {
int csr_nc = (csr_c + 8) & ~(8 - 1);
for (int i = csr_c; i < csr_nc && i < w; i++) put_at(csr_l, i, ' ');
csr_c = csr_nc;
} else if (c == '\r') {
csr_c = 0;
} else if (c == '\n') {
csr_c = 0;
csr_l++;
} else if (c >= ' ') {
put_at(csr_l, csr_c, c);
csr_c++;
}
if (csr_c >= w) {
csr_c = 0;
csr_l++;
}
if (csr_l == h) {
if (output != 0 && output->connected_vt == this) {
output->text_scroll(1, fgcolor, bgcolor);
}
for (int j = 0; j < w * (h-1); j++) {
text[j] = text[j + w];
}
for (int j = w * (h-1); j < w * h; j++) {
text[j].fgcolor = fgcolor;
text[j].bgcolor = bgcolor;
text[j].ch = ' ';
}
csr_l--;
}
if (output != 0 && output->connected_vt == this) output->text_setcsr(csr_l, csr_c, cursor_visible);
}
void vt::clear() {
for (int i = 0; i < w; i++) {
for (int j = 0; j < h; j++) {
put_at(j, i, ' ');
}
}
csr_c = csr_l = 0;
}
void vt::writeStr(char *s) {
while (*s) {
put(*(s++));
}
}
void vt::writeHex(uint32_t v) {
int i;
put('0'); put('x');
char hexdigits[] = "0123456789abcdef";
for (i = 0; i < 8; i++) {
put(hexdigits[v >> 28]);
v = v << 4;
}
}
void vt::writeDec(int v) {
if (v == 0) {
put('0');
return;
}
if (v < 0) {
put ('-');
v = -v;
}
char numbers[] = "0123456789";
while (v > 0) {
int order = 1, no = 1;
while (v / order > 0) order *= 10;
order /= 10;
put(numbers[v / order]);
v = v - (v / order * order);
while (v / no > 0) no *= 10;
while (no < order) {
put('0');
no *= 10;
}
}
}
// *******
int vt::outputTo(display *display) {
output = display;
if (output == 0) return 0;
output->connected_vt = this;
if (output->text_w() != w || output->text_h() != h) {
int ow = w, oh = h;
vt_char *old_text = text;
w = output->text_w();
h = output->text_h();
text = (vt_char*)malloc(w * h * sizeof(vt_char));
for (int c = 0; c < w; c++) {
for (int l = 0; l < h; l++) {
if (c < ow && l < oh) {
put_at(l, c, old_text[l * ow + c].ch);
} else {
put_at(l, c, ' ');
}
}
}
if (old_text != 0) free(old_text);
if (csr_c >= w) csr_c = w;
if (csr_l >= h) csr_l = h;
} else {
for (int c = 0; c < w; c++) {
for (int l = 0; l < h; l++) {
output->text_put(l, c, text[l*w+c].ch, text[l*w+c].fgcolor, text[l*w+c].bgcolor);
}
}
}
return 0;
}
int vt::write(size_t offset, size_t len, char* buffer) {
// ignore offset
for (unsigned i = 0; i < len; i++) put(buffer[i]);
return len;
}
size_t vt::get_size() {
return ((w << 16) + h);
}