// console.c // Author: Josh Holtrop // Date: 08/02/04 // Modified: 08/03/04 #include "char/console.h" #include "hos_defines.h" #include "fs/devices.h" #include "mm/vmm.h" #include "lang/asmfuncs.h" console_t *consoles[256]; int activeConsole; void console_put_char(minor_t id, int c); void console_write_cursor(minor_t id, u16_t position); void console_refresh(); // initialization routine for consoles module int console_init(u32_t num, int width, int height) { activeConsole = 0; dev_driver_t *console_driver = New(dev_driver_t); console_driver->char_write = console_char_write; devices_register_major('c', MAJOR_CONSOLE, console_driver); kfree(console_driver); for (; num > 1; num--) { if (( consoles[num] = New(console_t) )) { if (( consoles[num]->buffer = kmalloc(width * height) )) { consoles[num]->width = width; consoles[num]->height = height; consoles[num]->attribute = consoles[num]->foreground = 0x07; memsetw(consoles[num]->buffer, 0x0720, width * height); } else { kfree(consoles[num]); return -2; } } else return -1; } return 0; } int console_activate(int num) { if (consoles[num]) { activeConsole = num; memcpyw((void*)CONSOLE_MEMORY, consoles[num]->buffer, consoles[num]->width * consoles[num]->height); writeCursorPosition(consoles[num]->cursorPosition); } return -1; } int console_char_write(minor_t id, u64_t position, int c) { if (!consoles[id]) return -1; int cursorY = consoles[id]->cursorPosition / consoles[id]->width; int cursorX = consoles[id]->cursorPosition % consoles[id]->width; switch (consoles[id]->escapeLevel) { case 2: if (c >= '0' && c <= '9') // c is part of an escape value { consoles[id]->escapeValue[consoles[id]->escapePosition] *= 10; consoles[id]->escapeValue[consoles[id]->escapePosition] += c - '0'; return 0; } else if (c == ';') { if (consoles[id]->escapePosition < 7) consoles[id]->escapePosition++; return 0; } switch (c) { case 'A': // move cursor up n rows cursorY -= consoles[id]->escapeValue[0]; if (cursorY < 0) cursorY = 0; console_write_cursor(id, cursorY * consoles[id]->width + cursorX); break; case 'B': // move cursor down n rows cursorY += consoles[id]->escapeValue[0]; if (cursorY >= consoles[id]->height) cursorY = consoles[id]->height - 1; console_write_cursor(id, cursorY * consoles[id]->width + cursorX); break; case 'C': // move cursor right n columns cursorX -= consoles[id]->escapeValue[0]; if (cursorX < 0) cursorX = 0; console_write_cursor(id, cursorY * consoles[id]->width + cursorX); break; case 'D': // move cursor left n columns cursorX += consoles[id]->escapeValue[0]; if (cursorX >= consoles[id]->width) cursorX = consoles[id]->width - 1; console_write_cursor(id, cursorY * consoles[id]->width + cursorX); break; case 'H': case 'f': // move cursor to position (x,y) upper left is (1,1) cursorX = consoles[id]->escapeValue[0] - 1; cursorY = consoles[id]->escapeValue[1] - 1; if (cursorY < 0) cursorY = 0; if (cursorY >= consoles[id]->height) cursorY = consoles[id]->height - 1; if (cursorX < 0) cursorX = 0; if (cursorX >= consoles[id]->width) cursorX = consoles[id]->width - 1; console_write_cursor(id, 0); break; case 'J': // clear screen, home cursor memsetw(consoles[id]->buffer, 0x0720, consoles[id]->width * consoles[id]->height); console_refresh(); console_write_cursor(id, 0); break; case 'K': // erase line from cursor position (including char. under cursor) to end of line memsetw(consoles[id]->buffer + consoles[id]->cursorPosition, 0x0720, consoles[id]->width - cursorX); console_refresh(); break; case 's': // push cursor position on an internal stack if (consoles[id]->cursorStackPosition < 16) consoles[id]->cursorStack[consoles[id]->cursorStackPosition++] = consoles[id]->cursorPosition; break; case 'u': // pop cursor position from stack if (consoles[id]->cursorStackPosition > 0) consoles[id]->cursorPosition = consoles[id]->cursorStack[--consoles[id]->cursorStackPosition]; break; case 'm': // set text attributes for (; consoles[id]->escapePosition >= 0; consoles[id]->escapePosition--) { switch (consoles[id]->escapeValue[consoles[id]->escapePosition]) { case 0: consoles[id]->attribute = 0x07; break; case 1: consoles[id]->attribute |= 0x08; break; case 5: consoles[id]->attribute |= 0x80; case 7: case 30: } } break; } memsetd(consoles[id]->escapeValue, 0, 8); consoles[id]->escapePosition = 0; consoles[id]->escapeLevel = 0; return 0; case 1: if (c == '[') consoles[id]->escapeLevel = 2; break; consoles[id]->escapeLevel = 0; return 0; // invalid escape sequence default: if (c == '\e') { consoles[id]->escapeLevel = 1; return 0; } console_put_char(id, c); } return 0; } void console_put_char(minor_t id, int c) { } void console_write_cursor(minor_t id, u16_t position) { consoles[id]->cursorPosition = position; if (activeConsole == id) writeCursorPosition(position); } void console_refresh() { if (activeConsole > 0) { memcpyw((void*)CONSOLE_MEMORY, consoles[activeConsole]->buffer, consoles[activeConsole]->width * consoles[activeConsole]->height); writeCursorPosition(consoles[activeConsole]->cursorPosition); } }