@@ -6,8 +6,6 @@ | |||
- allow to change the canvas size in a per-frame basis. | |||
- 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 | |||
@@ -41,6 +41,55 @@ | |||
#include "cucul.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. | |||
* | |||
* 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; | |||
} | |||
/** \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. | |||
* | |||
* 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() | |||
* 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: | |||
* - \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].chars = 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; | |||
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. */ | |||
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); | |||
int cucul_set_attr(cucul_canvas_t *, 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_printf(cucul_canvas_t *, int, int, char const *, ...); | |||
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 *, | |||
cucul_canvas_t const *); | |||
int cucul_set_canvas_boundaries(cucul_canvas_t *, int, int, | |||
@@ -28,6 +28,8 @@ struct cucul_frame | |||
uint32_t *attrs; | |||
/* Painting context */ | |||
int x, y; | |||
int handlex, handley; | |||
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 | |||
* - 24 bytes for the frame info | |||
* 8 bytes for each character cell */ | |||
*bytes = 44 + 8 * cv->width * cv->height; | |||
*bytes = 52 + 8 * cv->width * cv->height; | |||
cur = data = malloc(*bytes); | |||
/* magic */ | |||
cur += sprintf(cur, "%s", "\xCA\xCA" "CV"); | |||
/* canvas_header */ | |||
cur += sprintu32(cur, 16 + 24); | |||
cur += sprintu32(cur, 16 + 32 * 1); | |||
cur += sprintu32(cur, cv->width * cv->height * 8); | |||
cur += sprintu16(cur, 0x0001); | |||
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, 0); | |||
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 */ | |||
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 | |||
* // not specify a duration | |||
* 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_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--) | |||
cv->frames[f] = cv->frames[f - 1]; | |||
if(cv->frame >= id) | |||
cv->frame++; | |||
cv->frames[id].width = cv->width; | |||
cv->frames[id].height = cv->height; | |||
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)); | |||
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; | |||
} | |||
@@ -247,14 +247,14 @@ static long int import_caca(cucul_canvas_t *cv, | |||
if(size < 4 + control_size + data_size) | |||
return 0; | |||
if(control_size < 16 + frames * 24) | |||
if(control_size < 16 + frames * 32) | |||
goto invalid_caca; | |||
for(expected_size = 0, f = 0; f < frames; f++) | |||
{ | |||
unsigned int width, height, duration; | |||
uint32_t attr; | |||
int x, y; | |||
int x, y, handlex, handley; | |||
width = sscanu32(buf + 4 + 16 + f * 24); | |||
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); | |||
x = (int32_t)sscanu32(buf + 4 + 16 + f * 24 + 16); | |||
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; | |||
} | |||
@@ -283,6 +285,10 @@ static long int import_caca(cucul_canvas_t *cv, | |||
} | |||
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; | |||