| 1 | /* |
|---|
| 2 | * libcaca Colour ASCII-Art library |
|---|
| 3 | * Copyright (c) 2002-2009 Sam Hocevar <sam@hocevar.net> |
|---|
| 4 | * All Rights Reserved |
|---|
| 5 | * |
|---|
| 6 | * $Id$ |
|---|
| 7 | * |
|---|
| 8 | * This library is free software. It comes without any warranty, to |
|---|
| 9 | * the extent permitted by applicable law. You can redistribute it |
|---|
| 10 | * and/or modify it under the terms of the Do What The Fuck You Want |
|---|
| 11 | * To Public License, Version 2, as published by Sam Hocevar. See |
|---|
| 12 | * http://sam.zoy.org/wtfpl/COPYING for more details. |
|---|
| 13 | */ |
|---|
| 14 | |
|---|
| 15 | /* |
|---|
| 16 | * This file contains the main functions used by \e libcaca applications |
|---|
| 17 | * to initialise a drawing context. |
|---|
| 18 | */ |
|---|
| 19 | |
|---|
| 20 | #include "config.h" |
|---|
| 21 | |
|---|
| 22 | #if !defined(__KERNEL__) |
|---|
| 23 | # include <stdio.h> |
|---|
| 24 | # include <stdlib.h> |
|---|
| 25 | # include <string.h> |
|---|
| 26 | # include <time.h> |
|---|
| 27 | # include <sys/types.h> |
|---|
| 28 | # if defined(HAVE_UNISTD_H) |
|---|
| 29 | # include <unistd.h> |
|---|
| 30 | # endif |
|---|
| 31 | #endif |
|---|
| 32 | |
|---|
| 33 | #include "caca.h" |
|---|
| 34 | #include "caca_internals.h" |
|---|
| 35 | |
|---|
| 36 | static int caca_resize(caca_canvas_t *, int, int); |
|---|
| 37 | |
|---|
| 38 | /** \brief Initialise a \e libcaca canvas. |
|---|
| 39 | * |
|---|
| 40 | * Initialise internal \e libcaca structures and the backend that will |
|---|
| 41 | * be used for subsequent graphical operations. It must be the first |
|---|
| 42 | * \e libcaca function to be called in a function. caca_free_canvas() |
|---|
| 43 | * should be called at the end of the program to free all allocated resources. |
|---|
| 44 | * |
|---|
| 45 | * Both the cursor and the canvas' handle are initialised at the top-left |
|---|
| 46 | * corner. |
|---|
| 47 | * |
|---|
| 48 | * If an error occurs, NULL is returned and \b errno is set accordingly: |
|---|
| 49 | * - \c EINVAL Specified width or height is invalid. |
|---|
| 50 | * - \c ENOMEM Not enough memory for the requested canvas size. |
|---|
| 51 | * |
|---|
| 52 | * \param width The desired canvas width |
|---|
| 53 | * \param height The desired canvas height |
|---|
| 54 | * \return A libcaca canvas handle upon success, NULL if an error occurred. |
|---|
| 55 | */ |
|---|
| 56 | caca_canvas_t * caca_create_canvas(int width, int height) |
|---|
| 57 | { |
|---|
| 58 | caca_canvas_t *cv; |
|---|
| 59 | |
|---|
| 60 | if(width < 0 || height < 0) |
|---|
| 61 | { |
|---|
| 62 | seterrno(EINVAL); |
|---|
| 63 | return NULL; |
|---|
| 64 | } |
|---|
| 65 | |
|---|
| 66 | cv = malloc(sizeof(caca_canvas_t)); |
|---|
| 67 | |
|---|
| 68 | if(!cv) |
|---|
| 69 | goto nomem; |
|---|
| 70 | |
|---|
| 71 | cv->refcount = 0; |
|---|
| 72 | cv->autoinc = 0; |
|---|
| 73 | cv->resize_callback = NULL; |
|---|
| 74 | cv->resize_data = NULL; |
|---|
| 75 | |
|---|
| 76 | cv->frame = 0; |
|---|
| 77 | cv->framecount = 1; |
|---|
| 78 | cv->frames = malloc(sizeof(struct caca_frame)); |
|---|
| 79 | if(!cv->frames) |
|---|
| 80 | { |
|---|
| 81 | free(cv); |
|---|
| 82 | goto nomem; |
|---|
| 83 | } |
|---|
| 84 | |
|---|
| 85 | cv->frames[0].width = cv->frames[0].height = 0; |
|---|
| 86 | cv->frames[0].chars = NULL; |
|---|
| 87 | cv->frames[0].attrs = NULL; |
|---|
| 88 | cv->frames[0].x = cv->frames[0].y = 0; |
|---|
| 89 | cv->frames[0].handlex = cv->frames[0].handley = 0; |
|---|
| 90 | cv->frames[0].curattr = 0; |
|---|
| 91 | cv->frames[0].name = strdup("frame#00000000"); |
|---|
| 92 | |
|---|
| 93 | _caca_load_frame_info(cv); |
|---|
| 94 | caca_set_color_ansi(cv, CACA_DEFAULT, CACA_TRANSPARENT); |
|---|
| 95 | |
|---|
| 96 | cv->ndirty = 0; |
|---|
| 97 | cv->ff = NULL; |
|---|
| 98 | |
|---|
| 99 | if(caca_resize(cv, width, height) < 0) |
|---|
| 100 | { |
|---|
| 101 | int saved_errno = geterrno(); |
|---|
| 102 | free(cv->frames[0].name); |
|---|
| 103 | free(cv->frames); |
|---|
| 104 | free(cv); |
|---|
| 105 | seterrno(saved_errno); |
|---|
| 106 | return NULL; |
|---|
| 107 | } |
|---|
| 108 | |
|---|
| 109 | return cv; |
|---|
| 110 | |
|---|
| 111 | nomem: |
|---|
| 112 | seterrno(ENOMEM); |
|---|
| 113 | return NULL; |
|---|
| 114 | } |
|---|
| 115 | |
|---|
| 116 | /** \brief Manage a canvas. |
|---|
| 117 | * |
|---|
| 118 | * Lock a canvas to prevent it from being resized. If non-NULL, |
|---|
| 119 | * the \e callback function pointer will be called upon each |
|---|
| 120 | * \e caca_set_canvas_size call and if the returned value is zero, the |
|---|
| 121 | * canvas resize request will be denied. |
|---|
| 122 | * |
|---|
| 123 | * This function is only useful for display drivers such as the \e libcaca |
|---|
| 124 | * library. |
|---|
| 125 | * |
|---|
| 126 | * If an error occurs, -1 is returned and \b errno is set accordingly: |
|---|
| 127 | * - \c EBUSY The canvas is already being managed. |
|---|
| 128 | * |
|---|
| 129 | * \param cv A libcaca canvas. |
|---|
| 130 | * \param callback An optional callback function pointer. |
|---|
| 131 | * \param p The argument to be passed to \e callback. |
|---|
| 132 | * \return 0 in case of success, -1 if an error occurred. |
|---|
| 133 | */ |
|---|
| 134 | int caca_manage_canvas(caca_canvas_t *cv, int (*callback)(void *), void *p) |
|---|
| 135 | { |
|---|
| 136 | if(cv->refcount) |
|---|
| 137 | { |
|---|
| 138 | seterrno(EBUSY); |
|---|
| 139 | return -1; |
|---|
| 140 | } |
|---|
| 141 | |
|---|
| 142 | cv->resize_callback = callback; |
|---|
| 143 | cv->resize_data = p; |
|---|
| 144 | cv->refcount = 1; |
|---|
| 145 | |
|---|
| 146 | return 0; |
|---|
| 147 | } |
|---|
| 148 | |
|---|
| 149 | /** \brief unmanage a canvas. |
|---|
| 150 | * |
|---|
| 151 | * unlock a canvas previously locked by caca_manage_canvas(). for safety |
|---|
| 152 | * reasons, the callback and callback data arguments must be the same as for |
|---|
| 153 | * the caca_manage_canvas() call. |
|---|
| 154 | * |
|---|
| 155 | * this function is only useful for display drivers such as the \e libcaca |
|---|
| 156 | * library. |
|---|
| 157 | * |
|---|
| 158 | * if an error occurs, -1 is returned and \b errno is set accordingly: |
|---|
| 159 | * - \c einval the canvas is not managed, or the callback arguments do |
|---|
| 160 | * not match. |
|---|
| 161 | * |
|---|
| 162 | * \param cv a libcaca canvas. |
|---|
| 163 | * \param callback the \e callback argument previously passed to |
|---|
| 164 | * caca_manage_canvas(). |
|---|
| 165 | * \param p the \e p argument previously passed to caca_manage_canvas(). |
|---|
| 166 | * \return 0 in case of success, -1 if an error occurred. |
|---|
| 167 | */ |
|---|
| 168 | int caca_unmanage_canvas(caca_canvas_t *cv, int (*callback)(void *), void *p) |
|---|
| 169 | { |
|---|
| 170 | if(!cv->refcount |
|---|
| 171 | || cv->resize_callback != callback || cv->resize_data != p) |
|---|
| 172 | { |
|---|
| 173 | seterrno(EINVAL); |
|---|
| 174 | return -1; |
|---|
| 175 | } |
|---|
| 176 | |
|---|
| 177 | cv->refcount = 0; |
|---|
| 178 | |
|---|
| 179 | return 0; |
|---|
| 180 | } |
|---|
| 181 | |
|---|
| 182 | /** \brief Resize a canvas. |
|---|
| 183 | * |
|---|
| 184 | * Set the canvas' width and height, in character cells. |
|---|
| 185 | * |
|---|
| 186 | * The contents of the canvas are preserved to the extent of the new |
|---|
| 187 | * canvas size. Newly allocated character cells at the right and/or at |
|---|
| 188 | * the bottom of the canvas are filled with spaces. |
|---|
| 189 | * |
|---|
| 190 | * If as a result of the resize the cursor coordinates fall outside the |
|---|
| 191 | * new canvas boundaries, they are readjusted. For instance, if the |
|---|
| 192 | * current X cursor coordinate is 11 and the requested width is 10, the |
|---|
| 193 | * new X cursor coordinate will be 10. |
|---|
| 194 | * |
|---|
| 195 | * It is an error to try to resize the canvas if an output driver has |
|---|
| 196 | * been attached to the canvas using caca_create_display(). You need to |
|---|
| 197 | * remove the output driver using caca_free_display() before you can change |
|---|
| 198 | * the canvas size again. However, the caca output driver can cause a |
|---|
| 199 | * canvas resize through user interaction. See the caca_event() documentation |
|---|
| 200 | * for more about this. |
|---|
| 201 | * |
|---|
| 202 | * If an error occurs, -1 is returned and \b errno is set accordingly: |
|---|
| 203 | * - \c EINVAL Specified width or height is invalid. |
|---|
| 204 | * - \c EBUSY The canvas is in use by a display driver and cannot be resized. |
|---|
| 205 | * - \c ENOMEM Not enough memory for the requested canvas size. If this |
|---|
| 206 | * happens, the canvas handle becomes invalid and should not be used. |
|---|
| 207 | * |
|---|
| 208 | * \param cv A libcaca canvas. |
|---|
| 209 | * \param width The desired canvas width. |
|---|
| 210 | * \param height The desired canvas height. |
|---|
| 211 | * \return 0 in case of success, -1 if an error occurred. |
|---|
| 212 | */ |
|---|
| 213 | int caca_set_canvas_size(caca_canvas_t *cv, int width, int height) |
|---|
| 214 | { |
|---|
| 215 | if(width < 0 || height < 0) |
|---|
| 216 | { |
|---|
| 217 | seterrno(EINVAL); |
|---|
| 218 | return -1; |
|---|
| 219 | } |
|---|
| 220 | |
|---|
| 221 | if(cv->refcount && cv->resize_callback |
|---|
| 222 | && !cv->resize_callback(cv->resize_data)) |
|---|
| 223 | { |
|---|
| 224 | seterrno(EBUSY); |
|---|
| 225 | return -1; |
|---|
| 226 | } |
|---|
| 227 | |
|---|
| 228 | return caca_resize(cv, width, height); |
|---|
| 229 | } |
|---|
| 230 | |
|---|
| 231 | /** \brief Get the canvas width. |
|---|
| 232 | * |
|---|
| 233 | * Return the current canvas' width, in character cells. |
|---|
| 234 | * |
|---|
| 235 | * This function never fails. |
|---|
| 236 | * |
|---|
| 237 | * \param cv A libcaca canvas. |
|---|
| 238 | * \return The canvas width. |
|---|
| 239 | */ |
|---|
| 240 | int caca_get_canvas_width(caca_canvas_t const *cv) |
|---|
| 241 | { |
|---|
| 242 | return cv->width; |
|---|
| 243 | } |
|---|
| 244 | |
|---|
| 245 | /** \brief Get the canvas height. |
|---|
| 246 | * |
|---|
| 247 | * Returns the current canvas' height, in character cells. |
|---|
| 248 | * |
|---|
| 249 | * This function never fails. |
|---|
| 250 | * |
|---|
| 251 | * \param cv A libcaca canvas. |
|---|
| 252 | * \return The canvas height. |
|---|
| 253 | */ |
|---|
| 254 | int caca_get_canvas_height(caca_canvas_t const *cv) |
|---|
| 255 | { |
|---|
| 256 | return cv->height; |
|---|
| 257 | } |
|---|
| 258 | |
|---|
| 259 | /** \brief Get the canvas character array. |
|---|
| 260 | * |
|---|
| 261 | * Return the current canvas' internal character array. The array elements |
|---|
| 262 | * consist in native endian 32-bit Unicode values as returned by |
|---|
| 263 | * caca_get_char(). |
|---|
| 264 | * |
|---|
| 265 | * This function is only useful for display drivers such as the \e libcaca |
|---|
| 266 | * library. |
|---|
| 267 | * |
|---|
| 268 | * This function never fails. |
|---|
| 269 | * |
|---|
| 270 | * \param cv A libcaca canvas. |
|---|
| 271 | * \return The canvas character array. |
|---|
| 272 | */ |
|---|
| 273 | uint8_t const * caca_get_canvas_chars(caca_canvas_t const *cv) |
|---|
| 274 | { |
|---|
| 275 | return (uint8_t const *)cv->chars; |
|---|
| 276 | } |
|---|
| 277 | |
|---|
| 278 | /** \brief Get the canvas attribute array. |
|---|
| 279 | * |
|---|
| 280 | * Returns the current canvas' internal attribute array. The array elements |
|---|
| 281 | * consist in native endian 32-bit attribute values as returned by |
|---|
| 282 | * caca_get_attr(). |
|---|
| 283 | * |
|---|
| 284 | * This function is only useful for display drivers such as the \e libcaca |
|---|
| 285 | * library. |
|---|
| 286 | * |
|---|
| 287 | * This function never fails. |
|---|
| 288 | * |
|---|
| 289 | * \param cv A libcaca canvas. |
|---|
| 290 | * \return The canvas attribute array. |
|---|
| 291 | */ |
|---|
| 292 | uint8_t const * caca_get_canvas_attrs(caca_canvas_t const *cv) |
|---|
| 293 | { |
|---|
| 294 | return (uint8_t const *)cv->attrs; |
|---|
| 295 | } |
|---|
| 296 | |
|---|
| 297 | /** \brief Free a \e libcaca canvas. |
|---|
| 298 | * |
|---|
| 299 | * Free all resources allocated by caca_create_canvas(). The canvas |
|---|
| 300 | * pointer becomes invalid and must no longer be used unless a new call |
|---|
| 301 | * to caca_create_canvas() is made. |
|---|
| 302 | * |
|---|
| 303 | * If an error occurs, -1 is returned and \b errno is set accordingly: |
|---|
| 304 | * - \c EBUSY The canvas is in use by a display driver and cannot be freed. |
|---|
| 305 | * |
|---|
| 306 | * \param cv A libcaca canvas. |
|---|
| 307 | * \return 0 in case of success, -1 if an error occurred. |
|---|
| 308 | */ |
|---|
| 309 | int caca_free_canvas(caca_canvas_t *cv) |
|---|
| 310 | { |
|---|
| 311 | int f; |
|---|
| 312 | |
|---|
| 313 | if(cv->refcount) |
|---|
| 314 | { |
|---|
| 315 | seterrno(EBUSY); |
|---|
| 316 | return -1; |
|---|
| 317 | } |
|---|
| 318 | |
|---|
| 319 | for(f = 0; f < cv->framecount; f++) |
|---|
| 320 | { |
|---|
| 321 | free(cv->frames[f].chars); |
|---|
| 322 | free(cv->frames[f].attrs); |
|---|
| 323 | free(cv->frames[f].name); |
|---|
| 324 | } |
|---|
| 325 | |
|---|
| 326 | caca_canvas_set_figfont(cv, NULL); |
|---|
| 327 | |
|---|
| 328 | free(cv->frames); |
|---|
| 329 | free(cv); |
|---|
| 330 | |
|---|
| 331 | return 0; |
|---|
| 332 | } |
|---|
| 333 | |
|---|
| 334 | /** \brief Generate a random integer within a range. |
|---|
| 335 | * |
|---|
| 336 | * Generate a random integer within the given range. |
|---|
| 337 | * |
|---|
| 338 | * This function never fails. |
|---|
| 339 | * |
|---|
| 340 | * \param min The lower bound of the integer range. |
|---|
| 341 | * \param max The upper bound of the integer range. |
|---|
| 342 | * \return A random integer comprised between \p min and \p max - 1 |
|---|
| 343 | * (inclusive). |
|---|
| 344 | */ |
|---|
| 345 | int caca_rand(int min, int max) |
|---|
| 346 | { |
|---|
| 347 | static int need_init = 1; |
|---|
| 348 | |
|---|
| 349 | if(need_init) |
|---|
| 350 | { |
|---|
| 351 | srand(getpid() + time(NULL)); |
|---|
| 352 | need_init = 0; |
|---|
| 353 | } |
|---|
| 354 | |
|---|
| 355 | return min + (int)((1.0 * (max - min)) * rand() / (RAND_MAX + 1.0)); |
|---|
| 356 | } |
|---|
| 357 | |
|---|
| 358 | |
|---|
| 359 | /* |
|---|
| 360 | * XXX: The following functions are local. |
|---|
| 361 | */ |
|---|
| 362 | |
|---|
| 363 | int caca_resize(caca_canvas_t *cv, int width, int height) |
|---|
| 364 | { |
|---|
| 365 | int x, y, f, old_width, old_height, new_size, old_size; |
|---|
| 366 | |
|---|
| 367 | old_width = cv->width; |
|---|
| 368 | old_height = cv->height; |
|---|
| 369 | old_size = old_width * old_height; |
|---|
| 370 | |
|---|
| 371 | _caca_save_frame_info(cv); |
|---|
| 372 | |
|---|
| 373 | /* Preload new width and height values into the canvas to optimise |
|---|
| 374 | * dirty rectangle handling */ |
|---|
| 375 | cv->width = width; |
|---|
| 376 | cv->height = height; |
|---|
| 377 | new_size = width * height; |
|---|
| 378 | |
|---|
| 379 | /* If width or height is smaller (or both), we have the opportunity to |
|---|
| 380 | * reduce or even remove dirty rectangles */ |
|---|
| 381 | if(width < old_width || height < old_height) |
|---|
| 382 | _caca_clip_dirty_rect_list(cv); |
|---|
| 383 | |
|---|
| 384 | /* Step 1: if new area is bigger, resize the memory area now. */ |
|---|
| 385 | if(new_size > old_size) |
|---|
| 386 | { |
|---|
| 387 | for(f = 0; f < cv->framecount; f++) |
|---|
| 388 | { |
|---|
| 389 | cv->frames[f].chars = realloc(cv->frames[f].chars, |
|---|
| 390 | new_size * sizeof(uint32_t)); |
|---|
| 391 | cv->frames[f].attrs = realloc(cv->frames[f].attrs, |
|---|
| 392 | new_size * sizeof(uint32_t)); |
|---|
| 393 | if(new_size && (!cv->frames[f].chars || !cv->frames[f].attrs)) |
|---|
| 394 | { |
|---|
| 395 | seterrno(ENOMEM); |
|---|
| 396 | return -1; |
|---|
| 397 | } |
|---|
| 398 | } |
|---|
| 399 | } |
|---|
| 400 | |
|---|
| 401 | /* Step 2: move line data if necessary. */ |
|---|
| 402 | if(width == old_width) |
|---|
| 403 | { |
|---|
| 404 | /* Width did not change, which means we do not need to move data. */ |
|---|
| 405 | ; |
|---|
| 406 | } |
|---|
| 407 | else if(width > old_width) |
|---|
| 408 | { |
|---|
| 409 | /* New width is bigger than old width, which means we need to |
|---|
| 410 | * copy lines starting from the bottom of the screen otherwise |
|---|
| 411 | * we will overwrite information. */ |
|---|
| 412 | for(f = 0; f < cv->framecount; f++) |
|---|
| 413 | { |
|---|
| 414 | uint32_t *chars = cv->frames[f].chars; |
|---|
| 415 | uint32_t *attrs = cv->frames[f].attrs; |
|---|
| 416 | |
|---|
| 417 | for(y = height < old_height ? height : old_height; y--; ) |
|---|
| 418 | { |
|---|
| 419 | uint32_t attr = cv->frames[f].curattr; |
|---|
| 420 | |
|---|
| 421 | for(x = old_width; x--; ) |
|---|
| 422 | { |
|---|
| 423 | chars[y * width + x] = chars[y * old_width + x]; |
|---|
| 424 | attrs[y * width + x] = attrs[y * old_width + x]; |
|---|
| 425 | } |
|---|
| 426 | |
|---|
| 427 | /* Zero the end of the line */ |
|---|
| 428 | for(x = width - old_width; x--; ) |
|---|
| 429 | { |
|---|
| 430 | chars[y * width + old_width + x] = (uint32_t)' '; |
|---|
| 431 | attrs[y * width + old_width + x] = attr; |
|---|
| 432 | } |
|---|
| 433 | } |
|---|
| 434 | } |
|---|
| 435 | |
|---|
| 436 | caca_add_dirty_rect(cv, old_width, 0, width - old_width, old_height); |
|---|
| 437 | } |
|---|
| 438 | else |
|---|
| 439 | { |
|---|
| 440 | /* New width is smaller. Copy as many lines as possible. Ignore |
|---|
| 441 | * the first line, it is already in place. */ |
|---|
| 442 | int lines = height < old_height ? height : old_height; |
|---|
| 443 | |
|---|
| 444 | for(f = 0; f < cv->framecount; f++) |
|---|
| 445 | { |
|---|
| 446 | uint32_t *chars = cv->frames[f].chars; |
|---|
| 447 | uint32_t *attrs = cv->frames[f].attrs; |
|---|
| 448 | |
|---|
| 449 | for(y = 1; y < lines; y++) |
|---|
| 450 | { |
|---|
| 451 | for(x = 0; x < width; x++) |
|---|
| 452 | { |
|---|
| 453 | chars[y * width + x] = chars[y * old_width + x]; |
|---|
| 454 | attrs[y * width + x] = attrs[y * old_width + x]; |
|---|
| 455 | } |
|---|
| 456 | } |
|---|
| 457 | } |
|---|
| 458 | } |
|---|
| 459 | |
|---|
| 460 | /* Step 3: fill the bottom of the new screen if necessary. */ |
|---|
| 461 | if(height > old_height) |
|---|
| 462 | { |
|---|
| 463 | for(f = 0; f < cv->framecount; f++) |
|---|
| 464 | { |
|---|
| 465 | uint32_t *chars = cv->frames[f].chars; |
|---|
| 466 | uint32_t *attrs = cv->frames[f].attrs; |
|---|
| 467 | uint32_t attr = cv->frames[f].curattr; |
|---|
| 468 | |
|---|
| 469 | /* Zero the bottom of the screen */ |
|---|
| 470 | for(x = (height - old_height) * width; x--; ) |
|---|
| 471 | { |
|---|
| 472 | chars[old_height * width + x] = (uint32_t)' '; |
|---|
| 473 | attrs[old_height * width + x] = attr; |
|---|
| 474 | } |
|---|
| 475 | } |
|---|
| 476 | |
|---|
| 477 | caca_add_dirty_rect(cv, 0, old_height, old_width, height - old_height); |
|---|
| 478 | } |
|---|
| 479 | |
|---|
| 480 | /* If both width and height are larger, there is a new dirty rectangle |
|---|
| 481 | * that needs to be created in the lower right corner. */ |
|---|
| 482 | if(width > old_width && height > old_height) |
|---|
| 483 | caca_add_dirty_rect(cv, old_width, old_height, |
|---|
| 484 | width - old_width, height - old_height); |
|---|
| 485 | |
|---|
| 486 | /* Step 4: if new area is smaller, resize memory area now. */ |
|---|
| 487 | if(new_size < old_size) |
|---|
| 488 | { |
|---|
| 489 | for(f = 0; f < cv->framecount; f++) |
|---|
| 490 | { |
|---|
| 491 | cv->frames[f].chars = realloc(cv->frames[f].chars, |
|---|
| 492 | new_size * sizeof(uint32_t)); |
|---|
| 493 | cv->frames[f].attrs = realloc(cv->frames[f].attrs, |
|---|
| 494 | new_size * sizeof(uint32_t)); |
|---|
| 495 | if(new_size && (!cv->frames[f].chars || !cv->frames[f].attrs)) |
|---|
| 496 | { |
|---|
| 497 | seterrno(ENOMEM); |
|---|
| 498 | return -1; |
|---|
| 499 | } |
|---|
| 500 | } |
|---|
| 501 | } |
|---|
| 502 | |
|---|
| 503 | /* Set new size */ |
|---|
| 504 | for(f = 0; f < cv->framecount; f++) |
|---|
| 505 | { |
|---|
| 506 | if(cv->frames[f].x > (int)width) |
|---|
| 507 | cv->frames[f].x = width; |
|---|
| 508 | if(cv->frames[f].y > (int)height) |
|---|
| 509 | cv->frames[f].y = height; |
|---|
| 510 | |
|---|
| 511 | cv->frames[f].width = width; |
|---|
| 512 | cv->frames[f].height = height; |
|---|
| 513 | } |
|---|
| 514 | |
|---|
| 515 | /* Reset the current frame shortcuts */ |
|---|
| 516 | _caca_load_frame_info(cv); |
|---|
| 517 | |
|---|
| 518 | return 0; |
|---|
| 519 | } |
|---|
| 520 | |
|---|
| 521 | /* |
|---|
| 522 | * XXX: The following functions are aliases. |
|---|
| 523 | */ |
|---|
| 524 | |
|---|
| 525 | cucul_canvas_t * cucul_create_canvas(int, int) CACA_ALIAS(caca_create_canvas); |
|---|
| 526 | int cucul_manage_canvas(cucul_canvas_t *, int (*)(void *), void *) |
|---|
| 527 | CACA_ALIAS(caca_manage_canvas); |
|---|
| 528 | int cucul_unmanage_canvas(cucul_canvas_t *, int (*)(void *), void *) |
|---|
| 529 | CACA_ALIAS(caca_unmanage_canvas); |
|---|
| 530 | int cucul_set_canvas_size(cucul_canvas_t *, int, int) |
|---|
| 531 | CACA_ALIAS(caca_set_canvas_size); |
|---|
| 532 | int cucul_get_canvas_width(cucul_canvas_t const *) |
|---|
| 533 | CACA_ALIAS(caca_get_canvas_width); |
|---|
| 534 | int cucul_get_canvas_height(cucul_canvas_t const *) |
|---|
| 535 | CACA_ALIAS(caca_get_canvas_height); |
|---|
| 536 | uint8_t const * cucul_get_canvas_chars(cucul_canvas_t const *) |
|---|
| 537 | CACA_ALIAS(caca_get_canvas_chars); |
|---|
| 538 | uint8_t const * cucul_get_canvas_attrs(cucul_canvas_t const *) |
|---|
| 539 | CACA_ALIAS(caca_get_canvas_attrs); |
|---|
| 540 | int cucul_free_canvas(cucul_canvas_t *) CACA_ALIAS(caca_free_canvas); |
|---|
| 541 | int cucul_rand(int, int) CACA_ALIAS(caca_rand); |
|---|
| 542 | |
|---|