From 47a176223bc1630f27d3289afa3c98697596c6ba Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Fri, 5 Apr 2019 19:20:33 -0700 Subject: [PATCH] Fix color support to work everywhere via hacky static variable --- kern/Makefrag | 1 + kern/ansi.c | 49 ++++++++++++++++++++++++++++++++++++++++++++ kern/ansi.h | 20 ++++++++++++++++++ kern/console.c | 15 ++++++++++++-- lib/printfmt.c | 55 +------------------------------------------------- 5 files changed, 84 insertions(+), 56 deletions(-) create mode 100644 kern/ansi.c create mode 100644 kern/ansi.h diff --git a/kern/Makefrag b/kern/Makefrag index 3b2982e..458dd57 100644 --- a/kern/Makefrag +++ b/kern/Makefrag @@ -17,6 +17,7 @@ KERN_SRCFILES := kern/entry.S \ kern/entrypgdir.c \ kern/init.c \ kern/console.c \ + kern/ansi.c \ kern/monitor.c \ kern/pmap.c \ kern/env.c \ diff --git a/kern/ansi.c b/kern/ansi.c new file mode 100644 index 0000000..c90057e --- /dev/null +++ b/kern/ansi.c @@ -0,0 +1,49 @@ +#include + +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; + } +} + diff --git a/kern/ansi.h b/kern/ansi.h new file mode 100644 index 0000000..970f9c6 --- /dev/null +++ b/kern/ansi.h @@ -0,0 +1,20 @@ +#ifndef _ANSI_H_ +#define _ANSI_H_ + +#include + +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 diff --git a/kern/console.c b/kern/console.c index 7d312a7..8019dad 100644 --- a/kern/console.c +++ b/kern/console.c @@ -7,6 +7,7 @@ #include #include +#include static void cons_intr(int (*proc)(void)); static void cons_putc(int c); @@ -128,6 +129,7 @@ lpt_putc(int c) static unsigned addr_6845; static uint16_t *crt_buf; static uint16_t crt_pos; +static struct AttrState attst; static void cga_init(void) @@ -136,6 +138,10 @@ cga_init(void) uint16_t was; unsigned pos; + attst.cattrs = 0; + attst.attrs = 0; + attst.state = NORMAL; + cp = (uint16_t*) (KERNBASE + CGA_BUF); was = *cp; *cp = (uint16_t) 0xA55A; @@ -157,10 +163,15 @@ cga_init(void) crt_pos = pos; } - +static void cga_putc_internal(int c); 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 (!(c & ~0xFF)) diff --git a/lib/printfmt.c b/lib/printfmt.c index 7535e93..b1de635 100644 --- a/lib/printfmt.c +++ b/lib/printfmt.c @@ -79,54 +79,6 @@ getint(va_list *ap, int lflag) // Main function to format and print a string. 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 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; int base, lflag, width, precision, altflag; char padc; - struct AttrState attst; - - attst.state = NORMAL; - attst.cattrs = 0; - attst.attrs = 0; while (1) { while ((ch = *(unsigned char *) fmt++) != '%') { if (ch == '\0') return; - putchw(putch, ch, putdat, &attst); + putch(ch, putdat); } // Process a %-escape sequence