diff options
Diffstat (limited to 'src/kernel/ui/vt.cpp')
-rw-r--r-- | src/kernel/ui/vt.cpp | 101 |
1 files changed, 87 insertions, 14 deletions
diff --git a/src/kernel/ui/vt.cpp b/src/kernel/ui/vt.cpp index cbb29f7..48a2da4 100644 --- a/src/kernel/ui/vt.cpp +++ b/src/kernel/ui/vt.cpp @@ -9,6 +9,9 @@ vt::vt(node* parent, int ww, int hh) : node(parent, FT_TERMINAL) { bgcolor = TC_BLACK; output = 0; cursor_visible = true; + + kbd_buffer_filled = 0; + kbd_waiter = 0; text = 0; if (w != 0 && h != 0) { @@ -27,18 +30,20 @@ void vt::put_at(int l, int c, int ch) { void vt::put(int c) { if (text == 0) return; - if (c == '\b' && csr_c != 0) { + if (c == '\b' && csr_c != 0) { // backspace csr_c--; put_at(csr_l, csr_c, ' '); - } else if (c == '\t') { + } else if (c == '\t') { // tab 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') { + } else if (c == '\r') { // carriage return csr_c = 0; - } else if (c == '\n') { + } else if (c == '\n') { // new line csr_c = 0; csr_l++; + } else if (c == '\f') { // form feed (new page) + clear(); } else if (c >= ' ') { put_at(csr_l, csr_c, c); csr_c++; @@ -73,12 +78,6 @@ void vt::clear() { csr_c = csr_l = 0; } -void vt::writeStr(char *s) { - while (*s) { - put(*(s++)); - } -} - void vt::writeHex(uint32_t v) { int i; @@ -116,11 +115,11 @@ void vt::writeDec(int v) { } } -// ******* +// *************** INTERACTION -int vt::outputTo(display *display) { +void vt::outputTo(display *display) { output = display; - if (output == 0) return 0; + if (output == 0) return; output->connected_vt = this; if (output->text_w() != w || output->text_h() != h) { @@ -149,15 +148,89 @@ int vt::outputTo(display *display) { } } } - return 0; } +void vt::keyboardInput(keypress kp) { + // convert to sequence of chars + int n = 0; + char b[8]; + + if (kp.character >= 0x80) kp.character = '?'; // todo some day : unicode + + if ((kp.command == 0 || kp.command == KB_ENTER || kp.command == KB_TAB || kp.command == KB_BACKSPACE) + && kp.character != 0 && kp.pressed) { + b[n++] = (char)kp.character; + } else if (kp.command == KB_CMD_ALT && kp.character >= 64 && kp.character <= 126 && kp.pressed) { + b[n++] = 27; + b[n++] = kp.character; + } + if (n == 0) return; + if (kbd_buffer_filled + n > KBD_BUFFER_SIZE) goto wake_up; + for (int i = 0; i < n; i++) { + kbd_buffer[kbd_buffer_filled++] = b[i]; + } + + wake_up: + if (kbd_waiter != 0) { + thread *w = kbd_waiter; + kbd_waiter = 0; + w->wakeUp(); + } +} + +// ********************* SYSCALLS + int vt::write(size_t offset, size_t len, char* buffer) { // ignore offset + // TODO: ANSI escape sequences + // todo some day : unicode for (unsigned i = 0; i < len; i++) put(buffer[i]); return len; } +int vt::read(size_t offset, size_t len, char* buffer) { + // ignore offset + + unsigned c = 0; + while (true) { + bool end = false; + if (kbd_buffer_filled > 0) { + int r = 0; + for (; r < kbd_buffer_filled; r++) { + if (kbd_buffer[r] == '\b') { + if (c > 0) { + c--; + put('\b'); + } + } else { + buffer[c] = kbd_buffer[r]; + put(buffer[c]); + if (buffer[c] == '\n' || buffer[c] == 27) end = true; + c++; + } + if (c == len) break; + } + memcpy(kbd_buffer + r, kbd_buffer, (kbd_buffer_filled - r)); + kbd_buffer_filled -= r; + } + if (end || c == len) return c; + + kbd_waiter = current_thread; + thread_goInactive(); + } +} + size_t vt::get_size() { return ((w << 16) + h); } + +int vt::link(node* to, int mode) { + if (mode == LM_OUTPUT_TO) { + display *d = to->as_display(); + if (d != 0) { + outputTo(d); + return 0; + } + } + return E_NOT_IMPLEMENTED; +} |