| @@ -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 */ | |||