diff --git a/cucul/import.c b/cucul/import.c index 25a061b..57e1950 100644 --- a/cucul/import.c +++ b/cucul/import.c @@ -29,6 +29,7 @@ static cucul_canvas_t *import_caca(void const *, unsigned int); static cucul_canvas_t *import_text(void const *, unsigned int); +static cucul_canvas_t *import_ansi(void const *, unsigned int); /** \brief Import a buffer into a canvas * @@ -48,15 +49,34 @@ static cucul_canvas_t *import_text(void const *, unsigned int); cucul_canvas_t * cucul_import_canvas(void const *data, unsigned int size, char const *format) { + char const *buf = (char const*) data; + + if(size==0 || data==NULL) + return NULL; + if(!strcasecmp("caca", format)) return import_caca(data, size); if(!strcasecmp("text", format)) return import_text(data, size); + if(!strcasecmp("ansi", format)) + return import_ansi(data, size); - /* FIXME: Try to autodetect */ if(!strcasecmp("", format)) - return import_caca(data, size); - + { + /* Autodetection */ + if(size>=4) /* if 4 first letters are CACA */ + { + if(buf[0] == 'C' && buf[1] == 'A' && buf[2] == 'C' && buf[3] != 'A') + return import_caca(data, size); + } + if(size>=2) /* If 2 first characters are ESC[ (not reliable at all) */ + { + if((buf[0] == 0x1b) && (buf[1] == '[')) + return import_ansi(data, size); + } + /* Otherwise, import it as text */ + return import_caca(data, size); + } return NULL; } @@ -76,6 +96,7 @@ char const * const * cucul_get_import_list(void) "", "autodetect", "text", "plain text", "caca", "native libcaca format", + "ansi", "ANSI coloured text", NULL, NULL }; @@ -174,3 +195,355 @@ static cucul_canvas_t *import_text(void const *data, unsigned int size) return cv; } +#define IS_ALPHA(x) (x>='A' && x<='z') +void updateCanvasSize(cucul_canvas_t *cv, int x, int y, int *max_x, int *max_y); +unsigned char get_ansi_command(unsigned char const *buffer, int size); +int parse_tuple(unsigned int *ret, unsigned char const *buffer, int size); +void manage_modifiers(char c, int *fg, int *bg, int *old_fg, int *old_bg); + +static cucul_canvas_t *import_ansi(void const *data, unsigned int size) +{ + cucul_canvas_t *cv; + unsigned char const *buffer = (unsigned char const*)data; + unsigned int i, sent_size=0; + unsigned char c; + unsigned int count=0; + unsigned int tuple[1024]; /* Should be enough. Will it be ? */ + int x=0, y=0, max_x = 80, max_y = 25; + int save_x=0, save_y=0; + unsigned int j, add=0; + int fg, bg, old_fg, old_bg; + + fg = old_fg = CUCUL_COLOR_LIGHTGRAY; + bg = old_bg = CUCUL_COLOR_BLACK; + + cv = cucul_create_canvas(max_x, max_y); + + for(i = 0 ;i < size; i++) + { + if((buffer[i] == 0x1b) && (buffer[i+1] == '[')) /* ESC code */ + { + i++; // ESC + i++; // [ + sent_size = size-i; + c = get_ansi_command(&buffer[i], sent_size); + add = parse_tuple(tuple, &buffer[i], sent_size); + count = 0; + + while(tuple[count] != 0x1337) count++; /* Gruik */ + + + switch(c) + { + case 'f': + case 'H': + if(tuple[0] != 0x1337) + { + x=tuple[0]; + if(tuple[1] != 0x1337) + y=tuple[1]; + } + else + { + x = 0; + y = 0; + } + updateCanvasSize(cv, x, y, &max_x, &max_y); + break; + case 'A': + if(tuple[0] == 0x1337) + y-=1; + else + y-=tuple[0]; + if(y<0) y=0; + updateCanvasSize(cv, x, y, &max_x, &max_y); + break; + case 'B': + if(tuple[0] == 0x1337) + y++; + else + y+=tuple[0]; + updateCanvasSize(cv, x, y, &max_x, &max_y); + break; + case 'C': + if(tuple[0] == 0x1337) + x++; + else + x+=tuple[0]; + updateCanvasSize(cv, x, y, &max_x, &max_y); + break; + case 'D': + if(tuple[0] == 0x1337) + x--; + else + x-=tuple[0]; + if(x<0) x=0; + updateCanvasSize(cv, x, y, &max_x, &max_y); + break; + case 's': + save_x = x; + save_y = y; + break; + case 'u': + x = save_x; + y = save_y; + updateCanvasSize(cv, x, y, &max_x, &max_y); + break; + case 'J': + if(tuple[0] == 2) + { + x = 0; + y = 0; + updateCanvasSize(cv, x, y, &max_x, &max_y); + } + break; + case 'K': + // CLEAR END OF LINE + break; + case 'm': + for(j=0; j < count; j++) + manage_modifiers(tuple[j], &fg, &bg, &old_fg, &old_bg); + cucul_set_color(cv, fg, bg); + break; + default: + /*printf("Unknow command %c (%c)\n", c, IS_ALPHA(c)?c:'.');*/ + break; + } + + + } else { + if(buffer[i] == '\n') + { + x = 0; + y++; + updateCanvasSize(cv, x, y, &max_x, &max_y); + } + else if(buffer[i] == '\r') + { + // DOS sucks. + } + else + { + if((buffer[i]>=0x20) || (buffer[i]<=0x7E)) + { + _cucul_putchar32(cv, x, y,_cucul_cp437_to_utf32(buffer[i])); + + // cucul_putchar(cv, x, y, buffer[i]); + } + else + cucul_putchar(cv, x, y, '?'); + x++; + updateCanvasSize(cv, x, y, &max_x, &max_y); + } + } + + + + i+=add; // add is tuple char count, then +[ +command + add = 0; + + } + return cv; +} + +/* XXX : ANSI loader helpers */ + +unsigned char get_ansi_command(unsigned char const *buffer, int size) +{ + int i = 0; + + for(i=0; i < size; i++) + if(IS_ALPHA(buffer[i])) + return buffer[i]; + + return 0; +} + +int parse_tuple(unsigned int *ret, unsigned char const *buffer, int size) +{ + int i = 0; + int j = 0; + int t = 0; + unsigned char nbr[1024]; + + + ret[0] = 0x1337; + + for(i=0; i < size; i++) + { + if(IS_ALPHA(buffer[i])) + { + if(j!=0) { + ret[t] = atoi((char*)nbr); + t++; + } + ret[t] = 0x1337; + j=0; + return i; + } + if(buffer[i] != ';') + { + nbr[j] = buffer[i]; + nbr[j+1] = 0; + j++; + } else + { + ret[t] = atoi((char*)nbr); + t++; + ret[t] = 0x1337; + j=0; + } + } + return size; +} + + + +void manage_modifiers(char c, int *fg, int *bg, int *old_fg, int *old_bg) +{ + switch(c) { + case 0: + *fg = CUCUL_COLOR_LIGHTGRAY; + *bg = CUCUL_COLOR_BLACK; + break; + case 1: // BOLD + + break; + case 4: // Underline + + break; + case 5: // blink + + break; + case 7: // reverse + *fg = 15-*fg; + *bg = 15-*bg; + break; + case 8: // invisible + *old_fg = *fg; + *old_bg = *bg; + *fg = CUCUL_COLOR_TRANSPARENT; + *bg = CUCUL_COLOR_TRANSPARENT; + break; + case 28: // not invisible + *fg = *old_fg; + *bg = *old_bg; + break; + case 30: + *fg = CUCUL_COLOR_BLACK; + break; + case 31: + *fg = CUCUL_COLOR_RED; + break; + case 32: + *fg = CUCUL_COLOR_GREEN; + break; + case 33: + *fg = CUCUL_COLOR_BROWN; + break; + case 34: + *fg = CUCUL_COLOR_BLUE; + break; + case 35: + *fg = CUCUL_COLOR_MAGENTA; + break; + case 36: + *fg = CUCUL_COLOR_CYAN; + break; + case 37: + *fg = CUCUL_COLOR_WHITE; + break; + case 39: + *fg = CUCUL_COLOR_LIGHTGRAY; + break; + case 40: + *bg = CUCUL_COLOR_BLACK; + break; + case 41: + *bg = CUCUL_COLOR_RED; + break; + case 42: + *bg = CUCUL_COLOR_GREEN; + break; + case 43: + *bg = CUCUL_COLOR_BROWN; + break; + case 44: + *bg = CUCUL_COLOR_BLUE; + break; + case 45: + *bg = CUCUL_COLOR_MAGENTA; + break; + case 46: + *bg = CUCUL_COLOR_CYAN; + break; + case 47: + *bg = CUCUL_COLOR_WHITE; + break; + case 49: + *bg = CUCUL_COLOR_BLACK; + break; + + case 90: + *fg = CUCUL_COLOR_DARKGRAY; + break; + case 91: + *fg = CUCUL_COLOR_LIGHTRED; + break; + case 92: + *fg = CUCUL_COLOR_LIGHTGREEN; + break; + case 93: + *fg = CUCUL_COLOR_YELLOW; + break; + case 94: + *fg = CUCUL_COLOR_LIGHTBLUE; + break; + case 95: + *fg = CUCUL_COLOR_LIGHTMAGENTA; + break; + case 96: + *fg = CUCUL_COLOR_LIGHTCYAN; + break; + case 97: + *fg = CUCUL_COLOR_WHITE; + break; + case 100: + *bg = CUCUL_COLOR_DARKGRAY; + break; + case 101: + *bg = CUCUL_COLOR_LIGHTRED; + break; + case 102: + *bg = CUCUL_COLOR_LIGHTGREEN; + break; + case 103: + *bg = CUCUL_COLOR_YELLOW; + break; + case 104: + *bg = CUCUL_COLOR_LIGHTBLUE; + break; + case 105: + *bg = CUCUL_COLOR_LIGHTMAGENTA; + break; + case 106: + *bg = CUCUL_COLOR_LIGHTCYAN; + break; + case 107: + *bg = CUCUL_COLOR_WHITE; + break; + default: + /* printf("Unknow option to 'm' %d (%c)\n", c, IS_ALPHA(c)?c:'.'); */ + break; + + } +} + + +void updateCanvasSize(cucul_canvas_t *cv, int x, int y, int *max_x, int *max_y) +{ + if(x>*max_x) *max_x = x; + if(y>*max_y) *max_y = y; + + cucul_set_canvas_size(cv, *max_x, *max_y); +} diff --git a/test/Makefile.am b/test/Makefile.am index 121b4ee..85c8599 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -2,7 +2,7 @@ AM_CPPFLAGS = -I$(top_srcdir)/cucul -I$(top_srcdir)/caca -DDATADIR=\"$(pkgdatadir)\" -noinst_PROGRAMS = colors demo dithering event export font frames gamma hsv spritedit text transform truecolor unicode +noinst_PROGRAMS = colors demo dithering event export font frames gamma hsv spritedit text transform truecolor unicode import colors_SOURCES = colors.c colors_LDADD = ../caca/libcaca.la ../cucul/libcucul.la @CACA_LIBS@ @@ -46,3 +46,5 @@ truecolor_LDADD = ../caca/libcaca.la ../cucul/libcucul.la @CACA_LIBS@ unicode_SOURCES = unicode.c unicode_LDADD = ../caca/libcaca.la ../cucul/libcucul.la @CACA_LIBS@ +import_SOURCES = import.c +import_LDADD = ../caca/libcaca.la ../cucul/libcucul.la @CACA_LIBS@