diff --git a/cucul/canvas.c b/cucul/canvas.c index 4b58cf9..483f69c 100644 --- a/cucul/canvas.c +++ b/cucul/canvas.c @@ -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) diff --git a/cucul/colour.c b/cucul/colour.c index cbdf3b4..efb2d86 100644 --- a/cucul/colour.c +++ b/cucul/colour.c @@ -19,6 +19,10 @@ #include "config.h" #include "common.h" +#if defined(HAVE_ERRNO_H) +# include +#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; } /* diff --git a/cucul/cucul.c b/cucul/cucul.c index 9239fb8..732bdcd 100644 --- a/cucul/cucul.c +++ b/cucul/cucul.c @@ -23,6 +23,9 @@ # include # include # include +# if defined(HAVE_ERRNO_H) +# include +# 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; } diff --git a/cucul/cucul.h b/cucul/cucul.h index 9426be6..eb73504 100644 --- a/cucul/cucul.h +++ b/cucul/cucul.h @@ -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 *); /* @} */ diff --git a/cucul/cucul_internals.h b/cucul/cucul_internals.h index 341c8f6..dd3381a 100644 --- a/cucul/cucul_internals.h +++ b/cucul/cucul_internals.h @@ -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 */