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