summaryrefslogtreecommitdiff
path: root/src/kernel/ui
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel/ui')
-rw-r--r--src/kernel/ui/vt.cpp159
-rw-r--r--src/kernel/ui/vt.h49
2 files changed, 208 insertions, 0 deletions
diff --git a/src/kernel/ui/vt.cpp b/src/kernel/ui/vt.cpp
new file mode 100644
index 0000000..4675cdc
--- /dev/null
+++ b/src/kernel/ui/vt.cpp
@@ -0,0 +1,159 @@
+#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);
+}
diff --git a/src/kernel/ui/vt.h b/src/kernel/ui/vt.h
new file mode 100644
index 0000000..b4f3672
--- /dev/null
+++ b/src/kernel/ui/vt.h
@@ -0,0 +1,49 @@
+#ifndef DEF_UI_VT_H
+#define DEF_UI_VT_H
+
+#include <vfs/node.h>
+#include <dev/display.h>
+
+struct vt_char {
+ int ch;
+ uint8_t fgcolor, bgcolor;
+};
+
+class vt : public node {
+ private:
+ display *output;
+ int w, h, csr_l, csr_c;
+ vt_char *text;
+
+ void put_at(int l, int c, int ch);
+ bool cursor_visible;
+
+ public:
+ uint8_t fgcolor, bgcolor;
+
+ vt(node* parent, int w, int h);
+
+ // internal use
+ void put(int c);
+ void clear();
+ void writeStr(char* str);
+ void writeHex(uint32_t v);
+ void writeDec(uint32_t v);
+
+ int outputTo(display *display);
+
+ virtual int write(size_t offset, size_t len, char* buffer);
+ virtual size_t get_size();
+};
+
+extern vt *ke_vt;
+#define NL ke_vt->writeStr("\n");
+#define TAB ke_vt->writeStr("\t");
+#define WHERE { ke_vt->writeStr("(ke:"); \
+ ke_vt->writeStr(__FILE__); \
+ ke_vt->writeStr(":"); \
+ ke_vt->writeDec(__LINE__); \
+ ke_vt->writeStr(") "); }
+
+#endif
+