|
|
@@ -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); |
|
|
|
} |