| @@ -112,10 +112,10 @@ int cucul_blit(cucul_canvas_t *, int, int, cucul_canvas_t const *, cucul_canvas_ | |||||
| * These functions perform horizontal and vertical canvas flipping. | * These functions perform horizontal and vertical canvas flipping. | ||||
| * | * | ||||
| * @{ */ | * @{ */ | ||||
| void cucul_invert(cucul_canvas_t *); | |||||
| void cucul_flip(cucul_canvas_t *); | |||||
| void cucul_flop(cucul_canvas_t *); | |||||
| void cucul_rotate(cucul_canvas_t *); | |||||
| int cucul_invert(cucul_canvas_t *); | |||||
| int cucul_flip(cucul_canvas_t *); | |||||
| int cucul_flop(cucul_canvas_t *); | |||||
| int cucul_rotate(cucul_canvas_t *); | |||||
| /* @} */ | /* @} */ | ||||
| /** \defgroup prim libcucul primitives drawing | /** \defgroup prim libcucul primitives drawing | ||||
| @@ -150,9 +150,9 @@ int cucul_fill_triangle(cucul_canvas_t *, int, int, int, int, int, int, char con | |||||
| * | * | ||||
| * @{ */ | * @{ */ | ||||
| unsigned int cucul_get_canvas_frame_count(cucul_canvas_t *); | unsigned int cucul_get_canvas_frame_count(cucul_canvas_t *); | ||||
| void cucul_set_canvas_frame(cucul_canvas_t *, unsigned int); | |||||
| void cucul_create_canvas_frame(cucul_canvas_t *, unsigned int); | |||||
| void cucul_free_canvas_frame(cucul_canvas_t *, unsigned int); | |||||
| int cucul_set_canvas_frame(cucul_canvas_t *, unsigned int); | |||||
| int cucul_create_canvas_frame(cucul_canvas_t *, unsigned int); | |||||
| int cucul_free_canvas_frame(cucul_canvas_t *, unsigned int); | |||||
| /* @} */ | /* @} */ | ||||
| /** \defgroup dither libcucul bitmap dithering | /** \defgroup dither libcucul bitmap dithering | ||||
| @@ -165,24 +165,24 @@ cucul_dither_t *cucul_create_dither(unsigned int, unsigned int, | |||||
| unsigned int, unsigned int, | unsigned int, unsigned int, | ||||
| unsigned int, unsigned int, | unsigned int, unsigned int, | ||||
| unsigned int, unsigned int); | unsigned int, unsigned int); | ||||
| void cucul_set_dither_palette(cucul_dither_t *, | |||||
| unsigned int r[], unsigned int g[], | |||||
| unsigned int b[], unsigned int a[]); | |||||
| void cucul_set_dither_brightness(cucul_dither_t *, float); | |||||
| void cucul_set_dither_gamma(cucul_dither_t *, float); | |||||
| void cucul_set_dither_contrast(cucul_dither_t *, float); | |||||
| void cucul_set_dither_invert(cucul_dither_t *, int); | |||||
| void cucul_set_dither_antialias(cucul_dither_t *, char const *); | |||||
| int cucul_set_dither_palette(cucul_dither_t *, | |||||
| unsigned int r[], unsigned int g[], | |||||
| unsigned int b[], unsigned int a[]); | |||||
| int cucul_set_dither_brightness(cucul_dither_t *, float); | |||||
| int cucul_set_dither_gamma(cucul_dither_t *, float); | |||||
| int cucul_set_dither_contrast(cucul_dither_t *, float); | |||||
| int cucul_set_dither_invert(cucul_dither_t *, int); | |||||
| int cucul_set_dither_antialias(cucul_dither_t *, char const *); | |||||
| char const * const * cucul_get_dither_antialias_list(cucul_dither_t const *); | char const * const * cucul_get_dither_antialias_list(cucul_dither_t const *); | ||||
| void cucul_set_dither_color(cucul_dither_t *, char const *); | |||||
| int cucul_set_dither_color(cucul_dither_t *, char const *); | |||||
| char const * const * cucul_get_dither_color_list(cucul_dither_t const *); | char const * const * cucul_get_dither_color_list(cucul_dither_t const *); | ||||
| void cucul_set_dither_charset(cucul_dither_t *, char const *); | |||||
| int cucul_set_dither_charset(cucul_dither_t *, char const *); | |||||
| char const * const * cucul_get_dither_charset_list(cucul_dither_t const *); | char const * const * cucul_get_dither_charset_list(cucul_dither_t const *); | ||||
| void cucul_set_dither_mode(cucul_dither_t *, char const *); | |||||
| int cucul_set_dither_mode(cucul_dither_t *, char const *); | |||||
| char const * const * cucul_get_dither_mode_list(cucul_dither_t const *); | char const * const * cucul_get_dither_mode_list(cucul_dither_t const *); | ||||
| void cucul_dither_bitmap(cucul_canvas_t *, int, int, int, int, | |||||
| int cucul_dither_bitmap(cucul_canvas_t *, int, int, int, int, | |||||
| cucul_dither_t const *, void *); | cucul_dither_t const *, void *); | ||||
| void cucul_free_dither(cucul_dither_t *); | |||||
| int cucul_free_dither(cucul_dither_t *); | |||||
| /* @} */ | /* @} */ | ||||
| /** \defgroup font libcucul font handling | /** \defgroup font libcucul font handling | ||||
| @@ -195,9 +195,9 @@ cucul_font_t *cucul_load_font(void const *, unsigned int); | |||||
| char const * const * cucul_get_font_list(void); | char const * const * cucul_get_font_list(void); | ||||
| unsigned int cucul_get_font_width(cucul_font_t *); | unsigned int cucul_get_font_width(cucul_font_t *); | ||||
| unsigned int cucul_get_font_height(cucul_font_t *); | unsigned int cucul_get_font_height(cucul_font_t *); | ||||
| void cucul_render_canvas(cucul_canvas_t *, cucul_font_t *, void *, | |||||
| int cucul_render_canvas(cucul_canvas_t *, cucul_font_t *, void *, | |||||
| unsigned int, unsigned int, unsigned int); | unsigned int, unsigned int, unsigned int); | ||||
| void cucul_free_font(cucul_font_t *); | |||||
| int cucul_free_font(cucul_font_t *); | |||||
| /* @} */ | /* @} */ | ||||
| /** \defgroup importexport libcucul importers/exporters from/to various formats | /** \defgroup importexport libcucul importers/exporters from/to various formats | ||||
| @@ -26,6 +26,9 @@ | |||||
| # include <stdlib.h> | # include <stdlib.h> | ||||
| # include <limits.h> | # include <limits.h> | ||||
| # include <string.h> | # include <string.h> | ||||
| # if defined(HAVE_ERRNO_H) | |||||
| # include <errno.h> | |||||
| # endif | |||||
| #endif | #endif | ||||
| #include "cucul.h" | #include "cucul.h" | ||||
| @@ -236,6 +239,11 @@ static inline void rgb2hsv_default(int r, int g, int b, | |||||
| * cucul_set_dither_palette() function. For depths greater than 8 bits per | * cucul_set_dither_palette() function. For depths greater than 8 bits per | ||||
| * pixel, a zero alpha mask causes the alpha values to be ignored. | * pixel, a zero alpha mask causes the alpha values to be ignored. | ||||
| * | * | ||||
| * If an error occurs, NULL is returned and \b errno is set accordingly: | |||||
| * - \c EINVAL Requested width, height, pitch or bits per pixel value was | |||||
| * invalid. | |||||
| * - \c ENOMEM Not enough memory to allocate dither structure. | |||||
| * | |||||
| * \param bpp Bitmap depth in bits per pixel. | * \param bpp Bitmap depth in bits per pixel. | ||||
| * \param w Bitmap width in pixels. | * \param w Bitmap width in pixels. | ||||
| * \param h Bitmap height in pixels. | * \param h Bitmap height in pixels. | ||||
| @@ -244,7 +252,7 @@ static inline void rgb2hsv_default(int r, int g, int b, | |||||
| * \param gmask Bitmask for green values. | * \param gmask Bitmask for green values. | ||||
| * \param bmask Bitmask for blue values. | * \param bmask Bitmask for blue values. | ||||
| * \param amask Bitmask for alpha values. | * \param amask Bitmask for alpha values. | ||||
| * \return Dither object, or NULL upon error. | |||||
| * \return Dither object upon success, NULL if an error occurred. | |||||
| */ | */ | ||||
| cucul_dither_t *cucul_create_dither(unsigned int bpp, unsigned int w, | cucul_dither_t *cucul_create_dither(unsigned int bpp, unsigned int w, | ||||
| unsigned int h, unsigned int pitch, | unsigned int h, unsigned int pitch, | ||||
| @@ -256,11 +264,21 @@ cucul_dither_t *cucul_create_dither(unsigned int bpp, unsigned int w, | |||||
| /* Minor sanity test */ | /* Minor sanity test */ | ||||
| if(!w || !h || !pitch || bpp > 32 || bpp < 8) | if(!w || !h || !pitch || bpp > 32 || bpp < 8) | ||||
| { | |||||
| #if defined(HAVE_ERRNO_H) | |||||
| errno = EINVAL; | |||||
| #endif | |||||
| return NULL; | return NULL; | ||||
| } | |||||
| d = malloc(sizeof(cucul_dither_t)); | d = malloc(sizeof(cucul_dither_t)); | ||||
| if(!d) | if(!d) | ||||
| { | |||||
| #if defined(HAVE_ERRNO_H) | |||||
| errno = ENOMEM; | |||||
| #endif | |||||
| return NULL; | return NULL; | ||||
| } | |||||
| d->bpp = bpp; | d->bpp = bpp; | ||||
| d->has_palette = 0; | d->has_palette = 0; | ||||
| @@ -325,99 +343,142 @@ cucul_dither_t *cucul_create_dither(unsigned int bpp, unsigned int w, | |||||
| * Set the palette of an 8 bits per pixel bitmap. Values should be between | * Set the palette of an 8 bits per pixel bitmap. Values should be between | ||||
| * 0 and 4095 (0xfff). | * 0 and 4095 (0xfff). | ||||
| * | * | ||||
| * If an error occurs, -1 is returned and \b errno is set accordingly: | |||||
| * - \c EINVAL Dither bits per pixel value is not 8, or one of the pixel | |||||
| * values was outside the range 0 - 4095. | |||||
| * | |||||
| * \param d Dither object. | * \param d Dither object. | ||||
| * \param red Array of 256 red values. | * \param red Array of 256 red values. | ||||
| * \param green Array of 256 green values. | * \param green Array of 256 green values. | ||||
| * \param blue Array of 256 blue values. | * \param blue Array of 256 blue values. | ||||
| * \param alpha Array of 256 alpha values. | * \param alpha Array of 256 alpha values. | ||||
| * \return 0 in case of success, -1 if an error occurred. | |||||
| */ | */ | ||||
| void cucul_set_dither_palette(cucul_dither_t *d, | |||||
| unsigned int red[], unsigned int green[], | |||||
| unsigned int blue[], unsigned int alpha[]) | |||||
| int cucul_set_dither_palette(cucul_dither_t *d, | |||||
| unsigned int red[], unsigned int green[], | |||||
| unsigned int blue[], unsigned int alpha[]) | |||||
| { | { | ||||
| int i, has_alpha = 0; | int i, has_alpha = 0; | ||||
| if(d->bpp != 8) | if(d->bpp != 8) | ||||
| return; | |||||
| { | |||||
| #if defined(HAVE_ERRNO_H) | |||||
| errno = EINVAL; | |||||
| #endif | |||||
| return -1; | |||||
| } | |||||
| for(i = 0; i < 256; i++) | for(i = 0; i < 256; i++) | ||||
| { | { | ||||
| if(red[i] >= 0 && red[i] < 0x1000 && | |||||
| green[i] >= 0 && green[i] < 0x1000 && | |||||
| blue[i] >= 0 && blue[i] < 0x1000 && | |||||
| alpha[i] >= 0 && alpha[i] < 0x1000) | |||||
| if((red[i] | green[i] | blue[i] | alpha[i]) >= 0x1000) | |||||
| { | { | ||||
| d->red[i] = red[i]; | |||||
| d->green[i] = green[i]; | |||||
| d->blue[i] = blue[i]; | |||||
| if(alpha[i]) | |||||
| { | |||||
| d->alpha[i] = alpha[i]; | |||||
| has_alpha = 1; | |||||
| } | |||||
| #if defined(HAVE_ERRNO_H) | |||||
| errno = EINVAL; | |||||
| #endif | |||||
| return -1; | |||||
| } | |||||
| } | |||||
| for(i = 0; i < 256; i++) | |||||
| { | |||||
| d->red[i] = red[i]; | |||||
| d->green[i] = green[i]; | |||||
| d->blue[i] = blue[i]; | |||||
| if(alpha[i]) | |||||
| { | |||||
| d->alpha[i] = alpha[i]; | |||||
| has_alpha = 1; | |||||
| } | } | ||||
| } | } | ||||
| d->has_alpha = has_alpha; | d->has_alpha = has_alpha; | ||||
| return 0; | |||||
| } | } | ||||
| /** \brief Set the brightness of a dither object. | /** \brief Set the brightness of a dither object. | ||||
| * | * | ||||
| * Set the brightness of dither. | * Set the brightness of dither. | ||||
| * | * | ||||
| * If an error occurs, -1 is returned and \b errno is set accordingly: | |||||
| * - \c EINVAL Brightness value was out of range. | |||||
| * | |||||
| * \param d Dither object. | * \param d Dither object. | ||||
| * \param brightness brightness value. | * \param brightness brightness value. | ||||
| * \return 0 in case of success, -1 if an error occurred. | |||||
| */ | */ | ||||
| void cucul_set_dither_brightness(cucul_dither_t *d, float brightness) | |||||
| int cucul_set_dither_brightness(cucul_dither_t *d, float brightness) | |||||
| { | { | ||||
| /* FIXME */ | /* FIXME */ | ||||
| return 0; | |||||
| } | } | ||||
| /** \brief Set the gamma of a dither object. | /** \brief Set the gamma of a dither object. | ||||
| * | * | ||||
| * Set the gamma of dither. | * Set the gamma of dither. | ||||
| * | * | ||||
| * If an error occurs, -1 is returned and \b errno is set accordingly: | |||||
| * - \c EINVAL Gamma value was out of range. | |||||
| * | |||||
| * \param d Dither object. | * \param d Dither object. | ||||
| * \param gamma Gamma value. | * \param gamma Gamma value. | ||||
| * \return 0 in case of success, -1 if an error occurred. | |||||
| */ | */ | ||||
| void cucul_set_dither_gamma(cucul_dither_t *d, float gamma) | |||||
| int cucul_set_dither_gamma(cucul_dither_t *d, float gamma) | |||||
| { | { | ||||
| /* FIXME: we don't need 4096 calls to gammapow(), we can just compute | |||||
| /* FIXME: we don't need 4096 calls to gammapow(), we could just compute | |||||
| * 128 of them and do linear interpolation for the rest. This will | * 128 of them and do linear interpolation for the rest. This will | ||||
| * probably speed up things a lot. */ | * probably speed up things a lot. */ | ||||
| int i; | int i; | ||||
| if(gamma <= 0.0) | if(gamma <= 0.0) | ||||
| return; | |||||
| { | |||||
| #if defined(HAVE_ERRNO_H) | |||||
| errno = EINVAL; | |||||
| #endif | |||||
| return -1; | |||||
| } | |||||
| d->gamma = gamma; | d->gamma = gamma; | ||||
| for(i = 0; i < 4096; i++) | for(i = 0; i < 4096; i++) | ||||
| d->gammatab[i] = 4096.0 * gammapow((float)i / 4096.0, 1.0 / gamma); | d->gammatab[i] = 4096.0 * gammapow((float)i / 4096.0, 1.0 / gamma); | ||||
| return 0; | |||||
| } | } | ||||
| /** \brief Invert colors of dither | /** \brief Invert colors of dither | ||||
| * | * | ||||
| * Invert colors of dither | |||||
| * Invert colors of dither. | |||||
| * | |||||
| * This function never fails. | |||||
| * | * | ||||
| * \param d Dither object. | * \param d Dither object. | ||||
| * \param value 0 for normal behaviour, 1 for invert | * \param value 0 for normal behaviour, 1 for invert | ||||
| * \return This function always returns 0. | |||||
| */ | */ | ||||
| void cucul_set_dither_invert(cucul_dither_t *d, int value) | |||||
| int cucul_set_dither_invert(cucul_dither_t *d, int value) | |||||
| { | { | ||||
| d->invert = value ? 1 : 0; | d->invert = value ? 1 : 0; | ||||
| return 0; | |||||
| } | } | ||||
| /** \brief Set the contrast of a dither object. | /** \brief Set the contrast of a dither object. | ||||
| * | * | ||||
| * Set the contrast of dither. | * Set the contrast of dither. | ||||
| * | * | ||||
| * If an error occurs, -1 is returned and \b errno is set accordingly: | |||||
| * - \c EINVAL Contrast value was out of range. | |||||
| * | |||||
| * \param d Dither object. | * \param d Dither object. | ||||
| * \param contrast contrast value. | * \param contrast contrast value. | ||||
| * \return 0 in case of success, -1 if an error occurred. | |||||
| */ | */ | ||||
| void cucul_set_dither_contrast(cucul_dither_t *d, float contrast) | |||||
| int cucul_set_dither_contrast(cucul_dither_t *d, float contrast) | |||||
| { | { | ||||
| /* FIXME */ | /* FIXME */ | ||||
| return 0; | |||||
| } | } | ||||
| /** \brief Set dither antialiasing | /** \brief Set dither antialiasing | ||||
| @@ -427,19 +488,32 @@ void cucul_set_dither_contrast(cucul_dither_t *d, float contrast) | |||||
| * | * | ||||
| * \li \c "none": no antialiasing. | * \li \c "none": no antialiasing. | ||||
| * | * | ||||
| * \li \c "prefilter": simple prefilter antialiasing. This is the default | |||||
| * value. | |||||
| * \li \c "prefilter" or \c "default": simple prefilter antialiasing. This | |||||
| * is the default value. | |||||
| * | |||||
| * If an error occurs, -1 is returned and \b errno is set accordingly: | |||||
| * - \c EINVAL Invalid antialiasing mode. | |||||
| * | * | ||||
| * \param d Dither object. | * \param d Dither object. | ||||
| * \param str A string describing the antialiasing method that will be used | * \param str A string describing the antialiasing method that will be used | ||||
| * for the dithering. | * for the dithering. | ||||
| * \return 0 in case of success, -1 if an error occurred. | |||||
| */ | */ | ||||
| void cucul_set_dither_antialias(cucul_dither_t *d, char const *str) | |||||
| int cucul_set_dither_antialias(cucul_dither_t *d, char const *str) | |||||
| { | { | ||||
| if(!strcasecmp(str, "none")) | if(!strcasecmp(str, "none")) | ||||
| d->antialias = 0; | d->antialias = 0; | ||||
| else /* "prefilter" is the default */ | |||||
| else if(!strcasecmp(str, "prefilter") || !strcasecmp(str, "default")) | |||||
| d->antialias = 1; | d->antialias = 1; | ||||
| else | |||||
| { | |||||
| #if defined(HAVE_ERRNO_H) | |||||
| errno = EINVAL; | |||||
| #endif | |||||
| return -1; | |||||
| } | |||||
| return 0; | |||||
| } | } | ||||
| /** \brief Get available antialiasing methods | /** \brief Get available antialiasing methods | ||||
| @@ -450,6 +524,8 @@ void cucul_set_dither_antialias(cucul_dither_t *d, char const *str) | |||||
| * cucul_set_dither_antialias(), and a string containing the natural | * cucul_set_dither_antialias(), and a string containing the natural | ||||
| * language description for that antialiasing method. | * language description for that antialiasing method. | ||||
| * | * | ||||
| * This function never fails. | |||||
| * | |||||
| * \param d Dither object. | * \param d Dither object. | ||||
| * \return An array of strings. | * \return An array of strings. | ||||
| */ | */ | ||||
| @@ -485,14 +561,18 @@ char const * const * | |||||
| * \li \c "full8": use the 8 ANSI colours for both the characters and the | * \li \c "full8": use the 8 ANSI colours for both the characters and the | ||||
| * background. | * background. | ||||
| * | * | ||||
| * \li \c "full16": use the 16 ANSI colours for both the characters and the | |||||
| * background. This is the default value. | |||||
| * \li \c "full16" or \c "default": use the 16 ANSI colours for both the | |||||
| * characters and the background. This is the default value. | |||||
| * | |||||
| * If an error occurs, -1 is returned and \b errno is set accordingly: | |||||
| * - \c EINVAL Invalid colour set. | |||||
| * | * | ||||
| * \param d Dither object. | * \param d Dither object. | ||||
| * \param str A string describing the colour set that will be used | * \param str A string describing the colour set that will be used | ||||
| * for the dithering. | * for the dithering. | ||||
| * \return 0 in case of success, -1 if an error occurred. | |||||
| */ | */ | ||||
| void cucul_set_dither_color(cucul_dither_t *d, char const *str) | |||||
| int cucul_set_dither_color(cucul_dither_t *d, char const *str) | |||||
| { | { | ||||
| if(!strcasecmp(str, "mono")) | if(!strcasecmp(str, "mono")) | ||||
| d->color_mode = COLOR_MODE_MONO; | d->color_mode = COLOR_MODE_MONO; | ||||
| @@ -506,8 +586,17 @@ void cucul_set_dither_color(cucul_dither_t *d, char const *str) | |||||
| d->color_mode = COLOR_MODE_FULLGRAY; | d->color_mode = COLOR_MODE_FULLGRAY; | ||||
| else if(!strcasecmp(str, "full8")) | else if(!strcasecmp(str, "full8")) | ||||
| d->color_mode = COLOR_MODE_FULL8; | d->color_mode = COLOR_MODE_FULL8; | ||||
| else /* "full16" is the default */ | |||||
| else if(!strcasecmp(str, "full16") || !strcasecmp(str, "default")) | |||||
| d->color_mode = COLOR_MODE_FULL16; | d->color_mode = COLOR_MODE_FULL16; | ||||
| else | |||||
| { | |||||
| #if defined(HAVE_ERRNO_H) | |||||
| errno = EINVAL; | |||||
| #endif | |||||
| return -1; | |||||
| } | |||||
| return 0; | |||||
| } | } | ||||
| /** \brief Get available colour modes | /** \brief Get available colour modes | ||||
| @@ -518,6 +607,8 @@ void cucul_set_dither_color(cucul_dither_t *d, char const *str) | |||||
| * cucul_set_dither_color(), and a string containing the natural | * cucul_set_dither_color(), and a string containing the natural | ||||
| * language description for that colour mode. | * language description for that colour mode. | ||||
| * | * | ||||
| * This function never fails. | |||||
| * | |||||
| * \param d Dither object. | * \param d Dither object. | ||||
| * \return An array of strings. | * \return An array of strings. | ||||
| */ | */ | ||||
| @@ -544,7 +635,8 @@ char const * const * | |||||
| * Tell the renderer which characters should be used to render the | * Tell the renderer which characters should be used to render the | ||||
| * dither. Valid values for \c str are: | * dither. Valid values for \c str are: | ||||
| * | * | ||||
| * \li \c "ascii": use only ASCII characters. This is the default value. | |||||
| * \li \c "ascii" or "default": use only ASCII characters. This is the | |||||
| * default value. | |||||
| * | * | ||||
| * \li \c "shades": use Unicode characters "U+2591 LIGHT SHADE", "U+2592 | * \li \c "shades": use Unicode characters "U+2591 LIGHT SHADE", "U+2592 | ||||
| * MEDIUM SHADE" and "U+2593 DARK SHADE". These characters are also | * MEDIUM SHADE" and "U+2593 DARK SHADE". These characters are also | ||||
| @@ -553,11 +645,15 @@ char const * const * | |||||
| * \li \c "blocks": use Unicode quarter-cell block combinations. These | * \li \c "blocks": use Unicode quarter-cell block combinations. These | ||||
| * characters are only found in the Unicode set. | * characters are only found in the Unicode set. | ||||
| * | * | ||||
| * If an error occurs, -1 is returned and \b errno is set accordingly: | |||||
| * - \c EINVAL Invalid character set. | |||||
| * | |||||
| * \param d Dither object. | * \param d Dither object. | ||||
| * \param str A string describing the characters that need to be used | * \param str A string describing the characters that need to be used | ||||
| * for the dithering. | * for the dithering. | ||||
| * \return 0 in case of success, -1 if an error occurred. | |||||
| */ | */ | ||||
| void cucul_set_dither_charset(cucul_dither_t *d, char const *str) | |||||
| int cucul_set_dither_charset(cucul_dither_t *d, char const *str) | |||||
| { | { | ||||
| if(!strcasecmp(str, "shades")) | if(!strcasecmp(str, "shades")) | ||||
| { | { | ||||
| @@ -569,11 +665,20 @@ void cucul_set_dither_charset(cucul_dither_t *d, char const *str) | |||||
| d->glyphs = blocks_glyphs; | d->glyphs = blocks_glyphs; | ||||
| d->glyph_count = sizeof(blocks_glyphs) / sizeof(*blocks_glyphs); | d->glyph_count = sizeof(blocks_glyphs) / sizeof(*blocks_glyphs); | ||||
| } | } | ||||
| else /* "ascii" is the default */ | |||||
| else if(!strcasecmp(str, "ascii") || !strcasecmp(str, "default")) | |||||
| { | { | ||||
| d->glyphs = ascii_glyphs; | d->glyphs = ascii_glyphs; | ||||
| d->glyph_count = sizeof(ascii_glyphs) / sizeof(*ascii_glyphs); | d->glyph_count = sizeof(ascii_glyphs) / sizeof(*ascii_glyphs); | ||||
| } | } | ||||
| else | |||||
| { | |||||
| #if defined(HAVE_ERRNO_H) | |||||
| errno = EINVAL; | |||||
| #endif | |||||
| return -1; | |||||
| } | |||||
| return 0; | |||||
| } | } | ||||
| /** \brief Get available dither character sets | /** \brief Get available dither character sets | ||||
| @@ -584,6 +689,8 @@ void cucul_set_dither_charset(cucul_dither_t *d, char const *str) | |||||
| * cucul_set_dither_charset(), and a string containing the natural | * cucul_set_dither_charset(), and a string containing the natural | ||||
| * language description for that character set. | * language description for that character set. | ||||
| * | * | ||||
| * This function never fails. | |||||
| * | |||||
| * \param d Dither object. | * \param d Dither object. | ||||
| * \return An array of strings. | * \return An array of strings. | ||||
| */ | */ | ||||
| @@ -618,11 +725,15 @@ char const * const * cucul_get_dither_charset_list(cucul_dither_t const *d) | |||||
| * | * | ||||
| * \li \c "fstein": use Floyd-Steinberg dithering. This is the default value. | * \li \c "fstein": use Floyd-Steinberg dithering. This is the default value. | ||||
| * | * | ||||
| * If an error occurs, -1 is returned and \b errno is set accordingly: | |||||
| * - \c EINVAL Unknown dithering mode. | |||||
| * | |||||
| * \param d Dither object. | * \param d Dither object. | ||||
| * \param str A string describing the method that needs to be used | * \param str A string describing the method that needs to be used | ||||
| * for the dithering. | * for the dithering. | ||||
| * \return 0 in case of success, -1 if an error occurred. | |||||
| */ | */ | ||||
| void cucul_set_dither_mode(cucul_dither_t *d, char const *str) | |||||
| int cucul_set_dither_mode(cucul_dither_t *d, char const *str) | |||||
| { | { | ||||
| if(!strcasecmp(str, "none")) | if(!strcasecmp(str, "none")) | ||||
| { | { | ||||
| @@ -654,12 +765,21 @@ void cucul_set_dither_mode(cucul_dither_t *d, char const *str) | |||||
| d->get_dither = get_random_dither; | d->get_dither = get_random_dither; | ||||
| d->increment_dither = increment_random_dither; | d->increment_dither = increment_random_dither; | ||||
| } | } | ||||
| else /* "fstein" is the default */ | |||||
| else if(!strcasecmp(str, "fstein") || !strcasecmp(str, "default")) | |||||
| { | { | ||||
| d->init_dither = init_fstein_dither; | d->init_dither = init_fstein_dither; | ||||
| d->get_dither = get_fstein_dither; | d->get_dither = get_fstein_dither; | ||||
| d->increment_dither = increment_fstein_dither; | d->increment_dither = increment_fstein_dither; | ||||
| } | } | ||||
| else | |||||
| { | |||||
| #if defined(HAVE_ERRNO_H) | |||||
| errno = EINVAL; | |||||
| #endif | |||||
| return -1; | |||||
| } | |||||
| return 0; | |||||
| } | } | ||||
| /** \brief Get dithering methods | /** \brief Get dithering methods | ||||
| @@ -670,6 +790,8 @@ void cucul_set_dither_mode(cucul_dither_t *d, char const *str) | |||||
| * cucul_set_dither_dithering(), and a string containing the natural | * cucul_set_dither_dithering(), and a string containing the natural | ||||
| * language description for that dithering method. | * language description for that dithering method. | ||||
| * | * | ||||
| * This function never fails. | |||||
| * | |||||
| * \param d Dither object. | * \param d Dither object. | ||||
| * \return An array of strings. | * \return An array of strings. | ||||
| */ | */ | ||||
| @@ -694,6 +816,8 @@ char const * const * cucul_get_dither_mode_list(cucul_dither_t const *d) | |||||
| * Dither a bitmap at the given coordinates. The dither can be of any size | * Dither a bitmap at the given coordinates. The dither can be of any size | ||||
| * and will be stretched to the text area. | * and will be stretched to the text area. | ||||
| * | * | ||||
| * This function never fails. | |||||
| * | |||||
| * \param cv A handle to the libcucul canvas. | * \param cv A handle to the libcucul canvas. | ||||
| * \param x X coordinate of the upper-left corner of the drawing area. | * \param x X coordinate of the upper-left corner of the drawing area. | ||||
| * \param y Y coordinate of the upper-left corner of the drawing area. | * \param y Y coordinate of the upper-left corner of the drawing area. | ||||
| @@ -701,9 +825,10 @@ char const * const * cucul_get_dither_mode_list(cucul_dither_t const *d) | |||||
| * \param h Height of the drawing area. | * \param h Height of the drawing area. | ||||
| * \param d Dither object to be drawn. | * \param d Dither object to be drawn. | ||||
| * \param pixels Bitmap's pixels. | * \param pixels Bitmap's pixels. | ||||
| * \return This function always returns 0. | |||||
| */ | */ | ||||
| void cucul_dither_bitmap(cucul_canvas_t *cv, int x, int y, int w, int h, | |||||
| cucul_dither_t const *d, void *pixels) | |||||
| int cucul_dither_bitmap(cucul_canvas_t *cv, int x, int y, int w, int h, | |||||
| cucul_dither_t const *d, void *pixels) | |||||
| { | { | ||||
| int *floyd_steinberg, *fs_r, *fs_g, *fs_b; | int *floyd_steinberg, *fs_r, *fs_g, *fs_b; | ||||
| int fs_length; | int fs_length; | ||||
| @@ -711,7 +836,7 @@ void cucul_dither_bitmap(cucul_canvas_t *cv, int x, int y, int w, int h, | |||||
| unsigned int dchmax; | unsigned int dchmax; | ||||
| if(!d || !pixels) | if(!d || !pixels) | ||||
| return; | |||||
| return 0; | |||||
| x1 = x; x2 = x + w - 1; | x1 = x; x2 = x + w - 1; | ||||
| y1 = y; y2 = y + h - 1; | y1 = y; y2 = y + h - 1; | ||||
| @@ -940,20 +1065,27 @@ void cucul_dither_bitmap(cucul_canvas_t *cv, int x, int y, int w, int h, | |||||
| } | } | ||||
| free(floyd_steinberg); | free(floyd_steinberg); | ||||
| return 0; | |||||
| } | } | ||||
| /** \brief Free the memory associated with a dither. | /** \brief Free the memory associated with a dither. | ||||
| * | * | ||||
| * Free the memory allocated by cucul_create_dither(). | * Free the memory allocated by cucul_create_dither(). | ||||
| * | * | ||||
| * This function never fails. | |||||
| * | |||||
| * \param d Dither object. | * \param d Dither object. | ||||
| * \return This function always returns 0. | |||||
| */ | */ | ||||
| void cucul_free_dither(cucul_dither_t *d) | |||||
| int cucul_free_dither(cucul_dither_t *d) | |||||
| { | { | ||||
| if(!d) | if(!d) | ||||
| return; | |||||
| return 0; | |||||
| free(d); | free(d); | ||||
| return 0; | |||||
| } | } | ||||
| /* | /* | ||||
| @@ -20,6 +20,9 @@ | |||||
| #include "common.h" | #include "common.h" | ||||
| #if !defined(__KERNEL__) | #if !defined(__KERNEL__) | ||||
| # if defined(HAVE_ERRNO_H) | |||||
| # include <errno.h> | |||||
| # endif | |||||
| # include <stdlib.h> | # include <stdlib.h> | ||||
| # include <stdio.h> | # include <stdio.h> | ||||
| # include <string.h> | # include <string.h> | ||||
| @@ -63,14 +66,27 @@ static void export_tga(cucul_canvas_t *, cucul_buffer_t *); | |||||
| * | * | ||||
| * \li \c "tga": export a TGA image. | * \li \c "tga": export a TGA image. | ||||
| * | * | ||||
| * If an error occurs, NULL is returned and \b errno is set accordingly: | |||||
| * - \c EINVAL Invalid format requested. | |||||
| * - \c ENOMEM Not enough memory to allocate output buffer. | |||||
| * | |||||
| * \param cv A libcucul canvas | * \param cv A libcucul canvas | ||||
| * \param format A string describing the requested output format. | * \param format A string describing the requested output format. | ||||
| * \return A libcucul buffer, or NULL in case of error. | |||||
| */ | */ | ||||
| cucul_buffer_t * cucul_export_canvas(cucul_canvas_t *cv, char const *format) | cucul_buffer_t * cucul_export_canvas(cucul_canvas_t *cv, char const *format) | ||||
| { | { | ||||
| cucul_buffer_t *ex; | cucul_buffer_t *ex; | ||||
| ex = malloc(sizeof(cucul_buffer_t)); | ex = malloc(sizeof(cucul_buffer_t)); | ||||
| if(!ex) | |||||
| { | |||||
| #if defined(HAVE_ERRNO_H) | |||||
| errno = ENOMEM; | |||||
| #endif | |||||
| return NULL; | |||||
| } | |||||
| ex->size = 0; | ex->size = 0; | ||||
| ex->data = NULL; | ex->data = NULL; | ||||
| ex->user_data = 0; | ex->user_data = 0; | ||||
| @@ -95,6 +111,9 @@ cucul_buffer_t * cucul_export_canvas(cucul_canvas_t *cv, char const *format) | |||||
| if(ex->size == 0) | if(ex->size == 0) | ||||
| { | { | ||||
| free(ex); | free(ex); | ||||
| #if defined(HAVE_ERRNO_H) | |||||
| errno = EINVAL; | |||||
| #endif | |||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| @@ -108,6 +127,8 @@ cucul_buffer_t * cucul_export_canvas(cucul_canvas_t *cv, char const *format) | |||||
| * the export format, to be used with cucul_export_canvas(), and a string | * the export format, to be used with cucul_export_canvas(), and a string | ||||
| * containing the natural language description for that export format. | * containing the natural language description for that export format. | ||||
| * | * | ||||
| * This function never fails. | |||||
| * | |||||
| * \return An array of strings. | * \return An array of strings. | ||||
| */ | */ | ||||
| char const * const * cucul_get_export_list(void) | char const * const * cucul_get_export_list(void) | ||||
| @@ -27,6 +27,9 @@ | |||||
| # elif defined(HAVE_NETINET_IN_H) | # elif defined(HAVE_NETINET_IN_H) | ||||
| # include <netinet/in.h> | # include <netinet/in.h> | ||||
| # endif | # endif | ||||
| # if defined(HAVE_ERRNO_H) | |||||
| # include <errno.h> | |||||
| # endif | |||||
| # include <stdio.h> | # include <stdio.h> | ||||
| # include <stdlib.h> | # include <stdlib.h> | ||||
| # include <string.h> | # include <string.h> | ||||
| @@ -108,6 +111,11 @@ DECLARE_UNPACKGLYPH(1) | |||||
| * are loaded as a font. This memory are must not be freed by the calling | * are loaded as a font. This memory are must not be freed by the calling | ||||
| * program until the font handle has been freed with cucul_free_font(). | * program until the font handle has been freed with cucul_free_font(). | ||||
| * | * | ||||
| * If an error occurs, NULL is returned and \b errno is set accordingly: | |||||
| * - \c ENOENT Requested built-in font does not exist. | |||||
| * - \c EINVAL Invalid font data in memory area. | |||||
| * - \c ENOMEM Not enough memory to allocate font structure. | |||||
| * | |||||
| * \param data The memory area containing the font or its name. | * \param data The memory area containing the font or its name. | ||||
| * \param size The size of the memory area, or 0 if the font name is given. | * \param size The size of the memory area, or 0 if the font name is given. | ||||
| * \return A font handle or NULL in case of error. | * \return A font handle or NULL in case of error. | ||||
| @@ -126,13 +134,29 @@ cucul_font_t *cucul_load_font(void const *data, unsigned int size) | |||||
| return cucul_load_font(monobold12_data, monobold12_size); | return cucul_load_font(monobold12_data, monobold12_size); | ||||
| #endif | #endif | ||||
| #if defined(HAVE_ERRNO_H) | |||||
| errno = ENOENT; | |||||
| #endif | |||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| if(size < sizeof(struct font_header)) | if(size < sizeof(struct font_header)) | ||||
| { | |||||
| #if defined(HAVE_ERRNO_H) | |||||
| errno = EINVAL; | |||||
| #endif | |||||
| return NULL; | return NULL; | ||||
| } | |||||
| f = malloc(sizeof(cucul_font_t)); | f = malloc(sizeof(cucul_font_t)); | ||||
| if(!f) | |||||
| { | |||||
| #if defined(HAVE_ERRNO_H) | |||||
| errno = ENOMEM; | |||||
| #endif | |||||
| return NULL; | |||||
| } | |||||
| f->private = (void *)(uintptr_t)data; | f->private = (void *)(uintptr_t)data; | ||||
| memcpy(&f->header, f->private + 8, sizeof(struct font_header)); | memcpy(&f->header, f->private + 8, sizeof(struct font_header)); | ||||
| @@ -152,10 +176,22 @@ cucul_font_t *cucul_load_font(void const *data, unsigned int size) | |||||
| || (f->header.flags & 1) == 0) | || (f->header.flags & 1) == 0) | ||||
| { | { | ||||
| free(f); | free(f); | ||||
| #if defined(HAVE_ERRNO_H) | |||||
| errno = EINVAL; | |||||
| #endif | |||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| f->block_list = malloc(f->header.blocks * sizeof(struct block_info)); | f->block_list = malloc(f->header.blocks * sizeof(struct block_info)); | ||||
| if(!f->block_list) | |||||
| { | |||||
| free(f); | |||||
| #if defined(HAVE_ERRNO_H) | |||||
| errno = ENOMEM; | |||||
| #endif | |||||
| return NULL; | |||||
| } | |||||
| memcpy(f->block_list, | memcpy(f->block_list, | ||||
| f->private + 8 + sizeof(struct font_header), | f->private + 8 + sizeof(struct font_header), | ||||
| f->header.blocks * sizeof(struct block_info)); | f->header.blocks * sizeof(struct block_info)); | ||||
| @@ -171,11 +207,24 @@ cucul_font_t *cucul_load_font(void const *data, unsigned int size) | |||||
| { | { | ||||
| free(f->block_list); | free(f->block_list); | ||||
| free(f); | free(f); | ||||
| #if defined(HAVE_ERRNO_H) | |||||
| errno = EINVAL; | |||||
| #endif | |||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| } | } | ||||
| f->glyph_list = malloc(f->header.glyphs * sizeof(struct glyph_info)); | f->glyph_list = malloc(f->header.glyphs * sizeof(struct glyph_info)); | ||||
| if(!f->glyph_list) | |||||
| { | |||||
| free(f->block_list); | |||||
| free(f); | |||||
| #if defined(HAVE_ERRNO_H) | |||||
| errno = ENOMEM; | |||||
| #endif | |||||
| return NULL; | |||||
| } | |||||
| memcpy(f->glyph_list, | memcpy(f->glyph_list, | ||||
| f->private + 8 + sizeof(struct font_header) | f->private + 8 + sizeof(struct font_header) | ||||
| + f->header.blocks * sizeof(struct block_info), | + f->header.blocks * sizeof(struct block_info), | ||||
| @@ -194,6 +243,9 @@ cucul_font_t *cucul_load_font(void const *data, unsigned int size) | |||||
| free(f->glyph_list); | free(f->glyph_list); | ||||
| free(f->block_list); | free(f->block_list); | ||||
| free(f); | free(f); | ||||
| #if defined(HAVE_ERRNO_H) | |||||
| errno = EINVAL; | |||||
| #endif | |||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| } | } | ||||
| @@ -208,6 +260,8 @@ cucul_font_t *cucul_load_font(void const *data, unsigned int size) | |||||
| * Return a list of available builtin fonts. The list is a NULL-terminated | * Return a list of available builtin fonts. The list is a NULL-terminated | ||||
| * array of strings. | * array of strings. | ||||
| * | * | ||||
| * This function never fails. | |||||
| * | |||||
| * \return An array of strings. | * \return An array of strings. | ||||
| */ | */ | ||||
| char const * const * cucul_get_font_list(void) | char const * const * cucul_get_font_list(void) | ||||
| @@ -226,6 +280,8 @@ char const * const * cucul_get_font_list(void) | |||||
| * | * | ||||
| * This function returns the maximum value for the current font's glyphs | * This function returns the maximum value for the current font's glyphs | ||||
| * | * | ||||
| * This function never fails. | |||||
| * | |||||
| * \param f The font, as returned by cucul_load_font() | * \param f The font, as returned by cucul_load_font() | ||||
| * \return The maximum glyph width. | * \return The maximum glyph width. | ||||
| */ | */ | ||||
| @@ -238,6 +294,8 @@ unsigned int cucul_get_font_width(cucul_font_t *f) | |||||
| * | * | ||||
| * This function returns the maximum value for the current font's glyphs | * This function returns the maximum value for the current font's glyphs | ||||
| * | * | ||||
| * This function never fails. | |||||
| * | |||||
| * \param f The font, as returned by cucul_load_font() | * \param f The font, as returned by cucul_load_font() | ||||
| * \return The maximum glyph height. | * \return The maximum glyph height. | ||||
| */ | */ | ||||
| @@ -253,13 +311,18 @@ unsigned int cucul_get_font_height(cucul_font_t *f) | |||||
| * this function has returned, the memory area that was given to | * this function has returned, the memory area that was given to | ||||
| * cucul_load_font() can be freed. | * cucul_load_font() can be freed. | ||||
| * | * | ||||
| * This function never fails. | |||||
| * | |||||
| * \param f The font, as returned by cucul_load_font() | * \param f The font, as returned by cucul_load_font() | ||||
| * \return This function always returns 0. | |||||
| */ | */ | ||||
| void cucul_free_font(cucul_font_t *f) | |||||
| int cucul_free_font(cucul_font_t *f) | |||||
| { | { | ||||
| free(f->glyph_list); | free(f->glyph_list); | ||||
| free(f->block_list); | free(f->block_list); | ||||
| free(f); | free(f); | ||||
| return 0; | |||||
| } | } | ||||
| /** \brief Render the canvas onto an image buffer. | /** \brief Render the canvas onto an image buffer. | ||||
| @@ -275,16 +338,19 @@ void cucul_free_font(cucul_font_t *f) | |||||
| * Glyphs that do not fit in the image buffer are currently not rendered at | * Glyphs that do not fit in the image buffer are currently not rendered at | ||||
| * all. They may be cropped instead in future versions. | * all. They may be cropped instead in future versions. | ||||
| * | * | ||||
| * This function never fails. | |||||
| * | |||||
| * \param cv The canvas to render | * \param cv The canvas to render | ||||
| * \param f The font, as returned by cucul_load_font() | * \param f The font, as returned by cucul_load_font() | ||||
| * \param buf The image buffer | * \param buf The image buffer | ||||
| * \param width The width (in pixels) of the image buffer | * \param width The width (in pixels) of the image buffer | ||||
| * \param height The height (in pixels) of the image buffer | * \param height The height (in pixels) of the image buffer | ||||
| * \param pitch The pitch (in bytes) of an image buffer line. | * \param pitch The pitch (in bytes) of an image buffer line. | ||||
| * \return This function always returns 0. | |||||
| */ | */ | ||||
| void cucul_render_canvas(cucul_canvas_t *cv, cucul_font_t *f, | |||||
| void *buf, unsigned int width, | |||||
| unsigned int height, unsigned int pitch) | |||||
| int cucul_render_canvas(cucul_canvas_t *cv, cucul_font_t *f, | |||||
| void *buf, unsigned int width, | |||||
| unsigned int height, unsigned int pitch) | |||||
| { | { | ||||
| uint8_t *glyph = NULL; | uint8_t *glyph = NULL; | ||||
| unsigned int x, y, xmax, ymax; | unsigned int x, y, xmax, ymax; | ||||
| @@ -379,6 +445,8 @@ void cucul_render_canvas(cucul_canvas_t *cv, cucul_font_t *f, | |||||
| if(f->header.bpp != 8) | if(f->header.bpp != 8) | ||||
| free(glyph); | free(glyph); | ||||
| return 0; | |||||
| } | } | ||||
| /* | /* | ||||
| @@ -19,6 +19,9 @@ | |||||
| #include "common.h" | #include "common.h" | ||||
| #if !defined(__KERNEL__) | #if !defined(__KERNEL__) | ||||
| # if defined(HAVE_ERRNO_H) | |||||
| # include <errno.h> | |||||
| # endif | |||||
| # include <stdio.h> | # include <stdio.h> | ||||
| # include <stdlib.h> | # include <stdlib.h> | ||||
| # include <string.h> | # include <string.h> | ||||
| @@ -43,8 +46,8 @@ static void ansi_parse_grcm(cucul_canvas_t *, struct ansi_grcm *, | |||||
| /** \brief Import a buffer into a canvas | /** \brief Import a buffer into a canvas | ||||
| * | * | ||||
| * This function imports a libcucul buffer (cucul_load_memory()/cucul_load_file()) | |||||
| * into an internal libcucul canvas. | |||||
| * This function imports a libcucul buffer as returned by cucul_load_memory() | |||||
| * or cucul_load_file() into an internal libcucul canvas. | |||||
| * | * | ||||
| * Valid values for \c format are: | * Valid values for \c format are: | ||||
| * | * | ||||
| @@ -54,6 +57,10 @@ static void ansi_parse_grcm(cucul_canvas_t *, struct ansi_grcm *, | |||||
| * | * | ||||
| * \li \c "caca": import native libcaca files. | * \li \c "caca": import native libcaca files. | ||||
| * | * | ||||
| * If an error occurs, NULL is returned and \b errno is set accordingly: | |||||
| * - \c ENOMEM Not enough memory to allocate canvas. | |||||
| * - \c EINVAL Invalid format requested. | |||||
| * | |||||
| * \param buffer A \e libcucul buffer containing the data to be loaded | * \param buffer A \e libcucul buffer containing the data to be loaded | ||||
| * into a canvas. | * into a canvas. | ||||
| * \param format A string describing the input format. | * \param format A string describing the input format. | ||||
| @@ -63,9 +70,6 @@ cucul_canvas_t * cucul_import_canvas(cucul_buffer_t *buffer, char const *format) | |||||
| { | { | ||||
| char const *buf = (char const*)buffer->data; | char const *buf = (char const*)buffer->data; | ||||
| if(buffer->size == 0 || buffer->data == NULL) | |||||
| return NULL; | |||||
| if(!strcasecmp("caca", format)) | if(!strcasecmp("caca", format)) | ||||
| return import_caca(buffer->data, buffer->size); | return import_caca(buffer->data, buffer->size); | ||||
| if(!strcasecmp("text", format)) | if(!strcasecmp("text", format)) | ||||
| @@ -75,24 +79,26 @@ cucul_canvas_t * cucul_import_canvas(cucul_buffer_t *buffer, char const *format) | |||||
| /* Autodetection */ | /* Autodetection */ | ||||
| if(!strcasecmp("", format)) | if(!strcasecmp("", format)) | ||||
| { | |||||
| unsigned int i=0; | |||||
| /* if 4 first letters are CACA */ | |||||
| if(buffer->size >= 4 && | |||||
| buf[0] == 'C' && buf[1] == 'A' && buf[2] == 'C' && buf[3] != 'A') | |||||
| return import_caca(buffer->data, buffer->size); | |||||
| /* If we find ESC[ argv, we guess it's an ANSI file */ | |||||
| while(i < buffer->size - 1) | |||||
| { | |||||
| if((buf[i] == 0x1b) && (buf[i+1] == '[')) | |||||
| return import_ansi(buffer->data, buffer->size); | |||||
| i++; | |||||
| } | |||||
| { | |||||
| unsigned int i; | |||||
| /* Otherwise, import it as text */ | |||||
| return import_text(buffer->data, buffer->size); | |||||
| } | |||||
| /* If 4 first letters are CACA */ | |||||
| if(buffer->size >= 4 && | |||||
| buf[0] == 'C' && buf[1] == 'A' && buf[2] == 'C' && buf[3] != 'A') | |||||
| return import_caca(buffer->data, buffer->size); | |||||
| /* If we find ESC[ argv, we guess it's an ANSI file */ | |||||
| for(i = 0; i < buffer->size - 1; i++) | |||||
| if((buf[i] == 0x1b) && (buf[i + 1] == '[')) | |||||
| return import_ansi(buffer->data, buffer->size); | |||||
| /* Otherwise, import it as text */ | |||||
| return import_text(buffer->data, buffer->size); | |||||
| } | |||||
| #if defined(HAVE_ERRNO_H) | |||||
| errno = EINVAL; | |||||
| #endif | |||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| @@ -103,6 +109,8 @@ cucul_canvas_t * cucul_import_canvas(cucul_buffer_t *buffer, char const *format) | |||||
| * the import format, to be used with cucul_import_canvas(), and a string | * the import format, to be used with cucul_import_canvas(), and a string | ||||
| * containing the natural language description for that import format. | * containing the natural language description for that import format. | ||||
| * | * | ||||
| * This function never fails. | |||||
| * | |||||
| * \return An array of strings. | * \return An array of strings. | ||||
| */ | */ | ||||
| char const * const * cucul_get_import_list(void) | char const * const * cucul_get_import_list(void) | ||||
| @@ -130,13 +138,13 @@ static cucul_canvas_t *import_caca(void const *data, unsigned int size) | |||||
| unsigned int width, height, n; | unsigned int width, height, n; | ||||
| if(size < 16) | if(size < 16) | ||||
| return NULL; | |||||
| goto invalid_caca; | |||||
| if(buf[0] != 'C' || buf[1] != 'A' || buf[2] != 'C' || buf[3] != 'A') | if(buf[0] != 'C' || buf[1] != 'A' || buf[2] != 'C' || buf[3] != 'A') | ||||
| return NULL; | |||||
| goto invalid_caca; | |||||
| if(buf[4] != 'C' || buf[5] != 'A' || buf[6] != 'N' || buf[7] != 'V') | if(buf[4] != 'C' || buf[5] != 'A' || buf[6] != 'N' || buf[7] != 'V') | ||||
| return NULL; | |||||
| goto invalid_caca; | |||||
| width = ((uint32_t)buf[8] << 24) | ((uint32_t)buf[9] << 16) | width = ((uint32_t)buf[8] << 24) | ((uint32_t)buf[9] << 16) | ||||
| | ((uint32_t)buf[10] << 8) | (uint32_t)buf[11]; | | ((uint32_t)buf[10] << 8) | (uint32_t)buf[11]; | ||||
| @@ -144,15 +152,20 @@ static cucul_canvas_t *import_caca(void const *data, unsigned int size) | |||||
| | ((uint32_t)buf[14] << 8) | (uint32_t)buf[15]; | | ((uint32_t)buf[14] << 8) | (uint32_t)buf[15]; | ||||
| if(!width || !height) | if(!width || !height) | ||||
| return NULL; | |||||
| goto invalid_caca; | |||||
| if(size != 16 + width * height * 8) | if(size != 16 + width * height * 8) | ||||
| return NULL; | |||||
| goto invalid_caca; | |||||
| cv = cucul_create_canvas(width, height); | cv = cucul_create_canvas(width, height); | ||||
| if(!cv) | if(!cv) | ||||
| { | |||||
| #if defined(HAVE_ERRNO_H) | |||||
| errno = ENOMEM; | |||||
| #endif | |||||
| return NULL; | return NULL; | ||||
| } | |||||
| for(n = height * width; n--; ) | for(n = height * width; n--; ) | ||||
| { | { | ||||
| @@ -167,6 +180,12 @@ static cucul_canvas_t *import_caca(void const *data, unsigned int size) | |||||
| } | } | ||||
| return cv; | return cv; | ||||
| invalid_caca: | |||||
| #if defined(HAVE_ERRNO_H) | |||||
| errno = EINVAL; | |||||
| #endif | |||||
| return NULL; | |||||
| } | } | ||||
| static cucul_canvas_t *import_text(void const *data, unsigned int size) | static cucul_canvas_t *import_text(void const *data, unsigned int size) | ||||
| @@ -176,37 +195,45 @@ static cucul_canvas_t *import_text(void const *data, unsigned int size) | |||||
| unsigned int width = 1, height = 1, x = 0, y = 0, i; | unsigned int width = 1, height = 1, x = 0, y = 0, i; | ||||
| cv = cucul_create_canvas(width, height); | cv = cucul_create_canvas(width, height); | ||||
| if(!cv) | |||||
| { | |||||
| #if defined(HAVE_ERRNO_H) | |||||
| errno = ENOMEM; | |||||
| #endif | |||||
| return NULL; | |||||
| } | |||||
| cucul_set_color(cv, CUCUL_COLOR_DEFAULT, CUCUL_COLOR_TRANSPARENT); | cucul_set_color(cv, CUCUL_COLOR_DEFAULT, CUCUL_COLOR_TRANSPARENT); | ||||
| for(i = 0; i < size; i++) | for(i = 0; i < size; i++) | ||||
| { | |||||
| unsigned char ch = *text++; | |||||
| { | |||||
| unsigned char ch = *text++; | |||||
| if(ch == '\r') | |||||
| continue; | |||||
| if(ch == '\r') | |||||
| continue; | |||||
| if(ch == '\n') | |||||
| { | |||||
| x = 0; | |||||
| y++; | |||||
| continue; | |||||
| } | |||||
| if(x >= width || y >= height) | |||||
| { | |||||
| if(x >= width) | |||||
| width = x + 1; | |||||
| if(ch == '\n') | |||||
| { | |||||
| x = 0; | |||||
| y++; | |||||
| continue; | |||||
| } | |||||
| if(y >= height) | |||||
| height = y + 1; | |||||
| if(x >= width || y >= height) | |||||
| { | |||||
| if(x >= width) | |||||
| width = x + 1; | |||||
| cucul_set_canvas_size(cv, width, height); | |||||
| } | |||||
| if(y >= height) | |||||
| height = y + 1; | |||||
| cucul_putchar(cv, x, y, ch); | |||||
| x++; | |||||
| cucul_set_canvas_size(cv, width, height); | |||||
| } | } | ||||
| cucul_putchar(cv, x, y, ch); | |||||
| x++; | |||||
| } | |||||
| return cv; | return cv; | ||||
| } | } | ||||
| @@ -220,158 +247,166 @@ static cucul_canvas_t *import_ansi(void const *data, unsigned int size) | |||||
| int x = 0, y = 0, save_x = 0, save_y = 0; | int x = 0, y = 0, save_x = 0, save_y = 0; | ||||
| cv = cucul_create_canvas(width, height); | cv = cucul_create_canvas(width, height); | ||||
| if(!cv) | |||||
| { | |||||
| #if defined(HAVE_ERRNO_H) | |||||
| errno = ENOMEM; | |||||
| #endif | |||||
| return NULL; | |||||
| } | |||||
| ansi_parse_grcm(cv, &grcm, 1, &dummy); | ansi_parse_grcm(cv, &grcm, 1, &dummy); | ||||
| for(i = 0; i < size; i += skip) | for(i = 0; i < size; i += skip) | ||||
| { | |||||
| skip = 1; | |||||
| /* Wrap long lines */ | |||||
| if((unsigned int)x >= width) | |||||
| { | { | ||||
| skip = 1; | |||||
| x = 0; | |||||
| y++; | |||||
| } | |||||
| /* Wrap long lines */ | |||||
| if((unsigned int)x >= width) | |||||
| { | |||||
| x = 0; | |||||
| y++; | |||||
| } | |||||
| if(buffer[i] == '\x1a' && size - i >= 8 | |||||
| && !memcmp(buffer + i + 1, "SAUCE00", 7)) | |||||
| break; /* End before SAUCE data */ | |||||
| if(buffer[i] == '\x1a' && size - i >= 8 | |||||
| && !memcmp(buffer + i + 1, "SAUCE00", 7)) | |||||
| break; /* End before SAUCE data */ | |||||
| if(buffer[i] == '\r') | |||||
| continue; /* DOS sucks */ | |||||
| if(buffer[i] == '\r') | |||||
| continue; /* DOS sucks */ | |||||
| if(buffer[i] == '\n') | |||||
| { | |||||
| x = 0; | |||||
| y++; | |||||
| continue; | |||||
| } | |||||
| if(buffer[i] == '\n') | |||||
| { | |||||
| x = 0; | |||||
| y++; | |||||
| continue; | |||||
| } | |||||
| /* Interpret escape commands, as per Standard ECMA-48 "Control | |||||
| * Functions for Coded Character Sets", 5.4. Control sequences. */ | |||||
| if(buffer[i] == '\x1b' && buffer[i + 1] == '[') | |||||
| { | |||||
| unsigned int argc = 0, argv[101]; | |||||
| unsigned int param, inter, final; | |||||
| /* Compute offsets to parameter bytes, intermediate bytes and | |||||
| * to the final byte. Only the final byte is mandatory, there | |||||
| * can be zero of the others. | |||||
| * 0 param=2 inter final final+1 | |||||
| * +-----+------------------+---------------------+-----------------+ | |||||
| * | CSI | parameter bytes | intermediate bytes | final byte | | |||||
| * | | 0x30 - 0x3f | 0x20 - 0x2f | 0x40 - 0x7e | | |||||
| * | ^[[ | 0123456789:;<=>? | SPC !"#$%&'()*+,-./ | azAZ@[\]^_`{|}~ | | |||||
| * +-----+------------------+---------------------+-----------------+ | |||||
| */ | |||||
| param = 2; | |||||
| for(inter = param; i + inter < size; inter++) | |||||
| if(buffer[i + inter] < 0x30 || buffer[i + inter] > 0x3f) | |||||
| break; | |||||
| /* Interpret escape commands, as per Standard ECMA-48 "Control | |||||
| * Functions for Coded Character Sets", 5.4. Control sequences. */ | |||||
| if(buffer[i] == '\x1b' && buffer[i + 1] == '[') | |||||
| { | |||||
| unsigned int argc = 0, argv[101]; | |||||
| unsigned int param, inter, final; | |||||
| /* Compute offsets to parameter bytes, intermediate bytes and | |||||
| * to the final byte. Only the final byte is mandatory, there | |||||
| * can be zero of the others. | |||||
| * 0 param=2 inter final final+1 | |||||
| * +-----+------------------+---------------------+-----------------+ | |||||
| * | CSI | parameter bytes | intermediate bytes | final byte | | |||||
| * | | 0x30 - 0x3f | 0x20 - 0x2f | 0x40 - 0x7e | | |||||
| * | ^[[ | 0123456789:;<=>? | SPC !"#$%&'()*+,-./ | azAZ@[\]^_`{|}~ | | |||||
| * +-----+------------------+---------------------+-----------------+ | |||||
| */ | |||||
| param = 2; | |||||
| for(inter = param; i + inter < size; inter++) | |||||
| if(buffer[i + inter] < 0x30 || buffer[i + inter] > 0x3f) | |||||
| break; | |||||
| for(final = inter; i + final < size; final++) | |||||
| if(buffer[i + final] < 0x20 || buffer[i + final] > 0x2f) | |||||
| break; | |||||
| if(buffer[i + final] < 0x40 || buffer[i + final] > 0x7e) | |||||
| break; /* Invalid Final Byte */ | |||||
| skip += final; | |||||
| /* Sanity checks */ | |||||
| if(param < inter && buffer[i + param] >= 0x3c) | |||||
| { | |||||
| fprintf(stderr, "private sequence \"^[[%.*s\"\n", | |||||
| final - param + 1, buffer + i + param); | |||||
| continue; /* Private sequence, skip it entirely */ | |||||
| } | |||||
| if(final - param > 100) | |||||
| continue; /* Suspiciously long sequence, skip it */ | |||||
| /* Parse parameter bytes as per ECMA-48 5.4.2: Parameter string | |||||
| * format */ | |||||
| if(param < inter) | |||||
| { | |||||
| argv[0] = 0; | |||||
| for(j = param; j < inter; j++) | |||||
| { | |||||
| if(buffer[i + j] == ';') | |||||
| argv[++argc] = 0; | |||||
| else if(buffer[i + j] >= '0' && buffer[i + j] <= '9') | |||||
| argv[argc] = 10 * argv[argc] + (buffer[i + j] - '0'); | |||||
| } | |||||
| argc++; | |||||
| } | |||||
| /* Interpret final byte. The code representations are given in | |||||
| * ECMA-48 5.4: Control sequences, and the code definitions are | |||||
| * given in ECMA-48 8.3: Definition of control functions. */ | |||||
| switch(buffer[i + final]) | |||||
| { | |||||
| case 'f': /* CUP - Cursor Position */ | |||||
| case 'H': /* HVP - Character And Line Position */ | |||||
| x = (argc > 1) ? argv[1] - 1 : 0; | |||||
| y = (argc > 0) ? argv[0] - 1 : 0; | |||||
| break; | |||||
| case 'A': /* CUU - Cursor Up */ | |||||
| y -= argc ? argv[0] : 1; | |||||
| if(y < 0) | |||||
| y = 0; | |||||
| break; | |||||
| case 'B': /* CUD - Cursor Down */ | |||||
| y += argc ? argv[0] : 1; | |||||
| break; | |||||
| case 'C': /* CUF - Cursor Right */ | |||||
| x += argc ? argv[0] : 1; | |||||
| break; | |||||
| case 'D': /* CUB - Cursor Left */ | |||||
| x -= argc ? argv[0] : 1; | |||||
| if(x < 0) | |||||
| x = 0; | |||||
| break; | |||||
| case 's': /* Private (save cursor position) */ | |||||
| save_x = x; | |||||
| save_y = y; | |||||
| break; | |||||
| case 'u': /* Private (reload cursor positin) */ | |||||
| x = save_x; | |||||
| y = save_y; | |||||
| break; | |||||
| case 'J': /* ED - Erase In Page */ | |||||
| if(argv[0] == 2) | |||||
| x = y = 0; | |||||
| break; | |||||
| case 'K': /* EL - Erase In Line */ | |||||
| for(j = x; j < width; j++) | |||||
| _cucul_putchar32(cv, j, y, (uint32_t)' '); | |||||
| x = width; | |||||
| break; | |||||
| case 'm': /* SGR - Select Graphic Rendition */ | |||||
| ansi_parse_grcm(cv, &grcm, argc, argv); | |||||
| break; | |||||
| default: | |||||
| fprintf(stderr, "unknown command %c\n", buffer[i + final]); | |||||
| break; | |||||
| } | |||||
| continue; | |||||
| } | |||||
| for(final = inter; i + final < size; final++) | |||||
| if(buffer[i + final] < 0x20 || buffer[i + final] > 0x2f) | |||||
| break; | |||||
| if(buffer[i + final] < 0x40 || buffer[i + final] > 0x7e) | |||||
| break; /* Invalid Final Byte */ | |||||
| skip += final; | |||||
| /* Sanity checks */ | |||||
| if(param < inter && buffer[i + param] >= 0x3c) | |||||
| { | |||||
| fprintf(stderr, "private sequence \"^[[%.*s\"\n", | |||||
| final - param + 1, buffer + i + param); | |||||
| continue; /* Private sequence, skip it entirely */ | |||||
| } | |||||
| /* We're going to paste a character. First make sure the canvas | |||||
| * is big enough. */ | |||||
| if((unsigned int)y >= height) | |||||
| if(final - param > 100) | |||||
| continue; /* Suspiciously long sequence, skip it */ | |||||
| /* Parse parameter bytes as per ECMA-48 5.4.2: Parameter string | |||||
| * format */ | |||||
| if(param < inter) | |||||
| { | |||||
| argv[0] = 0; | |||||
| for(j = param; j < inter; j++) | |||||
| { | { | ||||
| height = y + 1; | |||||
| cucul_set_canvas_size(cv, width, height); | |||||
| if(buffer[i + j] == ';') | |||||
| argv[++argc] = 0; | |||||
| else if(buffer[i + j] >= '0' && buffer[i + j] <= '9') | |||||
| argv[argc] = 10 * argv[argc] + (buffer[i + j] - '0'); | |||||
| } | } | ||||
| argc++; | |||||
| } | |||||
| /* Interpret final byte. The code representations are given in | |||||
| * ECMA-48 5.4: Control sequences, and the code definitions are | |||||
| * given in ECMA-48 8.3: Definition of control functions. */ | |||||
| switch(buffer[i + final]) | |||||
| { | |||||
| case 'f': /* CUP - Cursor Position */ | |||||
| case 'H': /* HVP - Character And Line Position */ | |||||
| x = (argc > 1) ? argv[1] - 1 : 0; | |||||
| y = (argc > 0) ? argv[0] - 1 : 0; | |||||
| break; | |||||
| case 'A': /* CUU - Cursor Up */ | |||||
| y -= argc ? argv[0] : 1; | |||||
| if(y < 0) | |||||
| y = 0; | |||||
| break; | |||||
| case 'B': /* CUD - Cursor Down */ | |||||
| y += argc ? argv[0] : 1; | |||||
| break; | |||||
| case 'C': /* CUF - Cursor Right */ | |||||
| x += argc ? argv[0] : 1; | |||||
| break; | |||||
| case 'D': /* CUB - Cursor Left */ | |||||
| x -= argc ? argv[0] : 1; | |||||
| if(x < 0) | |||||
| x = 0; | |||||
| break; | |||||
| case 's': /* Private (save cursor position) */ | |||||
| save_x = x; | |||||
| save_y = y; | |||||
| break; | |||||
| case 'u': /* Private (reload cursor positin) */ | |||||
| x = save_x; | |||||
| y = save_y; | |||||
| break; | |||||
| case 'J': /* ED - Erase In Page */ | |||||
| if(argv[0] == 2) | |||||
| x = y = 0; | |||||
| break; | |||||
| case 'K': /* EL - Erase In Line */ | |||||
| for(j = x; j < width; j++) | |||||
| _cucul_putchar32(cv, j, y, (uint32_t)' '); | |||||
| x = width; | |||||
| break; | |||||
| case 'm': /* SGR - Select Graphic Rendition */ | |||||
| ansi_parse_grcm(cv, &grcm, argc, argv); | |||||
| break; | |||||
| default: | |||||
| fprintf(stderr, "unknown command %c\n", buffer[i + final]); | |||||
| break; | |||||
| } | |||||
| continue; | |||||
| } | |||||
| /* Now paste our character */ | |||||
| _cucul_putchar32(cv, x, y, _cucul_cp437_to_utf32(buffer[i])); | |||||
| x++; | |||||
| /* We're going to paste a character. First make sure the canvas | |||||
| * is big enough. */ | |||||
| if((unsigned int)y >= height) | |||||
| { | |||||
| height = y + 1; | |||||
| cucul_set_canvas_size(cv, width, height); | |||||
| } | } | ||||
| /* Now paste our character */ | |||||
| _cucul_putchar32(cv, x, y, _cucul_cp437_to_utf32(buffer[i])); | |||||
| x++; | |||||
| } | |||||
| return cv; | return cv; | ||||
| } | } | ||||
| @@ -381,82 +416,82 @@ static void ansi_parse_grcm(cucul_canvas_t *cv, struct ansi_grcm *g, | |||||
| unsigned int argc, unsigned int const *argv) | unsigned int argc, unsigned int const *argv) | ||||
| { | { | ||||
| static uint8_t const ansi2cucul[] = | static uint8_t const ansi2cucul[] = | ||||
| { | |||||
| CUCUL_COLOR_BLACK, CUCUL_COLOR_RED, | |||||
| CUCUL_COLOR_GREEN, CUCUL_COLOR_BROWN, | |||||
| CUCUL_COLOR_BLUE, CUCUL_COLOR_MAGENTA, | |||||
| CUCUL_COLOR_CYAN, CUCUL_COLOR_LIGHTGRAY | |||||
| }; | |||||
| { | |||||
| CUCUL_COLOR_BLACK, CUCUL_COLOR_RED, | |||||
| CUCUL_COLOR_GREEN, CUCUL_COLOR_BROWN, | |||||
| CUCUL_COLOR_BLUE, CUCUL_COLOR_MAGENTA, | |||||
| CUCUL_COLOR_CYAN, CUCUL_COLOR_LIGHTGRAY | |||||
| }; | |||||
| unsigned int j; | unsigned int j; | ||||
| uint8_t myfg, mybg; | uint8_t myfg, mybg; | ||||
| for(j = 0; j < argc; j++) | for(j = 0; j < argc; j++) | ||||
| { | |||||
| /* Defined in ECMA-48 8.3.117: SGR - SELECT GRAPHIC RENDITION */ | |||||
| if(argv[j] >= 30 && argv[j] <= 37) | |||||
| g->fg = ansi2cucul[argv[j] - 30]; | |||||
| else if(argv[j] >= 40 && argv[j] <= 47) | |||||
| g->bg = ansi2cucul[argv[j] - 40]; | |||||
| else if(argv[j] >= 90 && argv[j] <= 97) | |||||
| g->fg = ansi2cucul[argv[j] - 90] + 8; | |||||
| else if(argv[j] >= 100 && argv[j] <= 107) | |||||
| g->bg = ansi2cucul[argv[j] - 100] + 8; | |||||
| else switch(argv[j]) | |||||
| { | { | ||||
| /* Defined in ECMA-48 8.3.117: SGR - SELECT GRAPHIC RENDITION */ | |||||
| if(argv[j] >= 30 && argv[j] <= 37) | |||||
| g->fg = ansi2cucul[argv[j] - 30]; | |||||
| else if(argv[j] >= 40 && argv[j] <= 47) | |||||
| g->bg = ansi2cucul[argv[j] - 40]; | |||||
| else if(argv[j] >= 90 && argv[j] <= 97) | |||||
| g->fg = ansi2cucul[argv[j] - 90] + 8; | |||||
| else if(argv[j] >= 100 && argv[j] <= 107) | |||||
| g->bg = ansi2cucul[argv[j] - 100] + 8; | |||||
| else switch(argv[j]) | |||||
| { | |||||
| case 0: /* default rendition */ | |||||
| g->fg = CUCUL_COLOR_DEFAULT; | |||||
| g->bg = CUCUL_COLOR_DEFAULT; | |||||
| g->bold = g->negative = g->concealed = 0; | |||||
| break; | |||||
| case 1: /* bold or increased intensity */ | |||||
| g->bold = 1; | |||||
| break; | |||||
| case 4: /* singly underlined */ | |||||
| break; | |||||
| case 5: /* slowly blinking (less then 150 per minute) */ | |||||
| break; | |||||
| case 7: /* negative image */ | |||||
| g->negative = 1; | |||||
| break; | |||||
| case 8: /* concealed characters */ | |||||
| g->concealed = 1; | |||||
| break; | |||||
| case 22: /* normal colour or normal intensity (neither bold nor faint) */ | |||||
| g->bold = 0; | |||||
| break; | |||||
| case 28: /* revealed characters */ | |||||
| g->concealed = 0; | |||||
| break; | |||||
| case 39: /* default display colour (implementation-defined) */ | |||||
| g->fg = CUCUL_COLOR_DEFAULT; | |||||
| break; | |||||
| case 49: /* default background colour (implementation-defined) */ | |||||
| g->bg = CUCUL_COLOR_DEFAULT; | |||||
| break; | |||||
| default: | |||||
| fprintf(stderr, "unknown sgr %i\n", argv[j]); | |||||
| break; | |||||
| } | |||||
| case 0: /* default rendition */ | |||||
| g->fg = CUCUL_COLOR_DEFAULT; | |||||
| g->bg = CUCUL_COLOR_DEFAULT; | |||||
| g->bold = g->negative = g->concealed = 0; | |||||
| break; | |||||
| case 1: /* bold or increased intensity */ | |||||
| g->bold = 1; | |||||
| break; | |||||
| case 4: /* singly underlined */ | |||||
| break; | |||||
| case 5: /* slowly blinking (less then 150 per minute) */ | |||||
| break; | |||||
| case 7: /* negative image */ | |||||
| g->negative = 1; | |||||
| break; | |||||
| case 8: /* concealed characters */ | |||||
| g->concealed = 1; | |||||
| break; | |||||
| case 22: /* normal colour or normal intensity (neither bold nor faint) */ | |||||
| g->bold = 0; | |||||
| break; | |||||
| case 28: /* revealed characters */ | |||||
| g->concealed = 0; | |||||
| break; | |||||
| case 39: /* default display colour (implementation-defined) */ | |||||
| g->fg = CUCUL_COLOR_DEFAULT; | |||||
| break; | |||||
| case 49: /* default background colour (implementation-defined) */ | |||||
| g->bg = CUCUL_COLOR_DEFAULT; | |||||
| break; | |||||
| default: | |||||
| fprintf(stderr, "unknown sgr %i\n", argv[j]); | |||||
| break; | |||||
| } | } | ||||
| } | |||||
| if(g->concealed) | if(g->concealed) | ||||
| { | |||||
| myfg = mybg = CUCUL_COLOR_TRANSPARENT; | |||||
| } | |||||
| { | |||||
| myfg = mybg = CUCUL_COLOR_TRANSPARENT; | |||||
| } | |||||
| else | else | ||||
| { | |||||
| myfg = g->negative ? g->bg : g->fg; | |||||
| mybg = g->negative ? g->fg : g->bg; | |||||
| { | |||||
| myfg = g->negative ? g->bg : g->fg; | |||||
| mybg = g->negative ? g->fg : g->bg; | |||||
| if(g->bold) | |||||
| { | |||||
| if(myfg < 8) | |||||
| myfg += 8; | |||||
| else if(myfg == CUCUL_COLOR_DEFAULT) | |||||
| myfg = CUCUL_COLOR_WHITE; | |||||
| } | |||||
| if(g->bold) | |||||
| { | |||||
| if(myfg < 8) | |||||
| myfg += 8; | |||||
| else if(myfg == CUCUL_COLOR_DEFAULT) | |||||
| myfg = CUCUL_COLOR_WHITE; | |||||
| } | } | ||||
| } | |||||
| cucul_set_color(cv, myfg, mybg); | cucul_set_color(cv, myfg, mybg); | ||||
| } | } | ||||
| @@ -22,6 +22,9 @@ | |||||
| # include <stdio.h> | # include <stdio.h> | ||||
| # include <stdlib.h> | # include <stdlib.h> | ||||
| # include <string.h> | # include <string.h> | ||||
| # if defined(HAVE_ERRNO_H) | |||||
| # include <errno.h> | |||||
| # endif | |||||
| #endif | #endif | ||||
| #include "cucul.h" | #include "cucul.h" | ||||
| @@ -31,6 +34,8 @@ | |||||
| * | * | ||||
| * This function returns the current canvas frame count. | * This function returns the current canvas frame count. | ||||
| * | * | ||||
| * This function never fails. | |||||
| * | |||||
| * \param cv A libcucul canvas | * \param cv A libcucul canvas | ||||
| * \return The frame count | * \return The frame count | ||||
| */ | */ | ||||
| @@ -47,18 +52,29 @@ unsigned int cucul_get_canvas_frame_count(cucul_canvas_t *cv) | |||||
| * | * | ||||
| * If the frame index is outside the canvas' frame range, nothing happens. | * If the frame index is outside the canvas' frame range, nothing happens. | ||||
| * | * | ||||
| * If an error occurs, -1 is returned and \b errno is set accordingly: | |||||
| * - \c EINVAL Requested frame is out of range. | |||||
| * | |||||
| * \param cv A libcucul canvas | * \param cv A libcucul canvas | ||||
| * \param frame The canvas frame to activate | * \param frame The canvas frame to activate | ||||
| * \return 0 in case of success, -1 if an error occurred. | |||||
| */ | */ | ||||
| void cucul_set_canvas_frame(cucul_canvas_t *cv, unsigned int frame) | |||||
| int cucul_set_canvas_frame(cucul_canvas_t *cv, unsigned int frame) | |||||
| { | { | ||||
| if(frame >= cv->framecount) | if(frame >= cv->framecount) | ||||
| return; | |||||
| { | |||||
| #if defined(HAVE_ERRNO_H) | |||||
| errno = EINVAL; | |||||
| #endif | |||||
| return -1; | |||||
| } | |||||
| cv->frame = frame; | cv->frame = frame; | ||||
| cv->chars = cv->allchars[cv->frame]; | cv->chars = cv->allchars[cv->frame]; | ||||
| cv->attr = cv->allattr[cv->frame]; | cv->attr = cv->allattr[cv->frame]; | ||||
| return 0; | |||||
| } | } | ||||
| /** \brief Add a frame to a canvas. | /** \brief Add a frame to a canvas. | ||||
| @@ -74,10 +90,14 @@ void cucul_set_canvas_frame(cucul_canvas_t *cv, unsigned int frame) | |||||
| * The active frame does not change, but its index may be renumbered due | * The active frame does not change, but its index may be renumbered due | ||||
| * to the insertion. | * to the insertion. | ||||
| * | * | ||||
| * If an error occurs, -1 is returned and \b errno is set accordingly: | |||||
| * - \c ENOMEM Not enough memory to allocate new frame. | |||||
| * | |||||
| * \param cv A libcucul canvas | * \param cv A libcucul canvas | ||||
| * \param frame The index where to insert the new frame | * \param frame The index where to insert the new frame | ||||
| * \return 0 in case of success, -1 if an error occurred. | |||||
| */ | */ | ||||
| void cucul_create_canvas_frame(cucul_canvas_t *cv, unsigned int frame) | |||||
| int cucul_create_canvas_frame(cucul_canvas_t *cv, unsigned int frame) | |||||
| { | { | ||||
| unsigned int size = cv->width * cv->height * sizeof(uint32_t); | unsigned int size = cv->width * cv->height * sizeof(uint32_t); | ||||
| unsigned int f; | unsigned int f; | ||||
| @@ -105,6 +125,8 @@ void cucul_create_canvas_frame(cucul_canvas_t *cv, unsigned int frame) | |||||
| cv->chars = cv->allchars[cv->frame]; | cv->chars = cv->allchars[cv->frame]; | ||||
| cv->attr = cv->allattr[cv->frame]; | cv->attr = cv->allattr[cv->frame]; | ||||
| return 0; | |||||
| } | } | ||||
| /** \brief Remove a frame from a canvas. | /** \brief Remove a frame from a canvas. | ||||
| @@ -123,18 +145,33 @@ void cucul_create_canvas_frame(cucul_canvas_t *cv, unsigned int frame) | |||||
| * Otherwise, the active frame does not change, but its index may be | * Otherwise, the active frame does not change, but its index may be | ||||
| * renumbered due to the deletion. | * renumbered due to the deletion. | ||||
| * | * | ||||
| * If an error occurs, -1 is returned and \b errno is set accordingly: | |||||
| * - \c EINVAL Requested frame is out of range, or attempt to delete the | |||||
| * last frame of the canvas. | |||||
| * | |||||
| * \param cv A libcucul canvas | * \param cv A libcucul canvas | ||||
| * \param frame The index of the frame to delete | * \param frame The index of the frame to delete | ||||
| * \return 0 in case of success, -1 if an error occurred. | |||||
| */ | */ | ||||
| void cucul_free_canvas_frame(cucul_canvas_t *cv, unsigned int frame) | |||||
| int cucul_free_canvas_frame(cucul_canvas_t *cv, unsigned int frame) | |||||
| { | { | ||||
| unsigned int f; | unsigned int f; | ||||
| if(frame >= cv->framecount) | if(frame >= cv->framecount) | ||||
| return; | |||||
| { | |||||
| #if defined(HAVE_ERRNO_H) | |||||
| errno = EINVAL; | |||||
| #endif | |||||
| return -1; | |||||
| } | |||||
| if(cv->framecount == 1) | if(cv->framecount == 1) | ||||
| return; | |||||
| { | |||||
| #if defined(HAVE_ERRNO_H) | |||||
| errno = EINVAL; | |||||
| #endif | |||||
| return -1; | |||||
| } | |||||
| free(cv->allchars[frame]); | free(cv->allchars[frame]); | ||||
| free(cv->allattr[frame]); | free(cv->allattr[frame]); | ||||
| @@ -156,5 +193,7 @@ void cucul_free_canvas_frame(cucul_canvas_t *cv, unsigned int frame) | |||||
| cv->chars = cv->allchars[cv->frame]; | cv->chars = cv->allchars[cv->frame]; | ||||
| cv->attr = cv->allattr[cv->frame]; | cv->attr = cv->allattr[cv->frame]; | ||||
| return 0; | |||||
| } | } | ||||
| @@ -33,9 +33,12 @@ static uint32_t rotatechar(uint32_t ch); | |||||
| * This function inverts a canvas' colours (black becomes white, red | * This function inverts a canvas' colours (black becomes white, red | ||||
| * becomes cyan, etc.) without changing the characters in it. | * becomes cyan, etc.) without changing the characters in it. | ||||
| * | * | ||||
| * This function never fails. | |||||
| * | |||||
| * \param cv The canvas to invert. | * \param cv The canvas to invert. | ||||
| * \return This function always returns 0. | |||||
| */ | */ | ||||
| void cucul_invert(cucul_canvas_t *cv) | |||||
| int cucul_invert(cucul_canvas_t *cv) | |||||
| { | { | ||||
| uint32_t *attr = cv->attr; | uint32_t *attr = cv->attr; | ||||
| unsigned int i; | unsigned int i; | ||||
| @@ -45,6 +48,8 @@ void cucul_invert(cucul_canvas_t *cv) | |||||
| *attr = *attr ^ 0x000f000f; | *attr = *attr ^ 0x000f000f; | ||||
| attr++; | attr++; | ||||
| } | } | ||||
| return 0; | |||||
| } | } | ||||
| /** \brief Flip a canvas horizontally. | /** \brief Flip a canvas horizontally. | ||||
| @@ -52,9 +57,12 @@ void cucul_invert(cucul_canvas_t *cv) | |||||
| * This function flips a canvas horizontally, choosing characters that | * This function flips a canvas horizontally, choosing characters that | ||||
| * look like the mirrored version wherever possible. | * look like the mirrored version wherever possible. | ||||
| * | * | ||||
| * This function never fails. | |||||
| * | |||||
| * \param cv The canvas to flip. | * \param cv The canvas to flip. | ||||
| * \return This function always returns 0. | |||||
| */ | */ | ||||
| void cucul_flip(cucul_canvas_t *cv) | |||||
| int cucul_flip(cucul_canvas_t *cv) | |||||
| { | { | ||||
| unsigned int y; | unsigned int y; | ||||
| @@ -82,6 +90,8 @@ void cucul_flip(cucul_canvas_t *cv) | |||||
| if(cleft == cright) | if(cleft == cright) | ||||
| *cleft = flipchar(*cleft); | *cleft = flipchar(*cleft); | ||||
| } | } | ||||
| return 0; | |||||
| } | } | ||||
| /** \brief Flip a canvas vertically. | /** \brief Flip a canvas vertically. | ||||
| @@ -89,9 +99,12 @@ void cucul_flip(cucul_canvas_t *cv) | |||||
| * This function flips a canvas vertically, choosing characters that | * This function flips a canvas vertically, choosing characters that | ||||
| * look like the mirrored version wherever possible. | * look like the mirrored version wherever possible. | ||||
| * | * | ||||
| * This function never fails. | |||||
| * | |||||
| * \param cv The canvas to flop. | * \param cv The canvas to flop. | ||||
| * \return This function always returns 0. | |||||
| */ | */ | ||||
| void cucul_flop(cucul_canvas_t *cv) | |||||
| int cucul_flop(cucul_canvas_t *cv) | |||||
| { | { | ||||
| unsigned int x; | unsigned int x; | ||||
| @@ -120,6 +133,8 @@ void cucul_flop(cucul_canvas_t *cv) | |||||
| if(ctop == cbottom) | if(ctop == cbottom) | ||||
| *ctop = flopchar(*ctop); | *ctop = flopchar(*ctop); | ||||
| } | } | ||||
| return 0; | |||||
| } | } | ||||
| /** \brief Rotate a canvas. | /** \brief Rotate a canvas. | ||||
| @@ -128,9 +143,12 @@ void cucul_flop(cucul_canvas_t *cv) | |||||
| * choosing characters that look like the mirrored version wherever | * choosing characters that look like the mirrored version wherever | ||||
| * possible. | * possible. | ||||
| * | * | ||||
| * This function never fails. | |||||
| * | |||||
| * \param cv The canvas to rotate. | * \param cv The canvas to rotate. | ||||
| * \return This function always returns 0. | |||||
| */ | */ | ||||
| void cucul_rotate(cucul_canvas_t *cv) | |||||
| int cucul_rotate(cucul_canvas_t *cv) | |||||
| { | { | ||||
| uint32_t *cbegin = cv->chars; | uint32_t *cbegin = cv->chars; | ||||
| uint32_t *cend = cbegin + cv->width * cv->height - 1; | uint32_t *cend = cbegin + cv->width * cv->height - 1; | ||||
| @@ -153,6 +171,8 @@ void cucul_rotate(cucul_canvas_t *cv) | |||||
| if(cbegin == cend) | if(cbegin == cend) | ||||
| *cbegin = rotatechar(*cbegin); | *cbegin = rotatechar(*cbegin); | ||||
| return 0; | |||||
| } | } | ||||
| static uint32_t flipchar(uint32_t ch) | static uint32_t flipchar(uint32_t ch) | ||||