diff --git a/caca/driver_raw.c b/caca/driver_raw.c index 92e5082..67828f2 100644 --- a/caca/driver_raw.c +++ b/caca/driver_raw.c @@ -53,30 +53,13 @@ static unsigned int raw_get_window_height(caca_display_t *dp) static void raw_display(caca_display_t *dp) { - uint32_t *attr = dp->cv->attr; - uint32_t *chars = dp->cv->chars; - uint32_t w, h; - unsigned int n; + cucul_buffer_t *buffer; - w = dp->cv->width; - h = dp->cv->height; - - fprintf(stdout, "CACA%c%c%c%c%c%c%c%c", - (w >> 24), (w >> 16) & 0xff, (w >> 8) & 0xff, w & 0xff, - (h >> 24), (h >> 16) & 0xff, (h >> 8) & 0xff, h & 0xff); - - for(n = dp->cv->height * dp->cv->width; n--; ) - { - uint32_t ch = *chars++; - uint32_t a = *attr++; - - fprintf(stdout, "%c%c%c%c%c%c%c%c", - (ch >> 24), (ch >> 16) & 0xff, (ch >> 8) & 0xff, ch & 0xff, - (a >> 24), (a >> 16) & 0xff, (a >> 8) & 0xff, a & 0xff); - } - - fprintf(stdout, "ACAC"); + buffer = cucul_create_export(dp->cv, "caca"); + fwrite(cucul_get_buffer_data(buffer), + cucul_get_buffer_size(buffer), 1, stdout); fflush(stdout); + cucul_free_buffer(buffer); } static void raw_handle_resize(caca_display_t *dp) diff --git a/cucul/cucul.c b/cucul/cucul.c index 548dd9b..6963488 100644 --- a/cucul/cucul.c +++ b/cucul/cucul.c @@ -87,25 +87,24 @@ cucul_canvas_t *cucul_load_canvas(void *data, unsigned int size) uint8_t *buf = (uint8_t *)data; unsigned int width, height, n; - if(size < 12) + if(size < 16) return NULL; if(buf[0] != 'C' || buf[1] != 'A' || buf[2] != 'C' || buf[3] != 'A') return NULL; - width = ((uint32_t)buf[4] << 24) | ((uint32_t)buf[5] << 16) - | ((uint32_t)buf[6] << 8) | (uint32_t)buf[7]; - height = ((uint32_t)buf[8] << 24) | ((uint32_t)buf[9] << 16) + if(buf[4] != 'C' || buf[5] != 'A' || buf[6] != 'N' || buf[7] != 'V') + return NULL; + + width = ((uint32_t)buf[8] << 24) | ((uint32_t)buf[9] << 16) | ((uint32_t)buf[10] << 8) | (uint32_t)buf[11]; + height = ((uint32_t)buf[12] << 24) | ((uint32_t)buf[13] << 16) + | ((uint32_t)buf[14] << 8) | (uint32_t)buf[15]; if(!width || !height) return NULL; - if(size != 12 + width * height * 8 + 4) - return NULL; - - if(buf[size - 4] != 'A' || buf[size - 3] != 'C' - || buf[size - 2] != 'A' || buf[size - 1] != 'C') + if(size != 16 + width * height * 8) return NULL; cv = cucul_create_canvas(width, height); @@ -115,14 +114,14 @@ cucul_canvas_t *cucul_load_canvas(void *data, unsigned int size) for(n = height * width; n--; ) { - cv->chars[n] = ((uint32_t)buf[12 + 8 * n] << 24) - | ((uint32_t)buf[13 + 8 * n] << 16) - | ((uint32_t)buf[14 + 8 * n] << 8) - | (uint32_t)buf[15 + 8 * n]; - cv->attr[n] = ((uint32_t)buf[16 + 8 * n] << 24) - | ((uint32_t)buf[17 + 8 * n] << 16) - | ((uint32_t)buf[18 + 8 * n] << 8) - | (uint32_t)buf[19 + 8 * n]; + cv->chars[n] = ((uint32_t)buf[16 + 0 + 8 * n] << 24) + | ((uint32_t)buf[16 + 1 + 8 * n] << 16) + | ((uint32_t)buf[16 + 2 + 8 * n] << 8) + | (uint32_t)buf[16 + 3 + 8 * n]; + cv->attr[n] = ((uint32_t)buf[16 + 4 + 8 * n] << 24) + | ((uint32_t)buf[16 + 5 + 8 * n] << 16) + | ((uint32_t)buf[16 + 6 + 8 * n] << 8) + | (uint32_t)buf[16 + 7 + 8 * n]; } return cv; diff --git a/cucul/export.c b/cucul/export.c index 50334ae..d6cdc5c 100644 --- a/cucul/export.c +++ b/cucul/export.c @@ -27,6 +27,7 @@ #include "cucul.h" #include "cucul_internals.h" +static void export_caca(cucul_canvas_t *, cucul_buffer_t *); static void export_ansi(cucul_canvas_t *, cucul_buffer_t *); static void export_html(cucul_canvas_t *, cucul_buffer_t *); static void export_html3(cucul_canvas_t *, cucul_buffer_t *); @@ -44,6 +45,8 @@ static void export_tga(cucul_canvas_t *, cucul_buffer_t *); * * Valid values for \e format are: * + * \li \e "caca": export native libcaca files. + * * \li \e "ansi": export ANSI art (CP437 charset with ANSI colour codes). * * \li \e "html": export an HTML page with CSS information. @@ -70,7 +73,9 @@ cucul_buffer_t * cucul_create_export(cucul_canvas_t *cv, char const *format) ex->size = 0; ex->data = NULL; - if(!strcasecmp("ansi", format)) + if(!strcasecmp("caca", format)) + export_caca(cv, ex); + else if(!strcasecmp("ansi", format)) export_ansi(cv, ex); else if(!strcasecmp("html", format)) export_html(cv, ex); @@ -107,6 +112,7 @@ char const * const * cucul_get_export_list(void) { static char const * const list[] = { + "caca", "native libcaca format", "ansi", "ANSI", "html", "HTML", "html3", "backwards-compatible HTML", @@ -124,6 +130,45 @@ char const * const * cucul_get_export_list(void) * XXX: the following functions are local. */ +/* Generate a native libcaca canvas file. */ +static void export_caca(cucul_canvas_t *cv, cucul_buffer_t *ex) +{ + uint32_t *attr = cv->attr; + uint32_t *chars = cv->chars; + char *cur; + uint32_t w, h; + unsigned int n; + + /* 16 bytes for the canvas, 8 bytes for each character cell. */ + ex->size = 16 + 8 * cv->width * cv->height; + ex->data = malloc(ex->size); + + cur = ex->data; + + w = cv->width; + h = cv->height; + + cur += sprintf(cur, "CACACANV%c%c%c%c%c%c%c%c", + (w >> 24), (w >> 16) & 0xff, (w >> 8) & 0xff, w & 0xff, + (h >> 24), (h >> 16) & 0xff, (h >> 8) & 0xff, h & 0xff); + + for(n = cv->height * cv->width; n--; ) + { + uint32_t ch = *chars++; + uint32_t a = *attr++; + + *cur++ = ch >> 24; + *cur++ = (ch >> 16) & 0xff; + *cur++ = (ch >> 8) & 0xff; + *cur++ = ch & 0xff; + + *cur++ = a >> 24; + *cur++ = (a >> 16) & 0xff; + *cur++ = (a >> 8) & 0xff; + *cur++ = a & 0xff; + } +} + /* Generate ANSI representation of current canvas. */ static void export_ansi(cucul_canvas_t *cv, cucul_buffer_t *ex) { diff --git a/src/cacaserver.c b/src/cacaserver.c index 145942e..c917e6b 100644 --- a/src/cacaserver.c +++ b/src/cacaserver.c @@ -134,7 +134,7 @@ int main(void) #endif server = malloc(sizeof(struct server)); - server->input = malloc(12); + server->input = malloc(16); server->read = 0; server->client_count = 0; @@ -205,22 +205,22 @@ int main(void) manage_connections(server); /* Read data from stdin */ - read(0, buf, 12); + read(0, buf, 16); - while(buf[0] != 'C' && buf[1] != 'A' && buf[2] != 'C' && buf[3] != 'A') + while(buf[0] != 'C' || buf[1] != 'A' || buf[2] != 'C' || buf[3] != 'A') { - memmove(buf, buf + 1, 11); - read(0, buf + 11, 1); + memmove(buf, buf + 1, 15); + read(0, buf + 15, 1); } - width = ((uint32_t)buf[4] << 24) | ((uint32_t)buf[5] << 16) - | ((uint32_t)buf[6] << 8) | (uint32_t)buf[7]; - height = ((uint32_t)buf[8] << 24) | ((uint32_t)buf[9] << 16) + width = ((uint32_t)buf[8] << 24) | ((uint32_t)buf[9] << 16) | ((uint32_t)buf[10] << 8) | (uint32_t)buf[11]; + height = ((uint32_t)buf[12] << 24) | ((uint32_t)buf[13] << 16) + | ((uint32_t)buf[14] << 8) | (uint32_t)buf[15]; - size = 12 + width * height * 8 + 4; + size = 16 + width * height * 8; buf = server->input = realloc(server->input, size); - read(0, buf + 12, size - 12); + read(0, buf + 16, size - 16); /* Free the previous canvas, if any */ if(server->canvas) @@ -239,9 +239,11 @@ int main(void) } /* Get ANSI representation of the image and skip the end-of buffer - * linefeed ("\r\n\0", 3 bytes) */ + * linefeed ("\r\n", 2 bytes) */ server->buffer = cucul_create_export(server->canvas, "ansi"); - server->buflen -= 3; + server->bufdata = cucul_get_buffer_data(server->buffer); + server->buflen = cucul_get_buffer_size(server->buffer); + server->buflen -= 2; for(i = 0; i < server->client_count; i++) { @@ -410,7 +412,11 @@ static int send_data(struct server *server, struct client *c) if(errno == EAGAIN) ret = 0; else + { + fprintf(stderr, "client %i failed (%s)\n", + c->fd, strerror(errno)); return -1; + } } if(ret == c->stop - c->start) @@ -458,7 +464,10 @@ static int send_data(struct server *server, struct client *c) if(errno == EAGAIN) ret = 0; else + { + fprintf(stderr, "client %i failed (%s)\n", c->fd, strerror(errno)); return -1; + } } if(ret < (ssize_t)strlen(ANSI_PREFIX)) @@ -487,7 +496,10 @@ static int send_data(struct server *server, struct client *c) if(errno == EAGAIN) ret = 0; else + { + fprintf(stderr, "client %i failed (%s)\n", c->fd, strerror(errno)); return -1; + } } if(ret < (int)server->buflen)