diff --git a/sortix/vgaterminal.cpp b/sortix/vgaterminal.cpp index cb463162..4aa04cfa 100644 --- a/sortix/vgaterminal.cpp +++ b/sortix/vgaterminal.cpp @@ -1,6 +1,6 @@ -/****************************************************************************** +/******************************************************************************* - COPYRIGHT(C) JONAS 'SORTIE' TERMANSEN 2011. + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012. This file is part of Sortix. @@ -14,13 +14,13 @@ FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License along - with Sortix. If not, see . + You should have received a copy of the GNU General Public License along with + Sortix. If not, see . vgaterminal.cpp - A terminal based on the VGA text mode buffer. + A terminal based on a text mode buffer. -******************************************************************************/ +*******************************************************************************/ #include #include @@ -31,535 +31,517 @@ using namespace Maxsi; -namespace Sortix +namespace Sortix { +namespace VGATerminal { + +const unsigned width = 80; +const unsigned height = 25; +const uint16_t DEFAULT_COLOR = (COLOR8_LIGHT_GREY << 8) | (COLOR8_BLACK << 12); +uint16_t* const vga = (uint16_t* const) 0xB8000; +uint16_t vgaattr[width * height]; +const uint16_t VGAATTR_CHAR = (1U<<0U); +unsigned line; +unsigned column; +uint16_t currentcolor; +unsigned ansisavedposx; +unsigned ansisavedposy; +bool showcursor; + +enum { - namespace VGATerminal + NONE, + CSI, + COMMAND, +} ansimode; + +void UpdateCursor() +{ + if ( showcursor ) + VGA::SetCursor(column, line); + else + VGA::SetCursor(width, height-1); +} + +// Clear the screen, put the cursor at the top left corner, set default +// text color, and reset ANSI escape sequence state. +void Reset() +{ + ansimode = NONE; + + line = 0; + column = 0; + ansisavedposx = 0; + ansisavedposy = 0; + + currentcolor = DEFAULT_COLOR; + + for ( nat y = 0; y < height; y++ ) { - const nat width = 80; - const nat height = 25; - const uint16_t defaultcolor = (COLOR8_LIGHT_GREY << 8) | (COLOR8_BLACK << 12); - uint16_t* const vga = (uint16_t* const) 0xB8000; - uint16_t vgaattr[width * height]; - const uint16_t VGAATTR_CHAR = (1U<<0U); - nat line; - nat column; - uint16_t currentcolor; - nat ansisavedposx; - nat ansisavedposy; - bool showcursor; - - enum + for ( nat x = 0; x < width; x++ ) { - NONE, - CSI, - COMMAND, - } ansimode; - - void UpdateCursor() - { - if ( showcursor ) - { - VGA::SetCursor(column, line); - } - else - { - VGA::SetCursor(width, height-1); - } + unsigned index = y * width + x; + vga[index] = ' ' | DEFAULT_COLOR; + vgaattr[index] = 0; } + } - // Clear the screen, put the cursor at the top left corner, set default - // text color, and reset ANSI escape sequence state. - void Reset() + // Reset the VGA cursor. + showcursor = true; + UpdateCursor(); +} + +// Initialize the terminal driver. +void Init() +{ + Reset(); +} + +// Move every line one row up and leaves an empty line at the bottom. +void ScrollUp() +{ + for ( nat y = 1; y < height; y++ ) + { + size_t linesize = width * sizeof(uint16_t); + size_t fromoff = (y-0) * width; + size_t destoff = (y-1) * width; + Memory::Copy(vga + destoff, vga + fromoff, linesize); + Memory::Copy(vgaattr + destoff, vgaattr + fromoff, linesize); + } + + for ( nat x = 0; x < width; x++ ) + { + unsigned index = (height-1) * width + x; + vga[index] = ' ' | currentcolor; + vgaattr[index] = 0; + } +} + +// Move every line one row down and leaves an empty line at the top. +void ScrollDown() +{ + for ( nat y = 1; y < height; y++ ) + { + size_t linesize = width * sizeof(uint16_t); + size_t fromoff = (y-1) * width; + size_t destoff = (y-0) * width; + Memory::Copy(vga + destoff, vga + fromoff, linesize); + Memory::Copy(vgaattr + destoff, vgaattr + fromoff, linesize); + } + + for ( nat x = 0; x < width; x++ ) + { + unsigned index = x; + vga[index] = ' ' | currentcolor; + vgaattr[index] = 0; + } +} + +// Move to the next line. If at bottom, scroll one line up. +void Newline() +{ + vgaattr[line * width + column] |= VGAATTR_CHAR; + if ( line < height - 1 ) + line++; + else + ScrollUp(); + column = 0; + UpdateCursor(); +} + +void ANSIReset(); +void ParseANSIEscape(char c); + +// Print text to the vga framebuffer, simulating how a terminal would +// display the text. +size_t Print(void* /*user*/, const char* string, size_t stringlen) +{ + // Iterate over each character. + size_t left = stringlen; + while ( (left--) > 0 ) + { + char c = *(string++); + + // If we are parsing an escape sequence, parse another char. + if ( ansimode != NONE ) { ParseANSIEscape(c); continue; } + + switch ( c ) { - ansimode = NONE; - - line = 0; - column = 0; - ansisavedposx = 0; - ansisavedposy = 0; - - currentcolor = defaultcolor; - - for ( nat y = 0; y < height; y++ ) + // Move cursor to the next line and scroll up (if needed). + case '\n': { - for ( nat x = 0; x < width; x++ ) - { - unsigned index = y * width + x; - vga[index] = ' ' | defaultcolor; - vgaattr[index] = 0; - } + Newline(); + break; } - - // Reset the VGA cursor. - showcursor = true; - UpdateCursor(); - } - - // Initialize the terminal driver. - void Init() - { - Reset(); - } - - // Move every line one row up and leaves an empty line at the bottom. - void ScrollUp() - { - for ( nat y = 1; y < height; y++ ) + // Move cursor to start of line. + case '\r': { - size_t linesize = width * sizeof(uint16_t); - size_t fromoff = (y-0) * width; - size_t destoff = (y-1) * width; - Memory::Copy(vga + destoff, vga + fromoff, linesize); - Memory::Copy(vgaattr + destoff, vgaattr + fromoff, linesize); + column = 0; + break; } - - for ( nat x = 0; x < width; x++ ) + // Delete the previous character. + case '\b': { - unsigned index = (height-1) * width + x; - vga[index] = ' ' | currentcolor; - vgaattr[index] = 0; + unsigned pos = line * width + column; + while ( pos ) + { + unsigned nextpos = pos-1; + vga[nextpos] = ' ' | currentcolor; + pos = nextpos; + uint16_t attr = vgaattr[pos]; + vgaattr[pos] = 0; + if ( attr & VGAATTR_CHAR ) { break; } + } + column = pos % width; + line = pos / width; + break; } - } - - // Move every line one row down and leaves an empty line at the top. - void ScrollDown() - { - for ( nat y = 1; y < height; y++ ) + // Expand a tab to a few spaces. + case '\t': { - size_t linesize = width * sizeof(uint16_t); - size_t fromoff = (y-1) * width; - size_t destoff = (y-0) * width; - Memory::Copy(vga + destoff, vga + fromoff, linesize); - Memory::Copy(vgaattr + destoff, vgaattr + fromoff, linesize); + if ( column == width ) { Newline(); } + nat until = 4 - (column % 4); + + vgaattr[line * width + (column)] |= VGAATTR_CHAR; + while ( (until--) != 0 ) + { + vga[line * width + (column++)] = ' ' | currentcolor; + } + break; } - - for ( nat x = 0; x < width; x++ ) + // Initialize an ANSI escape sequence, allowing much more + // powerful control of the terminal than ASCII does. + case '\e': { - unsigned index = x; - vga[index] = ' ' | currentcolor; - vgaattr[index] = 0; + ANSIReset(); + break; } - } - - // Move to the next line. If at bottom, scroll one line up. - void Newline() - { - vgaattr[line * width + column] |= VGAATTR_CHAR; - if ( line < height - 1 ) + // Print this character at the cursor and increment the cursor. + default: { - line++; column = 0; - } - else - { - ScrollUp(); column = 0; - } - - UpdateCursor(); - } - - void ANSIReset(); - void ParseANSIEscape(char c); - - // Print text to the vga framebuffer, simulating how a terminal would - // display the text. - size_t Print(void* /*user*/, const char* string, size_t stringlen) - { - // Check for the bug where string contains the address 0x80000000 - // which is not legal to print. It looks like we are trying to - // print a string from the stack that wasn't NUL-terminated. I - // tracked down the string value comes from LogTerminal, but it - // doesn't seem to originate from a write(2) call. Weird stuff. - addr_t straddr = (addr_t) string; - if ( straddr <= 0x80000000UL && 0x80000000UL <= straddr + stringlen ) - { - PanicF("Trying to print bad string 0x%zx + 0x%zx bytes: this " - "is a known bug, but with an unknown cause.", straddr, - stringlen); - } - - // Iterate over each character. - size_t left = stringlen; - while ( (left--) > 0 ) - { - char c = *(string++); - - // If we are parsing an escape sequence, parse another char. - if ( ansimode != NONE ) { ParseANSIEscape(c); continue; } - - switch ( c ) - { - // Move cursor to the next line and scroll up (if needed). - case '\n': - { - Newline(); - break; - } - // Move cursor to start of line. - case '\r': - { - column = 0; - break; - } - // Delete the previous character. - case '\b': - { - unsigned pos = line * width + column; - while ( pos ) - { - unsigned nextpos = pos-1; - vga[nextpos] = ' ' | currentcolor; - pos = nextpos; - uint16_t attr = vgaattr[pos]; - vgaattr[pos] = 0; - if ( attr & VGAATTR_CHAR ) { break; } - } - column = pos % width; - line = pos / width; - break; - } - // Expand a tab to a few spaces. - case '\t': - { - if ( column == width ) { Newline(); } - nat until = 4 - (column % 4); - - vgaattr[line * width + (column)] |= VGAATTR_CHAR; - while ( (until--) != 0 ) - { - vga[line * width + (column++)] = ' ' | currentcolor; - } - break; - } - // Initialize an ANSI escape sequence, allowing much more - // powerful control of the terminal than ASCII does. - case '\e': - { - ANSIReset(); - break; - } - // Print this character at the cursor and increment the cursor. - default: - { - if ( column == width ) { Newline(); } - unsigned index = line * width + (column++); - vga[index] = c | currentcolor; - vgaattr[index] |= VGAATTR_CHAR; - break; - } - } - } - - // Update the VGA hardware cursor. - UpdateCursor(); - - return stringlen; - } - - const size_t ANSI_NUM_PARAMS = 16; - nat ansiusedparams; - nat ansiparams[ANSI_NUM_PARAMS]; - nat currentparamindex; - bool paramundefined; - bool ignoresequence; - - // TODO: The ANSI escape code is only partially implemented! - - // Begin an ANSI esacpe sequence. - void ANSIReset() - { - if ( ansimode == NONE ) - { - ansiusedparams = 0; - currentparamindex = 0; - ansiparams[0] = 0; - paramundefined = true; - ignoresequence = false; - ansimode = CSI; - } - } - - // Reads parameters and changes font properties accordingly. - void AnsiSetFont() - { - // Convert from the ANSI color scheme to the VGA color scheme. - nat conversion[8] = { COLOR8_BLACK, COLOR8_RED, COLOR8_GREEN, COLOR8_BROWN, - COLOR8_BLUE, COLOR8_MAGENTA, COLOR8_CYAN, COLOR8_LIGHT_GREY }; - - for ( size_t i = 0; i < ansiusedparams; i++ ) - { - nat cmd = ansiparams[i]; - // Turn all attributes off. - if ( cmd == 0 ) - { - currentcolor = defaultcolor; - } - // Set text color. - else if ( 30 <= cmd && cmd <= 37 ) - { - nat val = cmd - 30; - currentcolor &= (0xF0FF); - currentcolor |= (conversion[val] << 8); - } - // Set background color. - else if ( 40 <= cmd && cmd <= 47 ) - { - nat val = cmd - 40; - currentcolor &= (0x0FFF); - currentcolor |= (conversion[val] << 12); - } - // TODO: There are many other things we don't support. - } - } - - // Executes an ASNI escape command based on given parameters. - void RunANSICommand(char c) - { - switch ( c ) - { - // Cursor up - case 'A': - { - nat dist = ( 0 < ansiusedparams ) ? ansiparams[0] : 1; - if ( line < dist ) { line = 0; } else { line -= dist; } - break; - } - // Cursor down - case 'B': - { - nat dist = ( 0 < ansiusedparams ) ? ansiparams[0] : 1; - if ( height <= line + dist ) { line = height-1; } else { line += dist; } - break; - } - // Cursor forward - case 'C': - { - nat dist = ( 0 < ansiusedparams ) ? ansiparams[0] : 1; - if ( width <= column + dist ) { column = width-1; } else { column += dist; } - break; - } - // Cursor backward - case 'D': - { - nat dist = ( 0 < ansiusedparams ) ? ansiparams[0] : 1; - if ( column < dist ) { column = 0; } else { column -= dist; } - break; - } - // Move to beginning of line N lines down. - case 'E': - { - column = 0; - nat dist = ( 0 < ansiusedparams ) ? ansiparams[0] : 1; - if ( height <= line + dist ) { line = height-1; } else { line += dist; } - break; - } - // Move to beginning of line N lines up. - case 'F': - { - column = 0; - nat dist = ( 0 < ansiusedparams ) ? ansiparams[0] : 1; - if ( line < dist ) { line = 0; } else { line -= dist; } - break; - } - // Move the cursor to column N. - case 'G': - { - nat pos = ( 0 < ansiusedparams ) ? ansiparams[0]-1 : 0; - if ( width <= pos ) { pos = width-1; } - column = pos; - break; - } - // Move the cursor to line Y, column X. - case 'H': - case 'f': - { - nat posy = ( 0 < ansiusedparams ) ? ansiparams[0]-1 : 0; - nat posx = ( 1 < ansiusedparams ) ? ansiparams[1]-1 : 0; - if ( width <= posx ) { posx = width-1; } - if ( height <= posy ) { posy = height-1; } - column = posx; - line = posy; - break; - } - // Erase parts of the screen. - case 'J': - { - nat mode = ( 0 < ansiusedparams ) ? ansiparams[0] : 0; - - nat from = 0; - nat to = 0; - - // From cursor to end. - if ( mode == 0 ) { from = line*width + column; to = height*width - 1; } - - // From start to cursor. - if ( mode == 1 ) { from = 0; to = line*width + column; } - - // Everything. - if ( mode == 2 ) { from = 0; to = height*width - 1; } - - for ( nat i = from; i <= to; i++ ) - { - vga[i] = ' ' | currentcolor; - vgaattr[i] = 0; - } - - break; - } - // Erase parts of the current line. - case 'K': - { - nat mode = ( 0 < ansiusedparams ) ? ansiparams[0] : 0; - - nat from = 0; - nat to = 0; - - // From cursor to end. - if ( mode == 0 ) { from = column; to = width - 1; } - - // From start to cursor. - if ( mode == 1 ) { from = 0; to = column; } - - // Everything. - if ( mode == 2 ) { from = 0; to = width - 1; } - - for ( nat i = from; i <= to; i++ ) - { - unsigned index = line * width + i; - vga[index] = ' ' | currentcolor; - vgaattr[index] = 0; - } - - break; - } - // Scroll a line up and place a new line at the buttom. - case 'S': - { - ScrollUp(); line = height-1; - break; - } - // Scroll a line up and place a new line at the top. - case 'T': - { - ScrollDown(); line = 0; - break; - } - // Change how the text is rendered. - case 'm': - { - if ( ansiusedparams == 0 ) - { - ansiparams[0] = 0; - ansiusedparams++; - } - AnsiSetFont(); - break; - } - // Request special information from terminal. - case 'n': - { - // TODO: Handle this code. - break; - } - // Save cursor position. - case 's': - { - ansisavedposx = column; - ansisavedposx = line; - break; - } - // Restore cursor position. - case 'u': - { - column = ansisavedposx; - line = ansisavedposx; - if ( width <= column ) { column = width-1; } - if ( height <= line ) { line = height-1; } - break; - } - // Hide cursor. - case 'l': - { - // TODO: This is somehow related to the special char '?'. - if ( 0 < ansiusedparams && ansiparams[0] == 25 ) - { - showcursor = false; - UpdateCursor(); - } - break; - } - // Show cursor. - case 'h': - { - // TODO: This is somehow related to the special char '?'. - if ( 0 < ansiusedparams && ansiparams[0] == 25 ) - { - showcursor = true; - UpdateCursor(); - } - break; - } - // TODO: Handle other cases. - } - - ansimode = NONE; - } - - // Parse another char of an ASNI escape code. - void ParseANSIEscape(char c) - { - // Check the proper prefixes are used. - if ( ansimode == CSI ) - { - if ( c != '[' ) { ansimode = NONE; return; } - ansimode = COMMAND; - } - - // Parse parameters and the command. - else if ( ansimode == COMMAND ) - { - // Read part of a parameter. - if ( '0' <= c && c <= '9' ) - { - if ( paramundefined ) { ansiusedparams++; } - paramundefined = false; - nat val = c - '0'; - ansiparams[currentparamindex] *= 10; - ansiparams[currentparamindex] += val; - } - - // Parameter delimiter. - else if ( c == ';' ) - { - if ( currentparamindex == ANSI_NUM_PARAMS - 1 ) { ansimode = NONE; return; } - paramundefined = true; - ansiparams[++currentparamindex] = 0; - } - - // Left for future standardization, so discard this sequence. - else if ( c == ':' ) - { - ignoresequence = true; - } - - // Run a command. - else if ( 64 <= c && c <= 126 ) - { - if ( !ignoresequence ) { RunANSICommand(c); } - } - - // Something I don't understand, and ignore intentionally. - else if ( c == '?' ) - { - } - - // TODO: There are some rare things that should be supported here. - - // Ignore unknown input. - else - { - ansimode = NONE; - } + if ( column == width ) { Newline(); } + unsigned index = line * width + (column++); + vga[index] = c | currentcolor; + vgaattr[index] |= VGAATTR_CHAR; + break; } } } + + // Update the VGA hardware cursor. + UpdateCursor(); + + return stringlen; } + +const size_t ANSI_NUM_PARAMS = 16; +nat ansiusedparams; +nat ansiparams[ANSI_NUM_PARAMS]; +nat currentparamindex; +bool paramundefined; +bool ignoresequence; + +// TODO: The ANSI escape code is only partially implemented! + +// Begin an ANSI esacpe sequence. +void ANSIReset() +{ + if ( ansimode == NONE ) + { + ansiusedparams = 0; + currentparamindex = 0; + ansiparams[0] = 0; + paramundefined = true; + ignoresequence = false; + ansimode = CSI; + } +} + +// Reads parameters and changes font properties accordingly. +void AnsiSetFont() +{ + // Convert from the ANSI color scheme to the VGA color scheme. + const unsigned conversion[8] = + { + COLOR8_BLACK, COLOR8_RED, COLOR8_GREEN, COLOR8_BROWN, + COLOR8_BLUE, COLOR8_MAGENTA, COLOR8_CYAN, COLOR8_LIGHT_GREY, + }; + + for ( size_t i = 0; i < ansiusedparams; i++ ) + { + nat cmd = ansiparams[i]; + // Turn all attributes off. + if ( cmd == 0 ) + { + currentcolor = DEFAULT_COLOR; + } + // Set text color. + else if ( 30 <= cmd && cmd <= 37 ) + { + nat val = cmd - 30; + currentcolor &= (0xF0FF); + currentcolor |= (conversion[val] << 8); + } + // Set background color. + else if ( 40 <= cmd && cmd <= 47 ) + { + nat val = cmd - 40; + currentcolor &= (0x0FFF); + currentcolor |= (conversion[val] << 12); + } + // TODO: There are many other things we don't support. + } +} + +// Executes an ASNI escape command based on given parameters. +void RunANSICommand(char c) +{ + switch ( c ) + { + // Cursor up + case 'A': + { + nat dist = ( 0 < ansiusedparams ) ? ansiparams[0] : 1; + if ( line < dist ) { line = 0; } else { line -= dist; } + break; + } + // Cursor down + case 'B': + { + nat dist = ( 0 < ansiusedparams ) ? ansiparams[0] : 1; + if ( height <= line + dist ) { line = height-1; } else { line += dist; } + break; + } + // Cursor forward + case 'C': + { + nat dist = ( 0 < ansiusedparams ) ? ansiparams[0] : 1; + if ( width <= column + dist ) { column = width-1; } else { column += dist; } + break; + } + // Cursor backward + case 'D': + { + nat dist = ( 0 < ansiusedparams ) ? ansiparams[0] : 1; + if ( column < dist ) { column = 0; } else { column -= dist; } + break; + } + // Move to beginning of line N lines down. + case 'E': + { + column = 0; + nat dist = ( 0 < ansiusedparams ) ? ansiparams[0] : 1; + if ( height <= line + dist ) { line = height-1; } else { line += dist; } + break; + } + // Move to beginning of line N lines up. + case 'F': + { + column = 0; + nat dist = ( 0 < ansiusedparams ) ? ansiparams[0] : 1; + if ( line < dist ) { line = 0; } else { line -= dist; } + break; + } + // Move the cursor to column N. + case 'G': + { + nat pos = ( 0 < ansiusedparams ) ? ansiparams[0]-1 : 0; + if ( width <= pos ) { pos = width-1; } + column = pos; + break; + } + // Move the cursor to line Y, column X. + case 'H': + case 'f': + { + nat posy = ( 0 < ansiusedparams ) ? ansiparams[0]-1 : 0; + nat posx = ( 1 < ansiusedparams ) ? ansiparams[1]-1 : 0; + if ( width <= posx ) { posx = width-1; } + if ( height <= posy ) { posy = height-1; } + column = posx; + line = posy; + break; + } + // Erase parts of the screen. + case 'J': + { + nat mode = ( 0 < ansiusedparams ) ? ansiparams[0] : 0; + + nat from = 0; + nat to = 0; + + // From cursor to end. + if ( mode == 0 ) { from = line*width + column; to = height*width - 1; } + + // From start to cursor. + if ( mode == 1 ) { from = 0; to = line*width + column; } + + // Everything. + if ( mode == 2 ) { from = 0; to = height*width - 1; } + + for ( nat i = from; i <= to; i++ ) + { + vga[i] = ' ' | currentcolor; + vgaattr[i] = 0; + } + + break; + } + // Erase parts of the current line. + case 'K': + { + nat mode = ( 0 < ansiusedparams ) ? ansiparams[0] : 0; + + nat from = 0; + nat to = 0; + + // From cursor to end. + if ( mode == 0 ) { from = column; to = width - 1; } + + // From start to cursor. + if ( mode == 1 ) { from = 0; to = column; } + + // Everything. + if ( mode == 2 ) { from = 0; to = width - 1; } + + for ( nat i = from; i <= to; i++ ) + { + unsigned index = line * width + i; + vga[index] = ' ' | currentcolor; + vgaattr[index] = 0; + } + + break; + } + // Scroll a line up and place a new line at the buttom. + case 'S': + { + ScrollUp(); line = height-1; + break; + } + // Scroll a line up and place a new line at the top. + case 'T': + { + ScrollDown(); line = 0; + break; + } + // Change how the text is rendered. + case 'm': + { + if ( ansiusedparams == 0 ) + { + ansiparams[0] = 0; + ansiusedparams++; + } + AnsiSetFont(); + break; + } + // Request special information from terminal. + case 'n': + { + // TODO: Handle this code. + break; + } + // Save cursor position. + case 's': + { + ansisavedposx = column; + ansisavedposx = line; + break; + } + // Restore cursor position. + case 'u': + { + column = ansisavedposx; + line = ansisavedposx; + if ( width <= column ) { column = width-1; } + if ( height <= line ) { line = height-1; } + break; + } + // Hide cursor. + case 'l': + { + // TODO: This is somehow related to the special char '?'. + if ( 0 < ansiusedparams && ansiparams[0] == 25 ) + { + showcursor = false; + UpdateCursor(); + } + break; + } + // Show cursor. + case 'h': + { + // TODO: This is somehow related to the special char '?'. + if ( 0 < ansiusedparams && ansiparams[0] == 25 ) + { + showcursor = true; + UpdateCursor(); + } + break; + } + // TODO: Handle other cases. + } + + ansimode = NONE; +} + +// Parse another char of an ASNI escape code. +void ParseANSIEscape(char c) +{ + // Check the proper prefixes are used. + if ( ansimode == CSI ) + { + if ( c != '[' ) { ansimode = NONE; return; } + ansimode = COMMAND; + } + + // Parse parameters and the command. + else if ( ansimode == COMMAND ) + { + // Read part of a parameter. + if ( '0' <= c && c <= '9' ) + { + if ( paramundefined ) { ansiusedparams++; } + paramundefined = false; + nat val = c - '0'; + ansiparams[currentparamindex] *= 10; + ansiparams[currentparamindex] += val; + } + + // Parameter delimiter. + else if ( c == ';' ) + { + if ( currentparamindex == ANSI_NUM_PARAMS - 1 ) { ansimode = NONE; return; } + paramundefined = true; + ansiparams[++currentparamindex] = 0; + } + + // Left for future standardization, so discard this sequence. + else if ( c == ':' ) + { + ignoresequence = true; + } + + // Run a command. + else if ( 64 <= c && c <= 126 ) + { + if ( !ignoresequence ) { RunANSICommand(c); } + } + + // Something I don't understand, and ignore intentionally. + else if ( c == '?' ) + { + } + + // TODO: There are some rare things that should be supported here. + + // Ignore unknown input. + else + { + ansimode = NONE; + } + } +} + +} // namespace VGATerminal +} // namespace Sortix diff --git a/sortix/vgaterminal.h b/sortix/vgaterminal.h index 2fb785ce..e011c4b8 100644 --- a/sortix/vgaterminal.h +++ b/sortix/vgaterminal.h @@ -1,6 +1,6 @@ -/****************************************************************************** +/******************************************************************************* - COPYRIGHT(C) JONAS 'SORTIE' TERMANSEN 2011. + Copyright(C) Jonas 'Sortie' Termansen 2011, 2012. This file is part of Sortix. @@ -14,26 +14,26 @@ FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License along - with Sortix. If not, see . + You should have received a copy of the GNU General Public License along with + Sortix. If not, see . - vgaterminal.h - A terminal based on the VGA text mode buffer. + vgaterminal.cpp + A terminal based on a text mode buffer. -******************************************************************************/ +*******************************************************************************/ #ifndef SORTIX_VGATERMINAL_H #define SORTIX_VGATERMINAL_H -namespace Sortix -{ - namespace VGATerminal - { - void Init(); - void Reset(); - size_t Print(void* user, const char* string, size_t stringlen); - } -} +namespace Sortix { +namespace VGATerminal { + +void Init(); +void Reset(); +size_t Print(void* user, const char* string, size_t stringlen); + +} // namespace VGATerminal +} // namespace Sortix #endif