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