@@ -58,17 +58,18 @@ | |||
* \param ch The character to print. | |||
* \return This function always returns 0. | |||
*/ | |||
void cucul_putchar(cucul_canvas_t *cv, int x, int y, char ch) | |||
int cucul_putchar(cucul_canvas_t *cv, int x, int y, char ch) | |||
{ | |||
if(x < 0 || x >= (int)cv->width || | |||
y < 0 || y >= (int)cv->height) | |||
return; | |||
if(x < 0 || x >= (int)cv->width || y < 0 || y >= (int)cv->height) | |||
return 0; | |||
if((unsigned char)ch < 0x20 || (unsigned char)ch > 0x7f) | |||
ch = 0x20; | |||
cv->chars[x + y * cv->width] = ch; | |||
cv->attr[x + y * cv->width] = (cv->bgcolor << 16) | cv->fgcolor; | |||
return 0; | |||
} | |||
/** \brief Print a string. | |||
@@ -86,20 +87,20 @@ void cucul_putchar(cucul_canvas_t *cv, int x, int y, char ch) | |||
* \param s The string to print. | |||
* \return This function always returns 0. | |||
*/ | |||
void cucul_putstr(cucul_canvas_t *cv, int x, int y, char const *s) | |||
int cucul_putstr(cucul_canvas_t *cv, int x, int y, char const *s) | |||
{ | |||
uint32_t *chars, *attr; | |||
unsigned int len; | |||
if(y < 0 || y >= (int)cv->height || x >= (int)cv->width) | |||
return; | |||
return 0; | |||
len = _cucul_strlen_utf8(s); | |||
if(x < 0) | |||
{ | |||
if(len < (unsigned int)-x) | |||
return; | |||
return 0; | |||
len -= -x; | |||
s = _cucul_skip_utf8(s, -x); | |||
x = 0; | |||
@@ -119,6 +120,8 @@ void cucul_putstr(cucul_canvas_t *cv, int x, int y, char const *s) | |||
s = _cucul_skip_utf8(s, 1); | |||
len--; | |||
} | |||
return 0; | |||
} | |||
/** \brief Print a formated string. | |||
@@ -138,14 +141,14 @@ void cucul_putstr(cucul_canvas_t *cv, int x, int y, char const *s) | |||
* \param ... Arguments to the format string. | |||
* \return This function always returns 0. | |||
*/ | |||
void cucul_printf(cucul_canvas_t *cv, int x, int y, char const *format, ...) | |||
int cucul_printf(cucul_canvas_t *cv, int x, int y, char const *format, ...) | |||
{ | |||
char tmp[BUFSIZ]; | |||
char *buf = tmp; | |||
va_list args; | |||
if(y < 0 || y >= (int)cv->height || x >= (int)cv->width) | |||
return; | |||
return 0; | |||
if(cv->width - x + 1 > BUFSIZ) | |||
buf = malloc(cv->width - x + 1); | |||
@@ -163,6 +166,8 @@ void cucul_printf(cucul_canvas_t *cv, int x, int y, char const *format, ...) | |||
if(buf != tmp) | |||
free(buf); | |||
return 0; | |||
} | |||
/** \brief Clear the canvas. | |||
@@ -174,7 +179,7 @@ void cucul_printf(cucul_canvas_t *cv, int x, int y, char const *format, ...) | |||
* \param cv The canvas to clear. | |||
* \return This function always returns 0. | |||
*/ | |||
void cucul_clear_canvas(cucul_canvas_t *cv) | |||
int cucul_clear_canvas(cucul_canvas_t *cv) | |||
{ | |||
uint32_t color = (cv->bgcolor << 16) | cv->fgcolor; | |||
unsigned int n; | |||
@@ -185,6 +190,8 @@ void cucul_clear_canvas(cucul_canvas_t *cv) | |||
cv->chars[n] = (uint32_t)' '; | |||
cv->attr[n] = color; | |||
} | |||
return 0; | |||
} | |||
/** \brief Blit a canvas onto another one. | |||
@@ -192,12 +199,16 @@ void cucul_clear_canvas(cucul_canvas_t *cv) | |||
* This function blits a canvas onto another one at the given coordinates. | |||
* An optional mask canvas can be used. | |||
* | |||
* If an error occurs, -1 is returned and \b errno is set accordingly: | |||
* - \c EINVAL A mask was specified but the mask size and source canvas | |||
* size do not match. | |||
* | |||
* \param dst The destination canvas. | |||
* \param x X coordinate. | |||
* \param y Y coordinate. | |||
* \param src The source canvas. | |||
* \param mask The mask canvas. | |||
* \return 0 in case of success, -1 otherwise. | |||
* \return 0 in case of success, -1 if an error occurred. | |||
*/ | |||
int cucul_blit(cucul_canvas_t *dst, int x, int y, | |||
cucul_canvas_t const *src, cucul_canvas_t const *mask) | |||
@@ -19,6 +19,10 @@ | |||
#include "config.h" | |||
#include "common.h" | |||
#if defined(HAVE_ERRNO_H) | |||
# include <errno.h> | |||
#endif | |||
#include "cucul.h" | |||
#include "cucul_internals.h" | |||
@@ -37,17 +41,28 @@ static const uint16_t ansitab[16] = | |||
* Color values are those defined in cucul.h, such as CUCUL_COLOR_RED | |||
* or CUCUL_COLOR_TRANSPARENT. | |||
* | |||
* If an error occurs, -1 is returned and \b errno is set accordingly: | |||
* - \c EINVAL At least one of the colour values is invalid. | |||
* | |||
* \param cv A handle to the libcucul canvas. | |||
* \param fg The requested foreground colour. | |||
* \param bg The requested background colour. | |||
* \return 0 in case of success, -1 if an error occurred. | |||
*/ | |||
void cucul_set_color(cucul_canvas_t *cv, unsigned char fg, unsigned char bg) | |||
int cucul_set_color(cucul_canvas_t *cv, unsigned char fg, unsigned char bg) | |||
{ | |||
if(fg > 0x20 || bg > 0x20) | |||
return; | |||
{ | |||
#if defined(HAVE_ERRNO_H) | |||
errno = EINVAL; | |||
#endif | |||
return -1; | |||
} | |||
cv->fgcolor = fg; | |||
cv->bgcolor = bg; | |||
return 0; | |||
} | |||
/** \brief Set the default colour pair (truecolor version). | |||
@@ -60,14 +75,23 @@ void cucul_set_color(cucul_canvas_t *cv, unsigned char fg, unsigned char bg) | |||
* instance, 0xf088 is solid dark cyan (A=15 R=0 G=8 B=8), and 0x8fff is | |||
* white with 50% alpha (A=8 R=15 G=15 B=15). | |||
* | |||
* If an error occurs, -1 is returned and \b errno is set accordingly: | |||
* - \c EINVAL At least one of the colour values is invalid. | |||
* | |||
* \param cv A handle to the libcucul canvas. | |||
* \param fg The requested foreground colour. | |||
* \param bg The requested background colour. | |||
* \return 0 in case of success, -1 if an error occurred. | |||
*/ | |||
void cucul_set_truecolor(cucul_canvas_t *cv, unsigned int fg, unsigned int bg) | |||
int cucul_set_truecolor(cucul_canvas_t *cv, unsigned int fg, unsigned int bg) | |||
{ | |||
if(fg > 0xffff || bg > 0xffff) | |||
return; | |||
{ | |||
#if defined(HAVE_ERRNO_H) | |||
errno = EINVAL; | |||
#endif | |||
return -1; | |||
} | |||
if(fg < 0x100) | |||
fg += 0x100; | |||
@@ -77,6 +101,8 @@ void cucul_set_truecolor(cucul_canvas_t *cv, unsigned int fg, unsigned int bg) | |||
cv->fgcolor = fg; | |||
cv->bgcolor = bg; | |||
return 0; | |||
} | |||
/* | |||
@@ -23,6 +23,9 @@ | |||
# include <stdio.h> | |||
# include <stdlib.h> | |||
# include <string.h> | |||
# if defined(HAVE_ERRNO_H) | |||
# include <errno.h> | |||
# endif | |||
#endif | |||
#include "cucul.h" | |||
@@ -38,6 +41,9 @@ | |||
* If one of the desired canvas coordinates is zero, a default canvas size | |||
* of 80x32 is used instead. | |||
* | |||
* If an error occurs, -1 is returned and \b errno is set accordingly: | |||
* - \c ENOMEM Not enough memory for the requested canvas size. | |||
* | |||
* \param width The desired canvas width | |||
* \param height The desired canvas height | |||
* \return A libcucul canvas handle upon success, NULL if an error occurred. | |||
@@ -45,6 +51,10 @@ | |||
cucul_canvas_t * cucul_create_canvas(unsigned int width, unsigned int height) | |||
{ | |||
cucul_canvas_t *cv = malloc(sizeof(cucul_canvas_t)); | |||
int ret; | |||
if(!cv) | |||
goto nomem; | |||
cv->refcount = 0; | |||
@@ -58,7 +68,18 @@ cucul_canvas_t * cucul_create_canvas(unsigned int width, unsigned int height) | |||
cv->frame = 0; | |||
cv->framecount = 1; | |||
cv->allchars = malloc(sizeof(uint32_t *)); | |||
if(!cv->allchars) | |||
{ | |||
free(cv); | |||
goto nomem; | |||
} | |||
cv->allattr = malloc(sizeof(uint32_t *)); | |||
if(!cv->allattr) | |||
{ | |||
free(cv->allchars); | |||
free(cv); | |||
goto nomem; | |||
} | |||
cv->allchars[0] = NULL; | |||
cv->allattr[0] = NULL; | |||
@@ -66,17 +87,34 @@ cucul_canvas_t * cucul_create_canvas(unsigned int width, unsigned int height) | |||
* default X11 window. When a graphic driver attaches to us, it can set | |||
* a different size. */ | |||
if(width && height) | |||
_cucul_set_canvas_size(cv, width, height); | |||
ret = _cucul_set_canvas_size(cv, width, height); | |||
else | |||
_cucul_set_canvas_size(cv, 80, 32); | |||
ret = _cucul_set_canvas_size(cv, 80, 32); | |||
if(_cucul_init_dither()) | |||
if(ret < 0) | |||
{ | |||
#if defined(HAVE_ERRNO_H) | |||
int saved_errno = errno; | |||
#endif | |||
free(cv->allattr); | |||
free(cv->allchars); | |||
free(cv); | |||
#if defined(HAVE_ERRNO_H) | |||
errno = saved_errno; | |||
#endif | |||
return NULL; | |||
} | |||
/* FIXME: this shouldn't happen here */ | |||
_cucul_init_dither(); | |||
return cv; | |||
nomem: | |||
#if defined(HAVE_ERRNO_H) | |||
errno = ENOMEM; | |||
#endif | |||
return NULL; | |||
} | |||
/** \brief Resize a canvas. | |||
@@ -94,23 +132,36 @@ cucul_canvas_t * cucul_create_canvas(unsigned int width, unsigned int height) | |||
* canvas resize through user interaction. See the caca_event() documentation | |||
* for more about this. | |||
* | |||
* If an error occurs, -1 is returned and \b errno is set accordingly: | |||
* - \c EBUSY The canvas is in use by a display driver and cannot be resized. | |||
* - \c ENOMEM Not enough memory for the requested canvas size. If this | |||
* happens, the canvas handle becomes invalid and should not be used. | |||
* | |||
* \param cv A libcucul canvas | |||
* \param width The desired canvas width | |||
* \param height The desired canvas height | |||
* \return 0 in case of success, -1 if an error occurred. | |||
*/ | |||
void cucul_set_canvas_size(cucul_canvas_t *cv, unsigned int width, | |||
unsigned int height) | |||
int cucul_set_canvas_size(cucul_canvas_t *cv, unsigned int width, | |||
unsigned int height) | |||
{ | |||
if(cv->refcount) | |||
return; | |||
{ | |||
#if defined(HAVE_ERRNO_H) | |||
errno = EBUSY; | |||
#endif | |||
return -1; | |||
} | |||
_cucul_set_canvas_size(cv, width, height); | |||
return _cucul_set_canvas_size(cv, width, height); | |||
} | |||
/** \brief Get the canvas width. | |||
* | |||
* This function returns the current canvas width, in character cells. | |||
* | |||
* This function never fails. | |||
* | |||
* \param cv A libcucul canvas | |||
* \return The canvas width. | |||
*/ | |||
@@ -123,6 +174,8 @@ unsigned int cucul_get_canvas_width(cucul_canvas_t *cv) | |||
* | |||
* This function returns the current canvas height, in character cells. | |||
* | |||
* This function never fails. | |||
* | |||
* \param cv A libcucul canvas | |||
* \return The canvas height. | |||
*/ | |||
@@ -136,8 +189,11 @@ unsigned int cucul_get_canvas_height(cucul_canvas_t *cv) | |||
* This function translates a cucul_color enum into a human-readable | |||
* description string of the associated colour. | |||
* | |||
* This function never fails. | |||
* | |||
* \param color The colour value. | |||
* \return A static string containing the colour's name. | |||
* \return A static string containing the colour's name, or \c "unknown" if | |||
* the colour is unknown. | |||
*/ | |||
char const *cucul_get_color_name(unsigned int color) | |||
{ | |||
@@ -173,12 +229,25 @@ char const *cucul_get_color_name(unsigned int color) | |||
* cucul_free_canvas() has been called, no other \e libcucul functions may be | |||
* used unless a new call to cucul_create_canvas() is done. | |||
* | |||
* If an error occurs, -1 is returned and \b errno is set accordingly: | |||
* - \c EBUSY The canvas is in use by a display driver and cannot be freed. | |||
* | |||
* \param cv A libcucul canvas | |||
* \return 0 in case of success, -1 if an error occurred. | |||
*/ | |||
void cucul_free_canvas(cucul_canvas_t *cv) | |||
int cucul_free_canvas(cucul_canvas_t *cv) | |||
{ | |||
unsigned int f; | |||
if(cv->refcount) | |||
{ | |||
#if defined(HAVE_ERRNO_H) | |||
errno = EBUSY; | |||
#endif | |||
return -1; | |||
} | |||
/* FIXME: this shouldn't be here either (see above) */ | |||
_cucul_end_dither(); | |||
for(f = 0; f < cv->framecount; f++) | |||
@@ -188,9 +257,13 @@ void cucul_free_canvas(cucul_canvas_t *cv) | |||
} | |||
free(cv); | |||
return 0; | |||
} | |||
/** \brief Generate a random integer within a range. | |||
* | |||
* This function never fails. | |||
* | |||
* \param min The lower bound of the integer range. | |||
* \param max The upper bound of the integer range. | |||
@@ -206,8 +279,8 @@ int cucul_rand(int min, int max) | |||
* XXX: The following functions are local. | |||
*/ | |||
void _cucul_set_canvas_size(cucul_canvas_t *cv, unsigned int width, | |||
unsigned int height) | |||
int _cucul_set_canvas_size(cucul_canvas_t *cv, unsigned int width, | |||
unsigned int height) | |||
{ | |||
unsigned int x, y, f, old_width, old_height, new_size, old_size; | |||
@@ -228,6 +301,13 @@ void _cucul_set_canvas_size(cucul_canvas_t *cv, unsigned int width, | |||
new_size * sizeof(uint32_t)); | |||
cv->allattr[f] = realloc(cv->allattr[f], | |||
new_size * sizeof(uint32_t)); | |||
if(!cv->allchars[f] || !cv->allattr[f]) | |||
{ | |||
#if defined(HAVE_ERRNO_H) | |||
errno = ENOMEM; | |||
#endif | |||
return -1; | |||
} | |||
} | |||
} | |||
@@ -310,11 +390,20 @@ void _cucul_set_canvas_size(cucul_canvas_t *cv, unsigned int width, | |||
new_size * sizeof(uint32_t)); | |||
cv->allattr[f] = realloc(cv->allattr[f], | |||
new_size * sizeof(uint32_t)); | |||
if(!cv->allchars[f] || !cv->allattr[f]) | |||
{ | |||
#if defined(HAVE_ERRNO_H) | |||
errno = ENOMEM; | |||
#endif | |||
return -1; | |||
} | |||
} | |||
} | |||
/* Reset the current frame shortcut */ | |||
cv->chars = cv->allchars[cv->frame]; | |||
cv->attr = cv->allattr[cv->frame]; | |||
return 0; | |||
} | |||
@@ -72,10 +72,10 @@ typedef struct cucul_font cucul_font_t; | |||
* | |||
* @{ */ | |||
cucul_canvas_t * cucul_create_canvas(unsigned int, unsigned int); | |||
void cucul_set_canvas_size(cucul_canvas_t *, unsigned int, unsigned int); | |||
int cucul_set_canvas_size(cucul_canvas_t *, unsigned int, unsigned int); | |||
unsigned int cucul_get_canvas_width(cucul_canvas_t *); | |||
unsigned int cucul_get_canvas_height(cucul_canvas_t *); | |||
void cucul_free_canvas(cucul_canvas_t *); | |||
int cucul_free_canvas(cucul_canvas_t *); | |||
int cucul_rand(int, int); | |||
/* @} */ | |||
@@ -95,13 +95,13 @@ int cucul_free_buffer(cucul_buffer_t *); | |||
* higher level graphics functions. | |||
* | |||
* @{ */ | |||
void cucul_set_color(cucul_canvas_t *, unsigned char, unsigned char); | |||
void cucul_set_truecolor(cucul_canvas_t *, unsigned int, unsigned int); | |||
int cucul_set_color(cucul_canvas_t *, unsigned char, unsigned char); | |||
int cucul_set_truecolor(cucul_canvas_t *, unsigned int, unsigned int); | |||
char const *cucul_get_color_name(unsigned int); | |||
void cucul_putchar(cucul_canvas_t *, int, int, char); | |||
void cucul_putstr(cucul_canvas_t *, int, int, char const *); | |||
void cucul_printf(cucul_canvas_t *, int, int, char const *, ...); | |||
void cucul_clear_canvas(cucul_canvas_t *); | |||
int cucul_putchar(cucul_canvas_t *, int, int, char); | |||
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_blit(cucul_canvas_t *, int, int, cucul_canvas_t const *, cucul_canvas_t const *); | |||
/* @} */ | |||
@@ -50,7 +50,7 @@ extern int _cucul_init_dither(void); | |||
extern int _cucul_end_dither(void); | |||
/* Canvas functions */ | |||
extern void _cucul_set_canvas_size(cucul_canvas_t *, unsigned int, unsigned int); | |||
extern int _cucul_set_canvas_size(cucul_canvas_t *, unsigned int, unsigned int); | |||
extern void _cucul_putchar32(cucul_canvas_t *, int, int, uint32_t); | |||
/* Charset functions */ | |||