Fix color support to work everywhere via hacky static variable

This commit is contained in:
Danila Fedorin 2019-04-05 19:20:33 -07:00
parent f00ab71fb5
commit 47a176223b
5 changed files with 84 additions and 56 deletions

View File

@ -17,6 +17,7 @@ KERN_SRCFILES := kern/entry.S \
kern/entrypgdir.c \ kern/entrypgdir.c \
kern/init.c \ kern/init.c \
kern/console.c \ kern/console.c \
kern/ansi.c \
kern/monitor.c \ kern/monitor.c \
kern/pmap.c \ kern/pmap.c \
kern/env.c \ kern/env.c \

49
kern/ansi.c Normal file
View File

@ -0,0 +1,49 @@
#include <kern/ansi.h>
uint8_t vga_colors[8] = {
[0] = 0,
[1] = 4,
[2] = 2,
[3] = 6,
[4] = 1,
[5] = 5,
[6] = 3,
[7] = 7
};
void
ansi_step(void (*putcf)(int), int c, struct AttrState* s) {
switch(s->state) {
case NORMAL:
if(c != 27) putcf(c | (s->cattrs << 8));
else s->state = ESC;
return;
case ESC:
s->state = (c == '[') ? BRACKET : NORMAL;
return;
case BRACKET:
if(c == '3') {
s->state = COLOR_FG;
} else if(c == '0') {
s->state = COLOR;
s->attrs = 0;
} else {
s->state = NORMAL;
}
return;
case COLOR_FG:
if(c >= '0' && c <= '9') {
s->attrs = (s->attrs & ~(0x07)) | vga_colors[c - '0'];
c |= ((c - '0') << 8);
s->state = COLOR;
} else {
s->state = NORMAL;
}
return;
case COLOR:
s->state = (c == ';') ? BRACKET : NORMAL;
if(c == 'm') s->cattrs = s->attrs;
return;
}
}

20
kern/ansi.h Normal file
View File

@ -0,0 +1,20 @@
#ifndef _ANSI_H_
#define _ANSI_H_
#include <inc/types.h>
struct AttrState {
uint8_t cattrs;
uint8_t attrs;
enum {
NORMAL,
ESC,
BRACKET,
COLOR_FG,
COLOR
} state;
};
void ansi_step(void (*putcf)(int), int c, struct AttrState* s);
#endif

View File

@ -7,6 +7,7 @@
#include <inc/assert.h> #include <inc/assert.h>
#include <kern/console.h> #include <kern/console.h>
#include <kern/ansi.h>
static void cons_intr(int (*proc)(void)); static void cons_intr(int (*proc)(void));
static void cons_putc(int c); static void cons_putc(int c);
@ -128,6 +129,7 @@ lpt_putc(int c)
static unsigned addr_6845; static unsigned addr_6845;
static uint16_t *crt_buf; static uint16_t *crt_buf;
static uint16_t crt_pos; static uint16_t crt_pos;
static struct AttrState attst;
static void static void
cga_init(void) cga_init(void)
@ -136,6 +138,10 @@ cga_init(void)
uint16_t was; uint16_t was;
unsigned pos; unsigned pos;
attst.cattrs = 0;
attst.attrs = 0;
attst.state = NORMAL;
cp = (uint16_t*) (KERNBASE + CGA_BUF); cp = (uint16_t*) (KERNBASE + CGA_BUF);
was = *cp; was = *cp;
*cp = (uint16_t) 0xA55A; *cp = (uint16_t) 0xA55A;
@ -157,10 +163,15 @@ cga_init(void)
crt_pos = pos; crt_pos = pos;
} }
static void cga_putc_internal(int c);
static void static void
cga_putc(int c) cga_putc(int c){
ansi_step(cga_putc_internal, c, &attst);
}
static void
cga_putc_internal(int c)
{ {
// if no attribute given, then use black on white // if no attribute given, then use black on white
if (!(c & ~0xFF)) if (!(c & ~0xFF))

View File

@ -79,54 +79,6 @@ getint(va_list *ap, int lflag)
// Main function to format and print a string. // Main function to format and print a string.
void printfmt(void (*putch)(int, void*), void *putdat, const char *fmt, ...); void printfmt(void (*putch)(int, void*), void *putdat, const char *fmt, ...);
struct AttrState {
uint8_t cattrs;
uint8_t attrs;
enum {
NORMAL,
ESC,
BRACKET,
COLOR_FG,
COLOR
} state;
};
void
putchw(void (*putch)(int, void*), int c, void* data, struct AttrState* s) {
switch(s->state) {
case NORMAL:
if(c != 27) putch(c | (s->cattrs << 8), data);
else s->state = ESC;
return;
case ESC:
s->state = (c == '[') ? BRACKET : NORMAL;
return;
case BRACKET:
if(c == '3') {
s->state = COLOR_FG;
} else if(c == '0') {
s->state = COLOR;
s->attrs = 0;
} else {
s->state = NORMAL;
}
return;
case COLOR_FG:
if(c >= '0' && c <= '9') {
s->attrs = (s->attrs & ~(0x07)) | (c - '0');
c |= ((c - '0') << 8);
s->state = COLOR;
} else {
s->state = NORMAL;
}
return;
case COLOR:
s->state = (c == ';') ? BRACKET : NORMAL;
if(c == 'm') s->cattrs = s->attrs;
return;
}
}
void void
vprintfmt(void (*putch)(int, void*), void *putdat, const char *fmt, va_list ap) vprintfmt(void (*putch)(int, void*), void *putdat, const char *fmt, va_list ap)
{ {
@ -135,17 +87,12 @@ vprintfmt(void (*putch)(int, void*), void *putdat, const char *fmt, va_list ap)
unsigned long long num; unsigned long long num;
int base, lflag, width, precision, altflag; int base, lflag, width, precision, altflag;
char padc; char padc;
struct AttrState attst;
attst.state = NORMAL;
attst.cattrs = 0;
attst.attrs = 0;
while (1) { while (1) {
while ((ch = *(unsigned char *) fmt++) != '%') { while ((ch = *(unsigned char *) fmt++) != '%') {
if (ch == '\0') if (ch == '\0')
return; return;
putchw(putch, ch, putdat, &attst); putch(ch, putdat);
} }
// Process a %-escape sequence // Process a %-escape sequence