Upgrade ANSI parser
This commit is contained in:
parent
c5504b80dc
commit
641221c2bb
114
vga_drv/cansid.c
114
vga_drv/cansid.c
@ -1,114 +0,0 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "cansid.h"
|
||||
|
||||
#define ESC '\x1B'
|
||||
|
||||
struct cansid_state cansid_init(void)
|
||||
{
|
||||
struct cansid_state rv = {
|
||||
.state = CANSID_ESC,
|
||||
.style = 0x0F,
|
||||
.next_style = 0x0F
|
||||
};
|
||||
return rv;
|
||||
}
|
||||
|
||||
static inline unsigned char cansid_convert_color(unsigned char color)
|
||||
{
|
||||
const unsigned char lookup_table[8] = { 0, 4, 2, 6, 1, 5, 3, 7 };
|
||||
return lookup_table[(int)color];
|
||||
}
|
||||
|
||||
struct color_char cansid_process(struct cansid_state *state, char x)
|
||||
{
|
||||
struct color_char rv = {
|
||||
.style = state->style,
|
||||
.ascii = '\0'
|
||||
};
|
||||
switch (state->state) {
|
||||
case CANSID_ESC:
|
||||
if (x == ESC)
|
||||
state->state = CANSID_BRACKET;
|
||||
else {
|
||||
rv.ascii = x;
|
||||
}
|
||||
break;
|
||||
case CANSID_BRACKET:
|
||||
if (x == '[')
|
||||
state->state = CANSID_PARSE;
|
||||
else {
|
||||
state->state = CANSID_ESC;
|
||||
rv.ascii = x;
|
||||
}
|
||||
break;
|
||||
case CANSID_PARSE:
|
||||
if (x == '3') {
|
||||
state->state = CANSID_FGCOLOR;
|
||||
} else if (x == '4') {
|
||||
state->state = CANSID_BGCOLOR;
|
||||
} else if (x == '0') {
|
||||
state->state = CANSID_ENDVAL;
|
||||
state->next_style = 0x0F;
|
||||
} else if (x == '1') {
|
||||
state->state = CANSID_ENDVAL;
|
||||
state->next_style |= (1 << 3);
|
||||
} else if (x == '=') {
|
||||
state->state = CANSID_EQUALS;
|
||||
} else {
|
||||
state->state = CANSID_ESC;
|
||||
state->next_style = state->style;
|
||||
rv.ascii = x;
|
||||
}
|
||||
break;
|
||||
case CANSID_BGCOLOR:
|
||||
if (x >= '0' && x <= '7') {
|
||||
state->state = CANSID_ENDVAL;
|
||||
state->next_style &= 0x1F;
|
||||
state->next_style |= cansid_convert_color(x - '0') << 4;
|
||||
} else {
|
||||
state->state = CANSID_ESC;
|
||||
state->next_style = state->style;
|
||||
rv.ascii = x;
|
||||
}
|
||||
break;
|
||||
case CANSID_FGCOLOR:
|
||||
if (x >= '0' && x <= '7') {
|
||||
state->state = CANSID_ENDVAL;
|
||||
state->next_style &= 0xF8;
|
||||
state->next_style |= cansid_convert_color(x - '0');
|
||||
} else {
|
||||
state->state = CANSID_ESC;
|
||||
state->next_style = state->style;
|
||||
rv.ascii = x;
|
||||
}
|
||||
break;
|
||||
case CANSID_EQUALS:
|
||||
if (x == '1') {
|
||||
state->state = CANSID_ENDVAL;
|
||||
state->next_style &= ~(1 << 3);
|
||||
} else {
|
||||
state->state = CANSID_ESC;
|
||||
state->next_style = state->style;
|
||||
rv.ascii = x;
|
||||
}
|
||||
break;
|
||||
case CANSID_ENDVAL:
|
||||
if (x == ';') {
|
||||
state->state = CANSID_PARSE;
|
||||
} else if (x == 'm') {
|
||||
// Finish and apply styles
|
||||
state->state = CANSID_ESC;
|
||||
state->style = state->next_style;
|
||||
} else {
|
||||
state->state = CANSID_ESC;
|
||||
state->next_style = state->style;
|
||||
rv.ascii = x;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return rv;
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
#ifndef CANSID_H
|
||||
#define CANSID_H
|
||||
|
||||
struct cansid_state {
|
||||
enum {
|
||||
CANSID_ESC,
|
||||
CANSID_BRACKET,
|
||||
CANSID_PARSE,
|
||||
CANSID_BGCOLOR,
|
||||
CANSID_FGCOLOR,
|
||||
CANSID_EQUALS,
|
||||
CANSID_ENDVAL,
|
||||
} state;
|
||||
unsigned char style;
|
||||
unsigned char next_style;
|
||||
};
|
||||
|
||||
struct color_char {
|
||||
unsigned char style;
|
||||
unsigned char ascii;
|
||||
};
|
||||
|
||||
struct cansid_state cansid_init(void);
|
||||
struct color_char cansid_process(struct cansid_state *state, char x);
|
||||
|
||||
#endif
|
@ -3,37 +3,39 @@
|
||||
#include "ports.h"
|
||||
#include <string.h>
|
||||
#include <stddef.h>
|
||||
#include "cansid.h"
|
||||
#include "vtconsole.h"
|
||||
#define xy_to_indx(x,y) ((x+(y*width))*2)
|
||||
static vga_color colors[]={VGA_BLACK,VGA_RED,VGA_GREEN,VGA_BROWN,
|
||||
VGA_BLUE,VGA_PURPLE,VGA_CYAN,VGA_WHITE};
|
||||
static char* screen;
|
||||
static int width;
|
||||
static int height;
|
||||
static int x;
|
||||
static int y;
|
||||
static vga_colors fg_color;
|
||||
static vga_colors bg_color;
|
||||
static char* scroll_buf[0xfa0];
|
||||
|
||||
static struct cansid_state state;
|
||||
static vtconsole_t* console;
|
||||
|
||||
static void set_char(int x,int y,struct color_char ch) {
|
||||
screen[xy_to_indx(x,y)]=ch.ascii;
|
||||
screen[xy_to_indx(x,y)+1]=ch.style;
|
||||
static void set_char(int x,int y,char ch,char style) {
|
||||
screen[xy_to_indx(x,y)]=ch;
|
||||
screen[xy_to_indx(x,y)+1]=style;
|
||||
}
|
||||
|
||||
static void vt_set_char(struct vtconsole* vtc, vtcell_t* cell, int x, int y) {
|
||||
vga_color fg_color=colors[cell->attr.fg];
|
||||
vga_color bg_color=colors[cell->attr.bg];
|
||||
char style=(fg_color&0xF)|((bg_color&0xF)<<4);
|
||||
style=style|((cell->attr.bright&0x1)<<7);
|
||||
set_char(x,y,cell->c,style);
|
||||
}
|
||||
|
||||
void vga_clear() {
|
||||
for (int y=0;y<height;y++) {
|
||||
for (int x=0;x<width;x++) {
|
||||
struct color_char ch;
|
||||
ch.ascii=' ';
|
||||
ch.style=0;
|
||||
set_char(x,y,ch);
|
||||
set_char(x,y,' ',0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void set_cursor(int x,int y) {
|
||||
int pos=(x+(y*width));
|
||||
static void set_cursor(struct vtconsole* vtc, vtcursor_t* cur) {
|
||||
int pos=(cur->x+(cur->y*width));
|
||||
port_byte_out(0x3D4,0xF);
|
||||
port_byte_out(0x3D5,pos&0xFF);
|
||||
port_byte_out(0x3D4,0xE);
|
||||
@ -41,56 +43,21 @@ static void set_cursor(int x,int y) {
|
||||
}
|
||||
|
||||
void vga_init(text_fb_info framebuffer_info) {
|
||||
x=0;
|
||||
y=0;
|
||||
fg_color=VGA_WHITE;
|
||||
bg_color=VGA_BLACK;
|
||||
state=cansid_init();
|
||||
screen=framebuffer_info.address;
|
||||
width=framebuffer_info.width;
|
||||
height=framebuffer_info.height;
|
||||
console=vtconsole(width,height,vt_set_char,set_cursor);
|
||||
port_byte_out(0x3D4,0xA);
|
||||
port_byte_out(0x3D5,(port_byte_in(0x3D5)&0xC0)|14);
|
||||
port_byte_out(0x3D4,0xB);
|
||||
port_byte_out(0x3D5,(port_byte_in(0x3D5)&0xE0)|15);
|
||||
set_cursor(0,0);
|
||||
vtcursor_t cur;
|
||||
cur.x=0;
|
||||
cur.y=0;
|
||||
set_cursor(NULL,&cur);
|
||||
vga_clear();
|
||||
}
|
||||
|
||||
void vga_write_string(const char* string) {
|
||||
for (size_t i=0;i<strlen(string);i++) {
|
||||
char c=string[i];
|
||||
if (c=='\n') {
|
||||
x=0;
|
||||
y++;
|
||||
} else {
|
||||
struct color_char ch=cansid_process(&state,c);
|
||||
if (ch.ascii) {
|
||||
set_char(x,y,ch);
|
||||
x++;
|
||||
}
|
||||
}
|
||||
if (x==width) {
|
||||
x=0;
|
||||
y++;
|
||||
}
|
||||
if (y==height) {
|
||||
x=0;
|
||||
y=24;
|
||||
memcpy(scroll_buf,&screen[xy_to_indx(0,1)],xy_to_indx(0,24));
|
||||
vga_clear();
|
||||
memcpy(screen,scroll_buf,xy_to_indx(0,25));
|
||||
}
|
||||
}
|
||||
set_cursor(x,y);
|
||||
}
|
||||
|
||||
void vga_backspace() {
|
||||
if (x!=0) {
|
||||
x--;
|
||||
struct color_char ch;
|
||||
ch.ascii=' ';
|
||||
ch.style=0;
|
||||
set_char(x,y,ch);
|
||||
}
|
||||
vtconsole_write(console,string,strlen(string));
|
||||
}
|
||||
|
@ -10,15 +10,8 @@ typedef enum {
|
||||
VGA_PURPLE=5,
|
||||
VGA_BROWN=6,
|
||||
VGA_GRAY=7,
|
||||
VGA_DARK_GRAY=8,
|
||||
VGA_LIGHT_BLUE=9,
|
||||
VGA_LIGHT_GREEN=10,
|
||||
VGA_LIGHT_CYAN=11,
|
||||
VGA_LIGHT_RED=12,
|
||||
VGA_LIGHT_PURPLE=13,
|
||||
VGA_YELLOW=14,
|
||||
VGA_WHITE=15
|
||||
} vga_colors;
|
||||
} vga_color;
|
||||
|
||||
|
||||
void vga_init();
|
||||
|
422
vga_drv/vtconsole.c
Executable file
422
vga_drv/vtconsole.c
Executable file
@ -0,0 +1,422 @@
|
||||
#include "vtconsole.h"
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#define min(a, b) ((a) < (b) ? (a) : (b))
|
||||
|
||||
|
||||
/* --- Constructor/Destructor ----------------------------------------------- */
|
||||
|
||||
vtconsole_t *vtconsole(int width, int height, vtc_paint_handler_t on_paint, vtc_cursor_handler_t on_move)
|
||||
{
|
||||
vtconsole_t *vtc = malloc(sizeof(vtconsole_t));
|
||||
|
||||
vtc->width = width;
|
||||
vtc->height = height;
|
||||
|
||||
vtc->ansiparser = (vtansi_parser_t){VTSTATE_ESC, {{0, 0}}, 0};
|
||||
vtc->attr = VTC_DEFAULT_ATTR;
|
||||
|
||||
vtc->buffer = malloc(width * height * sizeof(vtcell_t));
|
||||
|
||||
vtc->cursor = (vtcursor_t){0, 0};
|
||||
|
||||
vtc->on_paint = on_paint;
|
||||
vtc->on_move = on_move;
|
||||
|
||||
vtconsole_clear(vtc, 0, 0, width, height - 1);
|
||||
|
||||
return vtc;
|
||||
}
|
||||
|
||||
void vtconsole_delete(vtconsole_t *vtc)
|
||||
{
|
||||
free(vtc->buffer);
|
||||
free(vtc);
|
||||
}
|
||||
|
||||
/* --- Internal methodes ---------------------------------------------------- */
|
||||
|
||||
void vtconsole_clear(vtconsole_t *vtc, int fromx, int fromy, int tox, int toy)
|
||||
{
|
||||
for (int i = fromx + fromy * vtc->width; i < tox + toy * vtc->width; i++)
|
||||
{
|
||||
vtcell_t *cell = &vtc->buffer[i];
|
||||
|
||||
cell->attr = VTC_DEFAULT_ATTR;
|
||||
cell->c = ' ';
|
||||
|
||||
if (vtc->on_paint)
|
||||
{
|
||||
vtc->on_paint(vtc, cell, i % vtc->width, i / vtc->width);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void vtconsole_scroll(vtconsole_t *vtc, int lines)
|
||||
{
|
||||
if (lines == 0) return;
|
||||
|
||||
lines = lines > vtc->height ? vtc->height : lines;
|
||||
|
||||
// Scroll the screen by number of $lines.
|
||||
for (int i = 0; i < ((vtc->width * vtc->height) - (vtc->width * lines)); i++)
|
||||
{
|
||||
vtc->buffer[i] = vtc->buffer[i + (vtc->width * lines)];
|
||||
|
||||
if (vtc->on_paint)
|
||||
{
|
||||
vtc->on_paint(vtc, &vtc->buffer[i], i % vtc->width, i / vtc->width);
|
||||
}
|
||||
}
|
||||
|
||||
// Clear the last $lines.
|
||||
for (int i = ((vtc->width * vtc->height) - (vtc->width * lines)); i < vtc->width * vtc->height; i++)
|
||||
{
|
||||
vtcell_t *cell = &vtc->buffer[i];
|
||||
cell->attr = VTC_DEFAULT_ATTR;
|
||||
cell->c = ' ';
|
||||
|
||||
if (vtc->on_paint)
|
||||
{
|
||||
vtc->on_paint(vtc, &vtc->buffer[i], i % vtc->width, i / vtc->width);
|
||||
}
|
||||
}
|
||||
|
||||
// Move the cursor up $lines
|
||||
if (vtc->cursor.y > 0)
|
||||
{
|
||||
vtc->cursor.y -= lines;
|
||||
|
||||
if (vtc->cursor.y < 0) vtc->cursor.y = 0;
|
||||
|
||||
if (vtc->on_move)
|
||||
{
|
||||
vtc->on_move(vtc, &vtc->cursor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Append a new line
|
||||
void vtconsole_newline(vtconsole_t *vtc)
|
||||
{
|
||||
vtc->cursor.x = 0;
|
||||
vtc->cursor.y++;
|
||||
|
||||
if (vtc->cursor.y == vtc->height)
|
||||
{
|
||||
vtconsole_scroll(vtc, 1);
|
||||
}
|
||||
|
||||
if (vtc->on_move)
|
||||
{
|
||||
vtc->on_move(vtc, &vtc->cursor);
|
||||
}
|
||||
}
|
||||
|
||||
// Append character to the console buffer.
|
||||
void vtconsole_append(vtconsole_t *vtc, char c)
|
||||
{
|
||||
if (c == '\n')
|
||||
{
|
||||
vtconsole_newline(vtc);
|
||||
}
|
||||
else if (c == '\r')
|
||||
{
|
||||
vtc->cursor.x = 0;
|
||||
|
||||
if (vtc->on_move)
|
||||
{
|
||||
vtc->on_move(vtc, &vtc->cursor);
|
||||
}
|
||||
}
|
||||
else if (c == '\t')
|
||||
{
|
||||
int n = 8 - (vtc->cursor.x % 8);
|
||||
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
vtconsole_append(vtc, ' ');
|
||||
}
|
||||
}
|
||||
else if (c == '\b')
|
||||
{
|
||||
if (vtc->cursor.x > 0)
|
||||
{
|
||||
vtc->cursor.x--;
|
||||
}
|
||||
else
|
||||
{
|
||||
vtc->cursor.y--;
|
||||
vtc->cursor.x = vtc->width - 1;
|
||||
}
|
||||
|
||||
if (vtc->on_move)
|
||||
{
|
||||
vtc->on_move(vtc, &vtc->cursor);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (vtc->cursor.x >= vtc->width)
|
||||
vtconsole_newline(vtc);
|
||||
|
||||
vtcell_t *cell = &vtc->buffer[vtc->cursor.x + vtc->cursor.y * vtc->width];
|
||||
cell->c = c;
|
||||
cell->attr = vtc->attr;
|
||||
|
||||
if (vtc->on_paint)
|
||||
{
|
||||
vtc->on_paint(vtc, cell, vtc->cursor.x, vtc->cursor.y);
|
||||
}
|
||||
|
||||
vtc->cursor.x++;
|
||||
|
||||
if (vtc->on_move)
|
||||
{
|
||||
vtc->on_move(vtc, &vtc->cursor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Moves the cursor to row n, column m. The values are 1-based,
|
||||
void vtconsole_csi_cup(vtconsole_t *vtc, vtansi_arg_t *stack, int count)
|
||||
{
|
||||
if (count == 1 && stack[0].empty)
|
||||
{
|
||||
vtc->cursor.x = 0;
|
||||
vtc->cursor.y = 0;
|
||||
}
|
||||
else if (count == 2)
|
||||
{
|
||||
if (stack[0].empty)
|
||||
{
|
||||
vtc->cursor.y = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
vtc->cursor.y = min(stack[0].value - 1, vtc->height - 1);
|
||||
}
|
||||
|
||||
if (stack[1].empty)
|
||||
{
|
||||
vtc->cursor.y = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
vtc->cursor.x = min(stack[1].value - 1, vtc->width - 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (vtc->on_move)
|
||||
{
|
||||
vtc->on_move(vtc, &vtc->cursor);
|
||||
}
|
||||
}
|
||||
|
||||
// Clears part of the screen.
|
||||
void vtconsole_csi_ed(vtconsole_t *vtc, vtansi_arg_t *stack, int count)
|
||||
{
|
||||
(void)(count);
|
||||
|
||||
vtcursor_t cursor = vtc->cursor;
|
||||
|
||||
if (stack[0].empty)
|
||||
{
|
||||
vtconsole_clear(vtc, cursor.x, cursor.y, vtc->width, vtc->height - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
int attr = stack[0].value;
|
||||
|
||||
if (attr == 0)
|
||||
vtconsole_clear(vtc, cursor.x, cursor.y, vtc->width, vtc->height - 1);
|
||||
else if (attr == 1)
|
||||
vtconsole_clear(vtc, 0, 0, cursor.x, cursor.y);
|
||||
else if (attr == 2)
|
||||
vtconsole_clear(vtc, 0, 0, vtc->width, vtc->height - 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Erases part of the line.
|
||||
void vtconsole_csi_el(vtconsole_t *vtc, vtansi_arg_t *stack, int count)
|
||||
{
|
||||
(void)(count);
|
||||
|
||||
vtcursor_t cursor = vtc->cursor;
|
||||
|
||||
if (stack[0].empty)
|
||||
{
|
||||
vtconsole_clear(vtc, cursor.x, cursor.y, vtc->width, cursor.y);
|
||||
}
|
||||
else
|
||||
{
|
||||
int attr = stack[0].value;
|
||||
|
||||
if (attr == 0)
|
||||
vtconsole_clear(vtc, cursor.x, cursor.y, vtc->width, cursor.y);
|
||||
else if (attr == 1)
|
||||
vtconsole_clear(vtc, 0, cursor.y, cursor.x, cursor.y);
|
||||
else if (attr == 2)
|
||||
vtconsole_clear(vtc, 0, cursor.y, vtc->width, cursor.y);
|
||||
}
|
||||
}
|
||||
|
||||
// Sets the appearance of the following characters
|
||||
void vtconsole_csi_sgr(vtconsole_t *vtc, vtansi_arg_t *stack, int count)
|
||||
{
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
if (stack[i].empty || stack[i].value == 0)
|
||||
{
|
||||
vtc->attr = VTC_DEFAULT_ATTR;
|
||||
}
|
||||
else
|
||||
{
|
||||
int attr = stack[i].value;
|
||||
|
||||
if (attr == 1) // Increased intensity
|
||||
{
|
||||
vtc->attr.bright = true;
|
||||
}
|
||||
else if (attr >= 30 && attr <= 37) // Set foreground color
|
||||
{
|
||||
vtc->attr.fg = attr - 30;
|
||||
}
|
||||
else if (attr >= 40 && attr <= 47) // Set background color
|
||||
{
|
||||
vtc->attr.bg = attr - 40;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Process ANSI escape sequences and append character to the console buffer.
|
||||
void vtconsole_process(vtconsole_t *vtc, char c)
|
||||
{
|
||||
vtansi_parser_t *parser = &vtc->ansiparser;
|
||||
|
||||
switch (parser->state)
|
||||
{
|
||||
case VTSTATE_ESC:
|
||||
if (c == '\033')
|
||||
{
|
||||
parser->state = VTSTATE_BRACKET;
|
||||
|
||||
parser->index = 0;
|
||||
|
||||
parser->stack[parser->index].value = 0;
|
||||
parser->stack[parser->index].empty = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
parser->state = VTSTATE_ESC;
|
||||
vtconsole_append(vtc, c);
|
||||
}
|
||||
break;
|
||||
|
||||
case VTSTATE_BRACKET:
|
||||
if (c == '[')
|
||||
{
|
||||
parser->state = VTSTATE_ATTR;
|
||||
}
|
||||
else
|
||||
{
|
||||
parser->state = VTSTATE_ESC;
|
||||
vtconsole_append(vtc, c);
|
||||
}
|
||||
break;
|
||||
case VTSTATE_ATTR:
|
||||
if (isdigit(c))
|
||||
{
|
||||
parser->stack[parser->index].value *= 10;
|
||||
parser->stack[parser->index].value += (c - '0');
|
||||
parser->stack[parser->index].empty = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((parser->index) < VTC_ANSI_PARSER_STACK_SIZE)
|
||||
{
|
||||
parser->index++;
|
||||
}
|
||||
|
||||
parser->stack[parser->index].value = 0;
|
||||
parser->stack[parser->index].empty = true;
|
||||
|
||||
parser->state = VTSTATE_ENDVAL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (parser->state == VTSTATE_ENDVAL)
|
||||
{
|
||||
if (c == ';')
|
||||
{
|
||||
parser->state = VTSTATE_ATTR;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case 'A':
|
||||
/* Cursor up P1 rows */
|
||||
break;
|
||||
case 'B':
|
||||
/* Cursor down P1 rows */
|
||||
break;
|
||||
|
||||
case 'C':
|
||||
/* Cursor right P1 columns */
|
||||
break;
|
||||
case 'D':
|
||||
/* Cursor left P1 columns */
|
||||
break;
|
||||
|
||||
case 'E':
|
||||
/* Cursor to first column of line P1 rows down from current */
|
||||
break;
|
||||
case 'F':
|
||||
/* Cursor to first column of line P1 rows up from current */
|
||||
break;
|
||||
|
||||
case 'G':
|
||||
/* Cursor to column P1 */
|
||||
break;
|
||||
case 'd':
|
||||
/* Cursor left P1 columns */
|
||||
break;
|
||||
|
||||
case 'H':
|
||||
vtconsole_csi_cup(vtc, parser->stack, parser->index);
|
||||
break;
|
||||
case 'J':
|
||||
vtconsole_csi_ed(vtc, parser->stack, parser->index);
|
||||
break;
|
||||
case 'K':
|
||||
vtconsole_csi_el(vtc, parser->stack, parser->index);
|
||||
break;
|
||||
case 'm':
|
||||
vtconsole_csi_sgr(vtc, parser->stack, parser->index);
|
||||
break;
|
||||
}
|
||||
|
||||
parser->state = VTSTATE_ESC;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* --- Methodes ------------------------------------------------------------- */
|
||||
|
||||
void vtconsole_putchar(vtconsole_t *vtc, char c)
|
||||
{
|
||||
vtconsole_process(vtc, c);
|
||||
}
|
||||
|
||||
void vtconsole_write(vtconsole_t *vtc, const char *buffer, unsigned int size)
|
||||
{
|
||||
for (unsigned int i = 0; i < size; i++)
|
||||
{
|
||||
vtconsole_process(vtc, buffer[i]);
|
||||
}
|
||||
}
|
91
vga_drv/vtconsole.h
Executable file
91
vga_drv/vtconsole.h
Executable file
@ -0,0 +1,91 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#define VTC_DEFAULT_FOREGROUND VTCOLOR_GREY
|
||||
#define VTC_DEFAULT_BACKGROUND VTCOLOR_BLACK
|
||||
#define VTC_DEFAULT_ATTR (vtattr_t){ false, VTC_DEFAULT_FOREGROUND, VTC_DEFAULT_BACKGROUND }
|
||||
#define VTC_ANSI_PARSER_STACK_SIZE 8
|
||||
|
||||
struct vtconsole;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
VTCOLOR_BLACK,
|
||||
VTCOLOR_RED,
|
||||
VTCOLOR_GREEN,
|
||||
VTCOLOR_YELLOW,
|
||||
VTCOLOR_BLUE,
|
||||
VTCOLOR_MAGENTA,
|
||||
VTCOLOR_CYAN,
|
||||
VTCOLOR_GREY,
|
||||
} vtcolor_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
VTSTATE_ESC,
|
||||
VTSTATE_BRACKET,
|
||||
VTSTATE_ATTR,
|
||||
VTSTATE_ENDVAL,
|
||||
} vtansi_parser_state_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int value;
|
||||
bool empty;
|
||||
} vtansi_arg_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
vtansi_parser_state_t state;
|
||||
vtansi_arg_t stack[VTC_ANSI_PARSER_STACK_SIZE];
|
||||
int index;
|
||||
} vtansi_parser_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
bool bright;
|
||||
vtcolor_t fg;
|
||||
vtcolor_t bg;
|
||||
} vtattr_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char c;
|
||||
vtattr_t attr;
|
||||
} vtcell_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
} vtcursor_t;
|
||||
|
||||
typedef void (*vtc_paint_handler_t)(struct vtconsole* vtc, vtcell_t* cell, int x, int y);
|
||||
typedef void (*vtc_cursor_handler_t)(struct vtconsole* vtc, vtcursor_t* cur);
|
||||
|
||||
typedef struct vtconsole
|
||||
{
|
||||
|
||||
int width;
|
||||
int height;
|
||||
|
||||
vtattr_t attr;
|
||||
vtansi_parser_t ansiparser;
|
||||
|
||||
vtcell_t *buffer;
|
||||
vtcursor_t cursor;
|
||||
|
||||
vtc_paint_handler_t on_paint;
|
||||
vtc_cursor_handler_t on_move;
|
||||
} vtconsole_t;
|
||||
|
||||
vtconsole_t* vtconsole(int width, int height, vtc_paint_handler_t on_paint, vtc_cursor_handler_t on_move);
|
||||
void vtconsole_delete(vtconsole_t *c);
|
||||
|
||||
void vtconsole_clear(vtconsole_t *vtc, int fromx, int fromy, int tox, int toy);
|
||||
void vtconsole_scroll(vtconsole_t *vtc, int lines);
|
||||
void vtconsole_newline(vtconsole_t *vtc);
|
||||
|
||||
void vtconsole_putchar(vtconsole_t *vtc, char c);
|
||||
void vtconsole_write(vtconsole_t *vtc, const char *buffer, unsigned int size);
|
Loading…
x
Reference in New Issue
Block a user