summaryrefslogblamecommitdiff
path: root/src/kernel/ui/vt.cpp
blob: 4675cdc60f5161ff01fd350a35399db9fc668eb6 (plain) (tree)






























































































































































                                                                                                                 
#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(uint32_t v) {
	if (v == 0) {
		put('0');
		return;
	}

	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);
}