summaryrefslogtreecommitdiff
path: root/src/kernel/ui
diff options
context:
space:
mode:
authorAlex AUVOLAT <alexis211@gmail.com>2012-05-19 09:23:48 +0200
committerAlex AUVOLAT <alexis211@gmail.com>2012-05-19 09:23:48 +0200
commit7b466345af0d3a7dc5622617ce443a90c64e34a4 (patch)
treef276b6bf391ccfe8ec3a2cb62a7f70964249621f /src/kernel/ui
parentac10c1a29c44b0cb29960cd0f792c7361bc430ce (diff)
downloadTCE-7b466345af0d3a7dc5622617ce443a90c64e34a4.tar.gz
TCE-7b466345af0d3a7dc5622617ce443a90c64e34a4.zip
Added ANSI support, minimal readline-like library.
Diffstat (limited to 'src/kernel/ui')
-rw-r--r--src/kernel/ui/vt.cpp211
-rw-r--r--src/kernel/ui/vt.h5
2 files changed, 190 insertions, 26 deletions
diff --git a/src/kernel/ui/vt.cpp b/src/kernel/ui/vt.cpp
index 34dfbe9..9b0bdf0 100644
--- a/src/kernel/ui/vt.cpp
+++ b/src/kernel/ui/vt.cpp
@@ -3,12 +3,22 @@
vt *ke_vt = 0, *home_vt = 0;
+static char *kb_cmd_esc[] = {
+ /* 00 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 10 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 20 */ 0, 0, 0, 0, 0, 0, 0, 0, "\x1b[B", 0,
+ /* 30 */ "\x1b[D", 0, "\x1b[C", 0, "\x1b[A", 0, 0, 0, 0, 0,
+ /* 40 */ 0, 0, 0, 0, 0, 0, "\x1b[B", "\x1b[A", "\x1b[D", "\x1b[C",
+ /* 50 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 60 */ 0, 0, 0, 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;
+ keyboard_echo = false;
csr_l = csr_c = 0;
kbd_buffer_filled = 0;
@@ -34,6 +44,25 @@ void vt::put_at(int l, int c, int ch) {
}
}
+void vt::scroll(int n) {
+ if (output != 0 && output->connected_vt == this) {
+ output->text_scroll(n, fgcolor, bgcolor);
+ }
+ if (n > 0) {
+ for (int j = 0; j < w * (h-n); j++) {
+ text[j] = text[j + w];
+ }
+ for (int j = w * (h-n); j < w * h; j++) {
+ text[j].fgcolor = fgcolor;
+ text[j].bgcolor = bgcolor;
+ text[j].ch = ' ';
+ }
+ } else if (n < 0) {
+ //TODO
+ }
+ csr_l -= n;
+}
+
void vt::put(int c) {
if (text == 0) return;
@@ -60,18 +89,7 @@ void vt::put(int c) {
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--;
+ scroll(1);
}
if (output != 0 && output->connected_vt == this) output->text_setcsr(csr_l, csr_c, cursor_visible);
}
@@ -179,6 +197,11 @@ void vt::keyboardInput(keypress kp, keyboard* from) {
} else if (kp.command == KB_CMD_ALT && kp.character >= 64 && kp.character <= 126 && kp.pressed) {
b[n++] = 27;
b[n++] = kp.character;
+ } else if (kb_cmd_esc[kp.command & 0x3F] != 0 && kp.pressed) {
+ int i;
+ for (i = 0; kb_cmd_esc[kp.command & 0x3F][i] != 0; i++) {
+ b[n++] = kb_cmd_esc[kp.command & 0x3F][i];
+ }
}
if (n == 0) return;
if (kbd_buffer_filled + n > KBD_BUFFER_SIZE) goto wake_up;
@@ -200,7 +223,136 @@ 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]);
+ for (unsigned i = 0; i < len; i++) {
+ if (buffer[i] == 27) {
+ i++;
+ if (buffer[i++] == '[') {
+ int n = -1, m = -1;
+ while (buffer[i] >= '0' && buffer[i] <= '9') {
+ if (n == -1) n = 0;
+ n *= 10;
+ n += buffer[i] - '0';
+ i++;
+ }
+ if (buffer[i] == ';') {
+ i++;
+ while (buffer[i] >= '0' && buffer[i] <= '9') {
+ if (m == -1) m = 0;
+ m *= 10;
+ m += buffer[i] - '0';
+ i++;
+ }
+ }
+ if (buffer[i] == 'A') { // move cursor up
+ if (n == -1) n = 1;
+ csr_l -= n;
+ } else if (buffer[i] == 'B') { // move cursor down
+ if (n == -1) n = 1;
+ csr_l += n;
+ } else if (buffer[i] == 'C') { // move cursor forward
+ if (n == -1) n = 1;
+ csr_c += n;
+ } else if (buffer[i] == 'D') { // move cursor back
+ if (n == -1) n = 1;
+ csr_c -= n;
+ } else if (buffer[i] == 'E') { // move cursor n lines down, to beginning of line
+ if (n == -1) n = 1;
+ csr_l += n;
+ csr_c = 0;
+ } else if (buffer[i] == 'F') { // move cursor to beginning of line, n lines up
+ if (n == -1) n = 1;
+ csr_l -= n;
+ csr_c = 0;
+ } else if (buffer[i] == 'H' || buffer[i] == 'f') { // set cursor position
+ if (n == -1) n = 1;
+ if (m == -1) m = 1;
+ csr_l = n - 1;
+ csr_c = m - 1;
+ } else if (buffer[i] == 'J' || buffer[i] == 'K') { // erase data / erase line
+ if (n == -1) n = 0;
+ int start = 0, end = 0;
+ if (n == 0) {
+ start = csr_c; end = w;
+ } else if (n == 1) {
+ start = 0; end = csr_c;
+ } else if (n == 2) {
+ start = 0; end = w;
+ }
+ for (int p = start; p < end; p++) put_at(csr_l, p, ' ');
+ if (buffer[i] == 'J') { // erase data
+ if (n == 0) {
+ start = csr_l + 1; end = h;
+ } else if (n == 1) {
+ start = 0; end = csr_l;
+ } else if (n == 2) {
+ start = 0; end = h;
+ }
+ for (int l = start; l < end; l++) {
+ for (int c = 0; c < w; c++) put_at(l, c, ' ');
+ }
+ }
+ } else if (buffer[i] == 'S') { // scroll up
+ if (n == -1) n = 1;
+ scroll(n);
+ } else if (buffer[i] == 'T') { // scroll down
+ if (n == -1) n = 1;
+ scroll(-n);
+ } else if (buffer[i] == 'm') { // select graphic rendition
+ if (n == -1) n = 0;
+ if (n == 0) {
+ fgcolor = 7;
+ bgcolor = 0;
+ } else if (n == 1) {
+ fgcolor |= TC_MAKE_LIGHT;
+ } else if (n == 22) {
+ fgcolor &= TC_MAKE_DARK;
+ } else if (n >= 30 && n <= 37) {
+ fgcolor = (fgcolor & TC_MAKE_LIGHT) | (n - 30);
+ } else if (n >= 40 && n <= 47) {
+ bgcolor = (n - 40);
+ } else {
+ // others to do.
+ }
+ } else if (buffer[i] == 'n') { // device status report
+ kbd_buffer[kbd_buffer_filled++] = 27;
+ kbd_buffer[kbd_buffer_filled++] = '[';
+ if (csr_l >= 100) kbd_buffer[kbd_buffer_filled++] = ((csr_l / 100) % 10) + '0';
+ if (csr_l >= 10) kbd_buffer[kbd_buffer_filled++] = ((csr_l / 10) % 10) + '0';
+ kbd_buffer[kbd_buffer_filled++] = (csr_l % 10) + '0';
+ kbd_buffer[kbd_buffer_filled++] = ';';
+ if (csr_c >= 100) kbd_buffer[kbd_buffer_filled++] = ((csr_c / 100) % 10) + '0';
+ if (csr_c >= 10) kbd_buffer[kbd_buffer_filled++] = ((csr_c / 10) % 10) + '0';
+ kbd_buffer[kbd_buffer_filled++] = (csr_c % 10) + '0';
+ kbd_buffer[kbd_buffer_filled++] = 'R';
+ } else if (buffer[i] == 's') { // save cursor position
+ save_csr_l = csr_l;
+ save_csr_c = csr_c;
+ } else if (buffer[i] == 'p') { // restore cursor position
+ csr_l = save_csr_l;
+ csr_c = save_csr_c;
+ } else if (buffer[i] == 'e') { // CUSTOM : enable keyboard echo
+ keyboard_echo = true;
+ } else if (buffer[i] == 'h') { // CUSTOM : disable keyboard echo
+ keyboard_echo = false;
+ } else if (buffer[i] == '?') {
+ if (buffer[++i] == '2' && buffer[++i] == '5') {
+ if (buffer[++i] == 'l') cursor_visible = false;
+ else cursor_visible = true;
+ }
+ } else {
+ }
+ if (csr_l < 0) csr_l = 0;
+ if (csr_c < 0) csr_c = 0;
+ if (csr_l >= h) csr_l = h - 1;
+ if (csr_c >= w) csr_c = w - 1;
+ if (output != 0 && output->connected_vt == this) output->text_setcsr(csr_l, csr_c, cursor_visible);
+ } else {
+ // ignore it.
+ }
+ } else {
+ put(buffer[i]);
+ }
+ }
return len;
}
@@ -212,19 +364,30 @@ int vt::read(size_t offset, size_t len, char* buffer) {
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');
+ if (keyboard_echo) {
+ for (; r < kbd_buffer_filled; r++) {
+ if (kbd_buffer[r] == '\b') {
+ if (c > 0) {
+ c--;
+ put('\b');
+ }
+ } else if (kbd_buffer[r] == '\n') {
+ buffer[c++] = '\n';
+ c++;
+ put('\n');
+ end = true;
+ break;
+ } else if (kbd_buffer[r] >= ' ') {
+ buffer[c++] = kbd_buffer[r];
+ put(buffer[c]);
}
- } else {
- buffer[c] = kbd_buffer[r];
- put(buffer[c]);
- if (buffer[c] == '\n' || buffer[c] == 27) end = true;
- c++;
+ if (c == len) break;
+ }
+ } else {
+ for (; r < kbd_buffer_filled && c < len; r++) {
+ buffer[c++] = kbd_buffer[r];
}
- if (c == len) break;
+ end = true;
}
memcpy(kbd_buffer + r, kbd_buffer, (kbd_buffer_filled - r));
kbd_buffer_filled -= r;
diff --git a/src/kernel/ui/vt.h b/src/kernel/ui/vt.h
index a80452b..a29716f 100644
--- a/src/kernel/ui/vt.h
+++ b/src/kernel/ui/vt.h
@@ -15,11 +15,11 @@ struct vt_char {
class vt : public node {
private:
display *output;
- int w, h, csr_l, csr_c;
+ int w, h, csr_l, csr_c, save_csr_l, save_csr_c;
vt_char *text;
void put_at(int l, int c, int ch);
- bool cursor_visible;
+ bool cursor_visible, keyboard_echo;
int kbd_buffer_filled;
char kbd_buffer[KBD_BUFFER_SIZE];
@@ -35,6 +35,7 @@ class vt : public node {
// internal use
void put(int c);
void clear();
+ void scroll(int l);
void writeStr(char* str) { write(0, strlen(str), str); }
void writeHex(uint32_t v);
void writeDec(int v);