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.
 
 
 
 
 
 

269 lines
7.4 KiB

  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 character and string drawing functions.
  16. */
  17. #include "config.h"
  18. #if !defined(__KERNEL__)
  19. # include <stdio.h>
  20. # include <stdlib.h>
  21. # include <string.h>
  22. #endif
  23. #include "cucul.h"
  24. #include "caca.h"
  25. #include "caca_internals.h"
  26. /** \brief Set the display title.
  27. *
  28. * If libcaca runs in a window, try to change its title. This works with
  29. * the ncurses, S-Lang, OpenGL, X11 and Win32 drivers.
  30. *
  31. * If an error occurs, -1 is returned and \b errno is set accordingly:
  32. * - \c ENOSYS Display driver does not support setting the window title.
  33. *
  34. * \param dp The libcaca display context.
  35. * \param title The desired display title.
  36. * \return 0 upon success, -1 if an error occurred.
  37. */
  38. int caca_set_display_title(caca_display_t *dp, char const *title)
  39. {
  40. int ret = dp->drv.set_display_title(dp, title);
  41. if(ret)
  42. seterrno(ENOSYS);
  43. return ret;
  44. }
  45. /** \brief Get the display width.
  46. *
  47. * If libcaca runs in a window, get the usable window width. This value can
  48. * be used for aspect ratio calculation. If libcaca does not run in a window
  49. * or if there is no way to know the font size, most drivers will assume a
  50. * 6x10 font is being used. Note that the units are not necessarily pixels.
  51. *
  52. * This function never fails.
  53. *
  54. * \param dp The libcaca display context.
  55. * \return The display width.
  56. */
  57. int caca_get_display_width(caca_display_t const *dp)
  58. {
  59. return dp->drv.get_display_width(dp);
  60. }
  61. /** \brief Get the display height.
  62. *
  63. * If libcaca runs in a window, get the usable window height. This value can
  64. * be used for aspect ratio calculation. If libcaca does not run in a window
  65. * or if there is no way to know the font size, assume a 6x10 font is being
  66. * used. Note that the units are not necessarily pixels.
  67. *
  68. * This function never fails.
  69. *
  70. * \param dp The libcaca display context.
  71. * \return The display height.
  72. */
  73. int caca_get_display_height(caca_display_t const *dp)
  74. {
  75. return dp->drv.get_display_height(dp);
  76. }
  77. /** \brief Set the refresh delay.
  78. *
  79. * Set the refresh delay in microseconds. The refresh delay is used by
  80. * caca_refresh_display() to achieve constant framerate. See the
  81. * caca_refresh_display() documentation for more details.
  82. *
  83. * If the argument is zero, constant framerate is disabled. This is the
  84. * default behaviour.
  85. *
  86. * If an error occurs, -1 is returned and \b errno is set accordingly:
  87. * - \c EINVAL Refresh delay value is invalid.
  88. *
  89. * \param dp The libcaca display context.
  90. * \param usec The refresh delay in microseconds.
  91. * \return 0 upon success, -1 if an error occurred.
  92. */
  93. int caca_set_display_time(caca_display_t *dp, int usec)
  94. {
  95. if(usec < 0)
  96. {
  97. seterrno(EINVAL);
  98. return -1;
  99. }
  100. dp->delay = usec;
  101. return 0;
  102. }
  103. /** \brief Get the display's average rendering time.
  104. *
  105. * Get the average rendering time, which is the average measured time
  106. * between two caca_refresh_display() calls, in microseconds. If constant
  107. * framerate was activated by calling caca_set_display_time(), the average
  108. * rendering time will be close to the requested delay even if the real
  109. * rendering time was shorter.
  110. *
  111. * This function never fails.
  112. *
  113. * \param dp The libcaca display context.
  114. * \return The render time in microseconds.
  115. */
  116. int caca_get_display_time(caca_display_t const *dp)
  117. {
  118. return dp->rendertime;
  119. }
  120. /** \brief Flush pending changes and redraw the screen.
  121. *
  122. * Flush all graphical operations and print them to the display device.
  123. * Nothing will show on the screen until this function is called.
  124. *
  125. * If caca_set_display_time() was called with a non-zero value,
  126. * caca_refresh_display() will use that value to achieve constant
  127. * framerate: if two consecutive calls to caca_refresh_display() are within
  128. * a time range shorter than the value set with caca_set_display_time(),
  129. * the second call will be delayed before performing the screen refresh.
  130. *
  131. * This function never fails.
  132. *
  133. * \param dp The libcaca display context.
  134. * \return This function always returns 0.
  135. */
  136. int caca_refresh_display(caca_display_t *dp)
  137. {
  138. #if !defined(_DOXYGEN_SKIP_ME)
  139. #define IDLE_USEC 5000
  140. #endif
  141. int ticks = dp->lastticks + _caca_getticks(&dp->timer);
  142. dp->drv.display(dp);
  143. /* Once the display is finished, we can ack resizes */
  144. if(dp->resize.resized)
  145. {
  146. dp->resize.resized = 0;
  147. _caca_handle_resize(dp);
  148. }
  149. /* Wait until dp->delay + time of last call */
  150. ticks += _caca_getticks(&dp->timer);
  151. for(ticks += _caca_getticks(&dp->timer);
  152. ticks + IDLE_USEC < (int)dp->delay;
  153. ticks += _caca_getticks(&dp->timer))
  154. {
  155. _caca_sleep(IDLE_USEC);
  156. }
  157. /* Update the sliding mean of the render time */
  158. dp->rendertime = (7 * dp->rendertime + ticks) / 8;
  159. dp->lastticks = ticks - dp->delay;
  160. /* If we drifted too much, it's bad, bad, bad. */
  161. if(dp->lastticks > (int)dp->delay)
  162. dp->lastticks = 0;
  163. return 0;
  164. }
  165. /** \brief Show or hide the cursor.
  166. *
  167. * Show or hide the cursor, for devices that support such a feature.
  168. *
  169. * If an error occurs, -1 is returned and \b errno is set accordingly:
  170. * - \c ENOSYS Display driver does not support showing the cursor.
  171. *
  172. * \param dp The libcaca display context.
  173. * \param flag 0 hides the cursor, 1 shows the system's default cursor
  174. * (usually a white rectangle). Other values are reserved for
  175. * future use.
  176. * \return 0 upon success, -1 if an error occurred.
  177. */
  178. int caca_set_cursor(caca_display_t *dp, int flag)
  179. {
  180. if(!dp->drv.set_cursor)
  181. {
  182. seterrno(ENOSYS);
  183. return -1;
  184. }
  185. dp->drv.set_cursor(dp, flag);
  186. return 0;
  187. }
  188. /** \brief Show or hide the mouse pointer.
  189. *
  190. * Show or hide the mouse pointer. This function works with the ncurses,
  191. * S-Lang and X11 drivers.
  192. *
  193. * If an error occurs, -1 is returned and \b errno is set accordingly:
  194. * - \c ENOSYS Display driver does not support hiding the mouse pointer.
  195. *
  196. * \param dp The libcaca display context.
  197. * \param flag 0 hides the pointer, 1 shows the system's default pointer
  198. * (usually an arrow). Other values are reserved for future use.
  199. * \return 0 upon success, -1 if an error occurred.
  200. */
  201. int caca_set_mouse(caca_display_t *dp, int flag)
  202. {
  203. if(!dp->drv.set_mouse)
  204. {
  205. seterrno(ENOSYS);
  206. return -1;
  207. }
  208. dp->drv.set_mouse(dp, flag);
  209. return 0;
  210. }
  211. /*
  212. * XXX: following functions are local
  213. */
  214. void _caca_handle_resize(caca_display_t *dp)
  215. {
  216. dp->drv.handle_resize(dp);
  217. /* Tell libcucul we changed size */
  218. if(dp->resize.w != cucul_get_canvas_width(dp->cv)
  219. || dp->resize.h != cucul_get_canvas_height(dp->cv))
  220. {
  221. dp->resize.allow = 1;
  222. cucul_set_canvas_size(dp->cv, dp->resize.w, dp->resize.h);
  223. dp->resize.allow = 0;
  224. }
  225. }
  226. void _caca_set_term_title(char const *str)
  227. {
  228. #if defined(HAVE_GETENV)
  229. char *term;
  230. term = getenv("TERM");
  231. if(!term || !strcmp(term, "linux"))
  232. return;
  233. #endif
  234. fprintf(stdout, "\x1b]0;%s\x07", str);
  235. fflush(stdout);
  236. }