You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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