* Removed most code from the raw driver and replaced it with a call to the
caca exporter.
* Slightly changed the caca export format and updated code accordingly.
* Improved cacaserver error reporting.
tags/v0.99.beta14
| @@ -53,30 +53,13 @@ static unsigned int raw_get_window_height(caca_display_t *dp) | |||||
| static void raw_display(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); | fflush(stdout); | ||||
| cucul_free_buffer(buffer); | |||||
| } | } | ||||
| static void raw_handle_resize(caca_display_t *dp) | static void raw_handle_resize(caca_display_t *dp) | ||||
| @@ -87,25 +87,24 @@ cucul_canvas_t *cucul_load_canvas(void *data, unsigned int size) | |||||
| uint8_t *buf = (uint8_t *)data; | uint8_t *buf = (uint8_t *)data; | ||||
| unsigned int width, height, n; | unsigned int width, height, n; | ||||
| if(size < 12) | |||||
| if(size < 16) | |||||
| return NULL; | return NULL; | ||||
| if(buf[0] != 'C' || buf[1] != 'A' || buf[2] != 'C' || buf[3] != 'A') | if(buf[0] != 'C' || buf[1] != 'A' || buf[2] != 'C' || buf[3] != 'A') | ||||
| return NULL; | 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]; | | ((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) | if(!width || !height) | ||||
| return NULL; | 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; | return NULL; | ||||
| cv = cucul_create_canvas(width, height); | 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--; ) | 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; | return cv; | ||||
| @@ -27,6 +27,7 @@ | |||||
| #include "cucul.h" | #include "cucul.h" | ||||
| #include "cucul_internals.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_ansi(cucul_canvas_t *, cucul_buffer_t *); | ||||
| static void export_html(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 *); | 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: | * 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 "ansi": export ANSI art (CP437 charset with ANSI colour codes). | ||||
| * | * | ||||
| * \li \e "html": export an HTML page with CSS information. | * \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->size = 0; | ||||
| ex->data = NULL; | ex->data = NULL; | ||||
| if(!strcasecmp("ansi", format)) | |||||
| if(!strcasecmp("caca", format)) | |||||
| export_caca(cv, ex); | |||||
| else if(!strcasecmp("ansi", format)) | |||||
| export_ansi(cv, ex); | export_ansi(cv, ex); | ||||
| else if(!strcasecmp("html", format)) | else if(!strcasecmp("html", format)) | ||||
| export_html(cv, ex); | export_html(cv, ex); | ||||
| @@ -107,6 +112,7 @@ char const * const * cucul_get_export_list(void) | |||||
| { | { | ||||
| static char const * const list[] = | static char const * const list[] = | ||||
| { | { | ||||
| "caca", "native libcaca format", | |||||
| "ansi", "ANSI", | "ansi", "ANSI", | ||||
| "html", "HTML", | "html", "HTML", | ||||
| "html3", "backwards-compatible HTML", | "html3", "backwards-compatible HTML", | ||||
| @@ -124,6 +130,45 @@ char const * const * cucul_get_export_list(void) | |||||
| * XXX: the following functions are local. | * 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. */ | /* Generate ANSI representation of current canvas. */ | ||||
| static void export_ansi(cucul_canvas_t *cv, cucul_buffer_t *ex) | static void export_ansi(cucul_canvas_t *cv, cucul_buffer_t *ex) | ||||
| { | { | ||||
| @@ -134,7 +134,7 @@ int main(void) | |||||
| #endif | #endif | ||||
| server = malloc(sizeof(struct server)); | server = malloc(sizeof(struct server)); | ||||
| server->input = malloc(12); | |||||
| server->input = malloc(16); | |||||
| server->read = 0; | server->read = 0; | ||||
| server->client_count = 0; | server->client_count = 0; | ||||
| @@ -205,22 +205,22 @@ int main(void) | |||||
| manage_connections(server); | manage_connections(server); | ||||
| /* Read data from stdin */ | /* 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]; | | ((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); | 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 */ | /* Free the previous canvas, if any */ | ||||
| if(server->canvas) | if(server->canvas) | ||||
| @@ -239,9 +239,11 @@ int main(void) | |||||
| } | } | ||||
| /* Get ANSI representation of the image and skip the end-of buffer | /* 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->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++) | 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) | if(errno == EAGAIN) | ||||
| ret = 0; | ret = 0; | ||||
| else | else | ||||
| { | |||||
| fprintf(stderr, "client %i failed (%s)\n", | |||||
| c->fd, strerror(errno)); | |||||
| return -1; | return -1; | ||||
| } | |||||
| } | } | ||||
| if(ret == c->stop - c->start) | if(ret == c->stop - c->start) | ||||
| @@ -458,7 +464,10 @@ static int send_data(struct server *server, struct client *c) | |||||
| if(errno == EAGAIN) | if(errno == EAGAIN) | ||||
| ret = 0; | ret = 0; | ||||
| else | else | ||||
| { | |||||
| fprintf(stderr, "client %i failed (%s)\n", c->fd, strerror(errno)); | |||||
| return -1; | return -1; | ||||
| } | |||||
| } | } | ||||
| if(ret < (ssize_t)strlen(ANSI_PREFIX)) | if(ret < (ssize_t)strlen(ANSI_PREFIX)) | ||||
| @@ -487,7 +496,10 @@ static int send_data(struct server *server, struct client *c) | |||||
| if(errno == EAGAIN) | if(errno == EAGAIN) | ||||
| ret = 0; | ret = 0; | ||||
| else | else | ||||
| { | |||||
| fprintf(stderr, "client %i failed (%s)\n", c->fd, strerror(errno)); | |||||
| return -1; | return -1; | ||||
| } | |||||
| } | } | ||||
| if(ret < (int)server->buflen) | if(ret < (int)server->buflen) | ||||