| @@ -6,8 +6,6 @@ | |||||
| - allow to change the canvas size in a per-frame basis. | - allow to change the canvas size in a per-frame basis. | ||||
| - export attribute parsing functions such as attr_to_ansi4fg etc. | - export attribute parsing functions such as attr_to_ansi4fg etc. | ||||
| - add cursor support in the canvas, so that we can load ANSI files | |||||
| in stream mode. | |||||
| \subsection indep API-independent stuff | \subsection indep API-independent stuff | ||||
| @@ -41,6 +41,55 @@ | |||||
| #include "cucul.h" | #include "cucul.h" | ||||
| #include "cucul_internals.h" | #include "cucul_internals.h" | ||||
| /** \brief Set cursor position. | |||||
| * | |||||
| * Put the cursor at the given coordinates. Functions making use of the | |||||
| * cursor will use the new values. Setting the cursor position outside the | |||||
| * canvas is legal but the cursor will not be shown. | |||||
| * | |||||
| * This function never fails. | |||||
| * | |||||
| * \param cv A handle to the libcucul canvas. | |||||
| * \param x X cursor coordinate. | |||||
| * \param y Y cursor coordinate. | |||||
| * \return This function always returns 0. | |||||
| */ | |||||
| int cucul_gotoxy(cucul_canvas_t *cv, int x, int y) | |||||
| { | |||||
| cv->frames[cv->frame].x = x; | |||||
| cv->frames[cv->frame].y = y; | |||||
| return 0; | |||||
| } | |||||
| /** \brief Get X cursor position. | |||||
| * | |||||
| * Retrieve the X coordinate of the cursor's position. | |||||
| * | |||||
| * This function never fails. | |||||
| * | |||||
| * \param cv A handle to the libcucul canvas. | |||||
| * \return The cursor's X coordinate. | |||||
| */ | |||||
| int cucul_get_cursor_x(cucul_canvas_t *cv) | |||||
| { | |||||
| return cv->frames[cv->frame].x; | |||||
| } | |||||
| /** \brief Get Y cursor position. | |||||
| * | |||||
| * Retrieve the Y coordinate of the cursor's position. | |||||
| * | |||||
| * This function never fails. | |||||
| * | |||||
| * \param cv A handle to the libcucul canvas. | |||||
| * \return The cursor's Y coordinate. | |||||
| */ | |||||
| int cucul_get_cursor_y(cucul_canvas_t *cv) | |||||
| { | |||||
| return cv->frames[cv->frame].y; | |||||
| } | |||||
| /** \brief Print an ASCII or Unicode character. | /** \brief Print an ASCII or Unicode character. | ||||
| * | * | ||||
| * Print an ASCII or Unicode character at the given coordinates, using | * Print an ASCII or Unicode character at the given coordinates, using | ||||
| @@ -264,6 +313,54 @@ int cucul_clear_canvas(cucul_canvas_t *cv) | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| /** \brief Set cursor handle. | |||||
| * | |||||
| * Set the canvas' handle. Blitting functions will use the handle value | |||||
| * to put the canvas at the proper coordinates. | |||||
| * | |||||
| * This function never fails. | |||||
| * | |||||
| * \param cv A handle to the libcucul canvas. | |||||
| * \param x X handle coordinate. | |||||
| * \param y Y handle coordinate. | |||||
| * \return This function always returns 0. | |||||
| */ | |||||
| int cucul_set_canvas_handle(cucul_canvas_t *cv, int x, int y) | |||||
| { | |||||
| cv->frames[cv->frame].handlex = x; | |||||
| cv->frames[cv->frame].handley = y; | |||||
| return 0; | |||||
| } | |||||
| /** \brief Get X handle position. | |||||
| * | |||||
| * Retrieve the X coordinate of the canvas' handle. | |||||
| * | |||||
| * This function never fails. | |||||
| * | |||||
| * \param cv A handle to the libcucul canvas. | |||||
| * \return The canvas' handle's X coordinate. | |||||
| */ | |||||
| int cucul_get_canvas_handle_x(cucul_canvas_t *cv) | |||||
| { | |||||
| return cv->frames[cv->frame].handlex; | |||||
| } | |||||
| /** \brief Get Y handle position. | |||||
| * | |||||
| * Retrieve the Y coordinate of the canvas' handle. | |||||
| * | |||||
| * This function never fails. | |||||
| * | |||||
| * \param cv A handle to the libcucul canvas. | |||||
| * \return The canvas' handle's Y coordinate. | |||||
| */ | |||||
| int cucul_get_canvas_handle_y(cucul_canvas_t *cv) | |||||
| { | |||||
| return cv->frames[cv->frame].handley; | |||||
| } | |||||
| /** \brief Blit a canvas onto another one. | /** \brief Blit a canvas onto another one. | ||||
| * | * | ||||
| * Blit a canvas onto another one at the given coordinates. | * Blit a canvas onto another one at the given coordinates. | ||||
| @@ -43,6 +43,9 @@ | |||||
| * \e libcucul function to be called in a function. cucul_free_canvas() | * \e libcucul function to be called in a function. cucul_free_canvas() | ||||
| * should be called at the end of the program to free all allocated resources. | * should be called at the end of the program to free all allocated resources. | ||||
| * | * | ||||
| * Both the cursor and the canvas' handle are initialised at the top-left | |||||
| * corner. | |||||
| * | |||||
| * If an error occurs, NULL is returned and \b errno is set accordingly: | * If an error occurs, NULL is returned and \b errno is set accordingly: | ||||
| * - \c ENOMEM Not enough memory for the requested canvas size. | * - \c ENOMEM Not enough memory for the requested canvas size. | ||||
| * | * | ||||
| @@ -78,6 +81,8 @@ cucul_canvas_t * cucul_create_canvas(unsigned int width, unsigned int height) | |||||
| cv->frames[0].width = cv->frames[0].height = 0; | cv->frames[0].width = cv->frames[0].height = 0; | ||||
| cv->frames[0].chars = NULL; | cv->frames[0].chars = NULL; | ||||
| cv->frames[0].attrs = NULL; | cv->frames[0].attrs = NULL; | ||||
| cv->frames[0].x = cv->frames[0].y = 0; | |||||
| cv->frames[0].handlex = cv->frames[0].handley = 0; | |||||
| cv->frames[0].curattr = cv->curattr; | cv->frames[0].curattr = cv->curattr; | ||||
| if(_cucul_set_canvas_size(cv, width, height) < 0) | if(_cucul_set_canvas_size(cv, width, height) < 0) | ||||
| @@ -89,6 +89,9 @@ int cucul_rand(int, int); | |||||
| * | * | ||||
| * @{ */ | * @{ */ | ||||
| #define CUCUL_MAGIC_FULLWIDTH 0x000ffffe /**< Used to indicate that the previous character was a fullwidth glyph. */ | #define CUCUL_MAGIC_FULLWIDTH 0x000ffffe /**< Used to indicate that the previous character was a fullwidth glyph. */ | ||||
| int cucul_gotoxy(cucul_canvas_t *, int, int); | |||||
| int cucul_get_cursor_x(cucul_canvas_t *); | |||||
| int cucul_get_cursor_y(cucul_canvas_t *); | |||||
| unsigned long int cucul_get_attr(cucul_canvas_t *, int, int); | unsigned long int cucul_get_attr(cucul_canvas_t *, int, int); | ||||
| int cucul_set_attr(cucul_canvas_t *, unsigned long int); | int cucul_set_attr(cucul_canvas_t *, unsigned long int); | ||||
| int cucul_putattr(cucul_canvas_t *, int, int, unsigned long int); | int cucul_putattr(cucul_canvas_t *, int, int, unsigned long int); | ||||
| @@ -99,6 +102,9 @@ unsigned long int cucul_getchar(cucul_canvas_t *, int, int); | |||||
| int cucul_putstr(cucul_canvas_t *, int, int, char const *); | int cucul_putstr(cucul_canvas_t *, int, int, char const *); | ||||
| int cucul_printf(cucul_canvas_t *, int, int, char const *, ...); | int cucul_printf(cucul_canvas_t *, int, int, char const *, ...); | ||||
| int cucul_clear_canvas(cucul_canvas_t *); | int cucul_clear_canvas(cucul_canvas_t *); | ||||
| int cucul_set_canvas_handle(cucul_canvas_t *, int, int); | |||||
| int cucul_get_canvas_handle_x(cucul_canvas_t *); | |||||
| int cucul_get_canvas_handle_y(cucul_canvas_t *); | |||||
| int cucul_blit(cucul_canvas_t *, int, int, cucul_canvas_t const *, | int cucul_blit(cucul_canvas_t *, int, int, cucul_canvas_t const *, | ||||
| cucul_canvas_t const *); | cucul_canvas_t const *); | ||||
| int cucul_set_canvas_boundaries(cucul_canvas_t *, int, int, | int cucul_set_canvas_boundaries(cucul_canvas_t *, int, int, | ||||
| @@ -28,6 +28,8 @@ struct cucul_frame | |||||
| uint32_t *attrs; | uint32_t *attrs; | ||||
| /* Painting context */ | /* Painting context */ | ||||
| int x, y; | |||||
| int handlex, handley; | |||||
| uint32_t curattr; | uint32_t curattr; | ||||
| }; | }; | ||||
| @@ -171,14 +171,14 @@ static void *export_caca(cucul_canvas_t *cv, unsigned long int *bytes) | |||||
| * - 16 bytes for the canvas header | * - 16 bytes for the canvas header | ||||
| * - 24 bytes for the frame info | * - 24 bytes for the frame info | ||||
| * 8 bytes for each character cell */ | * 8 bytes for each character cell */ | ||||
| *bytes = 44 + 8 * cv->width * cv->height; | |||||
| *bytes = 52 + 8 * cv->width * cv->height; | |||||
| cur = data = malloc(*bytes); | cur = data = malloc(*bytes); | ||||
| /* magic */ | /* magic */ | ||||
| cur += sprintf(cur, "%s", "\xCA\xCA" "CV"); | cur += sprintf(cur, "%s", "\xCA\xCA" "CV"); | ||||
| /* canvas_header */ | /* canvas_header */ | ||||
| cur += sprintu32(cur, 16 + 24); | |||||
| cur += sprintu32(cur, 16 + 32 * 1); | |||||
| cur += sprintu32(cur, cv->width * cv->height * 8); | cur += sprintu32(cur, cv->width * cv->height * 8); | ||||
| cur += sprintu16(cur, 0x0001); | cur += sprintu16(cur, 0x0001); | ||||
| cur += sprintu32(cur, 1); | cur += sprintu32(cur, 1); | ||||
| @@ -189,8 +189,10 @@ static void *export_caca(cucul_canvas_t *cv, unsigned long int *bytes) | |||||
| cur += sprintu32(cur, cv->height); | cur += sprintu32(cur, cv->height); | ||||
| cur += sprintu32(cur, 0); | cur += sprintu32(cur, 0); | ||||
| cur += sprintu32(cur, cv->curattr); | cur += sprintu32(cur, cv->curattr); | ||||
| cur += sprintu32(cur, 0); | |||||
| cur += sprintu32(cur, 0); | |||||
| cur += sprintu32(cur, cv->frames[0].x); | |||||
| cur += sprintu32(cur, cv->frames[0].y); | |||||
| cur += sprintu32(cur, cv->frames[0].handlex); | |||||
| cur += sprintu32(cur, cv->frames[0].handley); | |||||
| /* canvas_data */ | /* canvas_data */ | ||||
| for(n = cv->height * cv->width; n--; ) | for(n = cv->height * cv->width; n--; ) | ||||
| @@ -236,6 +238,8 @@ static void *export_caca(cucul_canvas_t *cv, unsigned long int *bytes) | |||||
| * uint32_t duration; // Frame duration in milliseconds, 0 to | * uint32_t duration; // Frame duration in milliseconds, 0 to | ||||
| * // not specify a duration | * // not specify a duration | ||||
| * uint32_t attr; // Graphics context attribute | * uint32_t attr; // Graphics context attribute | ||||
| * int32_t cursor_x; // Cursor X coordinate | |||||
| * int32_t cursor_y; // Cursor Y coordinate | |||||
| * int32_t handle_x; // Handle X coordinate | * int32_t handle_x; // Handle X coordinate | ||||
| * int32_t handle_y; // Handle Y coordinate | * int32_t handle_y; // Handle Y coordinate | ||||
| * } | * } | ||||
| @@ -114,6 +114,9 @@ int cucul_create_canvas_frame(cucul_canvas_t *cv, unsigned int id) | |||||
| for(f = cv->framecount - 1; f > id; f--) | for(f = cv->framecount - 1; f > id; f--) | ||||
| cv->frames[f] = cv->frames[f - 1]; | cv->frames[f] = cv->frames[f - 1]; | ||||
| if(cv->frame >= id) | |||||
| cv->frame++; | |||||
| cv->frames[id].width = cv->width; | cv->frames[id].width = cv->width; | ||||
| cv->frames[id].height = cv->height; | cv->frames[id].height = cv->height; | ||||
| cv->frames[id].chars = malloc(size * sizeof(uint32_t)); | cv->frames[id].chars = malloc(size * sizeof(uint32_t)); | ||||
| @@ -122,8 +125,10 @@ int cucul_create_canvas_frame(cucul_canvas_t *cv, unsigned int id) | |||||
| memcpy(cv->frames[id].attrs, cv->attrs, size * sizeof(uint32_t)); | memcpy(cv->frames[id].attrs, cv->attrs, size * sizeof(uint32_t)); | ||||
| cv->frames[id].curattr = cv->curattr; | cv->frames[id].curattr = cv->curattr; | ||||
| if(cv->frame >= id) | |||||
| cv->frame++; | |||||
| cv->frames[id].x = cv->frames[cv->frame].x; | |||||
| cv->frames[id].y = cv->frames[cv->frame].y; | |||||
| cv->frames[id].handlex = cv->frames[cv->frame].handlex; | |||||
| cv->frames[id].handley = cv->frames[cv->frame].handley; | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| @@ -247,14 +247,14 @@ static long int import_caca(cucul_canvas_t *cv, | |||||
| if(size < 4 + control_size + data_size) | if(size < 4 + control_size + data_size) | ||||
| return 0; | return 0; | ||||
| if(control_size < 16 + frames * 24) | |||||
| if(control_size < 16 + frames * 32) | |||||
| goto invalid_caca; | goto invalid_caca; | ||||
| for(expected_size = 0, f = 0; f < frames; f++) | for(expected_size = 0, f = 0; f < frames; f++) | ||||
| { | { | ||||
| unsigned int width, height, duration; | unsigned int width, height, duration; | ||||
| uint32_t attr; | uint32_t attr; | ||||
| int x, y; | |||||
| int x, y, handlex, handley; | |||||
| width = sscanu32(buf + 4 + 16 + f * 24); | width = sscanu32(buf + 4 + 16 + f * 24); | ||||
| height = sscanu32(buf + 4 + 16 + f * 24 + 4); | height = sscanu32(buf + 4 + 16 + f * 24 + 4); | ||||
| @@ -262,6 +262,8 @@ static long int import_caca(cucul_canvas_t *cv, | |||||
| attr = sscanu32(buf + 4 + 16 + f * 24 + 12); | attr = sscanu32(buf + 4 + 16 + f * 24 + 12); | ||||
| x = (int32_t)sscanu32(buf + 4 + 16 + f * 24 + 16); | x = (int32_t)sscanu32(buf + 4 + 16 + f * 24 + 16); | ||||
| y = (int32_t)sscanu32(buf + 4 + 16 + f * 24 + 20); | y = (int32_t)sscanu32(buf + 4 + 16 + f * 24 + 20); | ||||
| handlex = (int32_t)sscanu32(buf + 4 + 16 + f * 24 + 24); | |||||
| handley = (int32_t)sscanu32(buf + 4 + 16 + f * 24 + 28); | |||||
| expected_size += width * height * 8; | expected_size += width * height * 8; | ||||
| } | } | ||||
| @@ -283,6 +285,10 @@ static long int import_caca(cucul_canvas_t *cv, | |||||
| } | } | ||||
| cv->curattr = sscanu32(buf + 4 + 16 + 12); | cv->curattr = sscanu32(buf + 4 + 16 + 12); | ||||
| cv->frames[0].x = (int32_t)sscanu32(buf + 4 + 16 + f * 24 + 16); | |||||
| cv->frames[0].y = (int32_t)sscanu32(buf + 4 + 16 + f * 24 + 20); | |||||
| cv->frames[0].handlex = (int32_t)sscanu32(buf + 4 + 16 + f * 24 + 24); | |||||
| cv->frames[0].handley = (int32_t)sscanu32(buf + 4 + 16 + f * 24 + 28); | |||||
| return 4 + control_size + data_size; | return 4 + control_size + data_size; | ||||