From 05e98f2254b35b1e21056afb9791f1ad571a80d5 Mon Sep 17 00:00:00 2001 From: Sam Hocevar Date: Wed, 8 Mar 2006 17:20:38 +0000 Subject: [PATCH] * cucul_set_size() does nothing if a graphical backend is attached. Added documentation to explain this behaviour. --- cucul/cucul.c | 208 +++++++++++++++++++++++++++----------------------- 1 file changed, 113 insertions(+), 95 deletions(-) diff --git a/cucul/cucul.c b/cucul/cucul.c index 94a7ae5..ca51140 100644 --- a/cucul/cucul.c +++ b/cucul/cucul.c @@ -26,7 +26,8 @@ #include "cucul.h" #include "cucul_internals.h" -static void cucul_read_environment(cucul_t *qq); +static void cucul_read_environment(cucul_t *); +void _cucul_set_size(cucul_t *, unsigned int, unsigned int); /** \brief Initialise \e libcucul. * @@ -74,118 +75,46 @@ cucul_t * cucul_init(void) return qq; } -/** \brief Set the screen size. +/** \brief Set the canvas size. * - * This function sets the screen width and height, in character cells. + * This function sets the canvas width and height, in character cells. * - * \param width The desired screen width - * \param height The desired screen height + * It is an error to try to resize the canvas if an output driver has + * been attached to the canvas using caca_attach(). You need to remove + * the output driver using caca_detach() before you can change the + * canvas size again. + * + * However, the caca output driver can cause a canvas resize through + * user interaction. See the caca_event() documentation for more about + * this. + * + * \param width The desired canvas width + * \param height The desired canvas height */ void cucul_set_size(cucul_t *qq, unsigned int width, unsigned int height) { - unsigned int x, y, old_width, old_height, new_size, old_size; - - old_width = qq->width; - old_height = qq->height; - old_size = old_width * old_height; - - qq->width = width; - qq->height = height; - new_size = width * height; - - /* Step 1: if new area is bigger, resize the memory area now. */ - if(new_size > old_size) - { - qq->chars = realloc(qq->chars, new_size * sizeof(uint32_t)); - qq->attr = realloc(qq->attr, new_size * sizeof(uint8_t)); - } - - /* Step 2: move line data if necessary. */ - if(width == old_width) - { - /* Width did not change, which means we do not need to move data. */ - ; - } - else if(width > old_width) - { - /* New width is bigger than old width, which means we need to - * copy lines starting from the bottom of the screen otherwise - * we will overwrite information. */ - for(y = height < old_height ? height : old_height; y--; ) - { - for(x = old_width; x--; ) - { - qq->chars[y * width + x] = qq->chars[y * old_width + x]; - qq->attr[y * width + x] = qq->attr[y * old_width + x]; - } + if(qq->refcount) + return; - /* Zero the end of the line */ - for(x = width - old_width; x--; ) - qq->chars[y * width + old_width + x] = (uint32_t)' '; - memset(qq->attr + y * width + old_width, 0, - width - old_width); - } - } - else - { - /* New width is smaller. Copy as many lines as possible. Ignore - * the first line, it is already in place. */ - unsigned int lines = height < old_height ? height : old_height; - - for(y = 1; y < lines; y++) - { - for(x = 0; x < width; x++) - { - qq->chars[y * width + x] = qq->chars[y * old_width + x]; - qq->attr[y * width + x] = qq->attr[y * old_width + x]; - } - } - } - - /* Step 3: fill the bottom of the new screen if necessary. */ - if(height > old_height) - { - /* Zero the bottom of the screen */ - for(x = (height - old_height) * width; x--; ) - qq->chars[old_height * width + x] = (uint32_t)' '; - memset(qq->attr + old_height * width, 0, - (height - old_height) * width); - } - - /* Step 4: if new area is smaller, resize memory area now. */ - if(new_size <= old_size) - { - qq->chars = realloc(qq->chars, new_size * sizeof(uint32_t)); - qq->attr = realloc(qq->attr, new_size * sizeof(uint8_t)); - } - - /* Recompute the scratch line and the empty line */ - if(width != old_width) - { - qq->empty_line = realloc(qq->empty_line, width + 1); - memset(qq->empty_line, ' ', width); - qq->empty_line[width] = '\0'; - - qq->scratch_line = realloc(qq->scratch_line, width + 1); - } + cucul_set_size_internal(qq, width, height); } -/** \brief Get the screen width. +/** \brief Get the canvas width. * - * This function returns the current screen width, in character cells. + * This function returns the current canvas width, in character cells. * - * \return The screen width. + * \return The canvas width. */ unsigned int cucul_get_width(cucul_t *qq) { return qq->width; } -/** \brief Get the screen height. +/** \brief Get the canvas height. * - * This function returns the current screen height, in character cells. + * This function returns the current canvas height, in character cells. * - * \return The screen height. + * \return The canvas height. */ unsigned int cucul_get_height(cucul_t *qq) { @@ -394,3 +323,92 @@ static void cucul_read_environment(cucul_t * qq) #endif } +void _cucul_set_size(cucul_t *qq, unsigned int width, unsigned int height) +{ + unsigned int x, y, old_width, old_height, new_size, old_size; + + old_width = qq->width; + old_height = qq->height; + old_size = old_width * old_height; + + qq->width = width; + qq->height = height; + new_size = width * height; + + /* Step 1: if new area is bigger, resize the memory area now. */ + if(new_size > old_size) + { + qq->chars = realloc(qq->chars, new_size * sizeof(uint32_t)); + qq->attr = realloc(qq->attr, new_size * sizeof(uint8_t)); + } + + /* Step 2: move line data if necessary. */ + if(width == old_width) + { + /* Width did not change, which means we do not need to move data. */ + ; + } + else if(width > old_width) + { + /* New width is bigger than old width, which means we need to + * copy lines starting from the bottom of the screen otherwise + * we will overwrite information. */ + for(y = height < old_height ? height : old_height; y--; ) + { + for(x = old_width; x--; ) + { + qq->chars[y * width + x] = qq->chars[y * old_width + x]; + qq->attr[y * width + x] = qq->attr[y * old_width + x]; + } + + /* Zero the end of the line */ + for(x = width - old_width; x--; ) + qq->chars[y * width + old_width + x] = (uint32_t)' '; + memset(qq->attr + y * width + old_width, 0, + width - old_width); + } + } + else + { + /* New width is smaller. Copy as many lines as possible. Ignore + * the first line, it is already in place. */ + unsigned int lines = height < old_height ? height : old_height; + + for(y = 1; y < lines; y++) + { + for(x = 0; x < width; x++) + { + qq->chars[y * width + x] = qq->chars[y * old_width + x]; + qq->attr[y * width + x] = qq->attr[y * old_width + x]; + } + } + } + + /* Step 3: fill the bottom of the new screen if necessary. */ + if(height > old_height) + { + /* Zero the bottom of the screen */ + for(x = (height - old_height) * width; x--; ) + qq->chars[old_height * width + x] = (uint32_t)' '; + memset(qq->attr + old_height * width, 0, + (height - old_height) * width); + } + + /* Step 4: if new area is smaller, resize memory area now. */ + if(new_size <= old_size) + { + qq->chars = realloc(qq->chars, new_size * sizeof(uint32_t)); + qq->attr = realloc(qq->attr, new_size * sizeof(uint8_t)); + } + + /* Recompute the scratch line and the empty line */ + if(width != old_width) + { + qq->empty_line = realloc(qq->empty_line, width + 1); + memset(qq->empty_line, ' ', width); + qq->empty_line[width] = '\0'; + + qq->scratch_line = realloc(qq->scratch_line, width + 1); + } +} +