diff --git a/cucul/import.c b/cucul/import.c index 3011c5d..68119aa 100644 --- a/cucul/import.c +++ b/cucul/import.c @@ -200,21 +200,18 @@ static cucul_canvas_t *import_text(void const *data, unsigned int size) return cv; } -#define IS_ALPHA(x) (x>='A' && x<='z') -#define END_ARG 0x1337 -static int parse_tuple(unsigned int *, unsigned char const *, int); -static void manage_modifiers(int, uint8_t *, uint8_t *, uint8_t *, uint8_t *, uint8_t *, uint8_t *); +static void manage_modifiers(int, uint8_t *, uint8_t *, uint8_t *, + uint8_t *, uint8_t *, uint8_t *); 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; + unsigned int i, j; int x = 0, y = 0; - int width = 80, height = 25; + unsigned int width = 80, height = 25; int save_x = 0, save_y = 0; unsigned int skip; - int j; uint8_t fg, bg, save_fg, save_bg, bold, reverse; fg = save_fg = CUCUL_COLOR_LIGHTGRAY; @@ -242,37 +239,60 @@ static cucul_canvas_t *import_ansi(void const *data, unsigned int size) continue; } - if(buffer[i] == '\x1b' && buffer[i + 1] == '[') /* ESC code */ + /* Interpret escape commands, as per Standard ECMA-48 "Control + * Functions for Coded Character Sets", 5.4. Control sequences. */ + if(buffer[i] == '\x1b' && buffer[i + 1] == '[') { unsigned int argv[1024]; /* Should be enough. Will it be? */ unsigned int argc = 0; - unsigned char c = '\0'; + unsigned int param, inter, final; - i++; // ESC - i++; // [ + /* Offset to parameter bytes */ + param = 2; - for(j = i; j < (int)size; j++) - if(IS_ALPHA(buffer[j])) - { - c = buffer[j]; + /* Offset to intermediate bytes: skip parameter bytes */ + for(inter = param; i + inter < size; inter++) + if(buffer[i + inter] < 0x30 || buffer[i + inter] > 0x3f) + break; + + /* Offset to final byte: skip intermediate bytes */ + for(final = inter; i + final < size; final++) + if(buffer[i + final] < 0x20 || buffer[i + final] > 0x2f) break; - } - skip += parse_tuple(argv, buffer + i, size - i); + if(buffer[i + final] < 0x40 || buffer[i + final] > 0x7e) + break; /* Invalid Final Byte */ - while(argv[argc] != END_ARG) - argc++; /* Gruik */ + skip += final; - switch(c) + if(param < inter && buffer[i + param] >= 0x3c) { - case 'f': - case 'H': - switch(argc) + //fprintf(stderr, "private sequence \"^[[%.*s\"\n", + // final - param + 1, buffer + i + param); + continue; /* Private sequence, skip it entirely */ + } + + /* Parse parameter bytes, if any */ + if(param < inter) + { + argv[0] = 0; + for(j = param; j < inter; j++) { - case 0: x = y = 0; break; - case 1: y = argv[0] - 1; x = 0; break; - case 2: y = argv[0] - 1; x = argv[1] - 1; break; + if(buffer[i + j] == ';') + argv[++argc] = 0; + else if(buffer[i + j] >= '0' && buffer[i + j] <= '9') + argv[argc] = 10 * argv[argc] + (buffer[i + j] - '0'); } + argc++; + } + + /* Interpret final byte */ + switch(buffer[i + final]) + { + case 'f': + case 'H': + x = (argc > 1) ? argv[1] - 1 : 0; + y = (argc > 0) ? argv[0] - 1 : 0; break; case 'A': y -= argc ? argv[0] : 1; @@ -309,7 +329,7 @@ static cucul_canvas_t *import_ansi(void const *data, unsigned int size) x = width; break; case 'm': - for(j = 0; j < (int)argc; j++) + for(j = 0; j < argc; j++) manage_modifiers(argv[j], &fg, &bg, &save_fg, &save_bg, &bold, &reverse); if(bold && fg < 8) @@ -330,13 +350,13 @@ static cucul_canvas_t *import_ansi(void const *data, unsigned int size) /* We're going to paste a character. First make sure the canvas * is big enough. */ - if(x >= width) + if((unsigned int)x >= width) { x = 0; y++; } - if(y >= height) + if((unsigned int)y >= height) { height = y + 1; cucul_set_canvas_size(cv, width, height); @@ -350,47 +370,7 @@ static cucul_canvas_t *import_ansi(void const *data, unsigned int size) return cv; } -/* XXX : ANSI loader helpers */ - -static 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] = END_ARG; - - for(i = 0; i < size; i++) - { - if(IS_ALPHA(buffer[i])) - { - if(j != 0) - { - ret[t] = atoi((char*)nbr); - t++; - } - ret[t] = END_ARG; - 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] = END_ARG; - j = 0; - } - } - return size; -} +/* XXX : ANSI loader helper */ static void manage_modifiers(int i, uint8_t *fg, uint8_t *bg, uint8_t *save_fg, uint8_t *save_bg, uint8_t *bold, uint8_t *reverse)