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.
 
 
 
 
 
 

271 line
7.4 KiB

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