Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

19 лет назад
19 лет назад
21 лет назад
19 лет назад
19 лет назад
19 лет назад
19 лет назад
19 лет назад
19 лет назад
19 лет назад
19 лет назад
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. /*
  2. * libcaca Colour ASCII-Art library
  3. * Copyright (c) 2006 Sam Hocevar <sam@zoy.org>
  4. * All Rights Reserved
  5. *
  6. * $Id$
  7. *
  8. * This library is free software; you can redistribute it and/or
  9. * modify it under the terms of the Do What The Fuck You Want To
  10. * Public License, Version 2, as published by Sam Hocevar. See
  11. * http://sam.zoy.org/wtfpl/COPYING for more details.
  12. */
  13. /*
  14. * This file contains the main functions used by \e libcaca applications to
  15. * initialise the library, get the screen properties, set the framerate and
  16. * so on.
  17. */
  18. #include "config.h"
  19. #include "common.h"
  20. #if !defined(__KERNEL__)
  21. # include <stdlib.h>
  22. # include <string.h>
  23. # include <stdio.h>
  24. # if defined(USE_PLUGINS)
  25. # if defined(HAVE_DLFCN_H)
  26. # include <dlfcn.h>
  27. # endif
  28. # endif
  29. #endif
  30. #include "cucul.h"
  31. #include "cucul_internals.h"
  32. #include "caca.h"
  33. #include "caca_internals.h"
  34. #if defined(USE_PLUGINS)
  35. # define gl_install(p) caca_plugin_install("gl", p)
  36. # define x11_install(p) caca_plugin_install("x11", p)
  37. #endif
  38. static int caca_select_driver(caca_display_t *);
  39. #if defined(USE_PLUGINS)
  40. static int caca_plugin_install(char const *, caca_display_t *);
  41. #endif
  42. /** \brief Attach a caca graphical context to a cucul canvas.
  43. *
  44. * Create a graphical context using device-dependent features (ncurses for
  45. * terminals, an X11 window, a DOS command window...) that attaches to a
  46. * libcucul canvas. Everything that gets drawn in the libcucul canvas can
  47. * then be displayed by the libcaca driver.
  48. *
  49. * If an error occurs, NULL is returned and \b errno is set accordingly:
  50. * - \c ENOMEM Not enough memory.
  51. * - \c ENODEV Graphical device could not be initialised.
  52. *
  53. * \param cv The cucul cavas.
  54. * \return The caca graphical context or NULL if an error occurred.
  55. */
  56. caca_display_t * caca_create_display(cucul_canvas_t * cv)
  57. {
  58. caca_display_t *dp = malloc(sizeof(caca_display_t));
  59. if(!dp)
  60. {
  61. seterrno(ENOMEM);
  62. return NULL;
  63. }
  64. dp->cv = cv;
  65. #if defined(USE_PLUGINS)
  66. dp->plugin = NULL;
  67. #endif
  68. if(caca_select_driver(dp))
  69. {
  70. #if defined(USE_PLUGINS)
  71. if(dp->plugin)
  72. dlclose(dp->plugin);
  73. #endif
  74. free(dp);
  75. seterrno(ENODEV);
  76. return NULL;
  77. }
  78. if(dp->drv.init_graphics(dp))
  79. {
  80. #if defined(USE_PLUGINS)
  81. if(dp->plugin)
  82. dlclose(dp->plugin);
  83. #endif
  84. free(dp);
  85. seterrno(ENODEV);
  86. return NULL;
  87. }
  88. /* Attached! */
  89. dp->cv->refcount++;
  90. /* Graphics stuff */
  91. dp->delay = 0;
  92. dp->rendertime = 0;
  93. /* Events stuff */
  94. #if defined(USE_SLANG) || defined(USE_NCURSES)
  95. dp->events.key_timer.last_sec = 0;
  96. dp->events.key_timer.last_usec = 0;
  97. dp->events.last_key_ticks = 0;
  98. dp->events.autorepeat_ticks = 0;
  99. dp->events.last_key_event.type = CACA_EVENT_NONE;
  100. #endif
  101. #if defined(USE_SLANG) || defined(USE_NCURSES) || defined(USE_CONIO) || defined(USE_GL)
  102. dp->events.queue = 0;
  103. #endif
  104. dp->timer.last_sec = 0;
  105. dp->timer.last_usec = 0;
  106. dp->lastticks = 0;
  107. /* Mouse position */
  108. dp->mouse.x = dp->cv->width / 2;
  109. dp->mouse.y = dp->cv->height / 2;
  110. /* Resize events */
  111. dp->resize.resized = 0;
  112. return dp;
  113. }
  114. /** \brief Detach a caca graphical context from a cucul backend context.
  115. *
  116. * Detach a graphical context from its cucul backend and destroy it. The
  117. * libcucul canvas continues to exist and other graphical contexts can be
  118. * attached to it afterwards.
  119. *
  120. * This function never fails.
  121. *
  122. * \param dp The libcaca graphical context.
  123. * \return This function always returns 0.
  124. */
  125. int caca_free_display(caca_display_t *dp)
  126. {
  127. dp->drv.end_graphics(dp);
  128. #if defined(USE_PLUGINS)
  129. if(dp->plugin)
  130. dlclose(dp->plugin);
  131. #endif
  132. dp->cv->refcount--;
  133. free(dp);
  134. return 0;
  135. }
  136. /*
  137. * XXX: The following functions are local.
  138. */
  139. static int caca_select_driver(caca_display_t *dp)
  140. {
  141. #if defined(HAVE_GETENV) && defined(HAVE_STRCASECMP)
  142. char *var = getenv("CACA_DRIVER");
  143. /* If the environment variable was set, use it */
  144. if(var && *var)
  145. {
  146. #if defined(USE_WIN32)
  147. if(!strcasecmp(var, "win32")) return win32_install(dp);
  148. #endif
  149. #if defined(USE_CONIO)
  150. if(!strcasecmp(var, "conio")) return conio_install(dp);
  151. #endif
  152. #if defined(USE_X11)
  153. if(!strcasecmp(var, "x11")) return x11_install(dp);
  154. #endif
  155. #if defined(USE_GL)
  156. if(!strcasecmp(var, "gl")) return gl_install(dp);
  157. #endif
  158. #if !defined(__KERNEL__)
  159. if(!strcasecmp(var, "raw")) return raw_install(dp);
  160. #endif
  161. #if defined(USE_SLANG)
  162. if(!strcasecmp(var, "slang")) return slang_install(dp);
  163. #endif
  164. #if defined(USE_NCURSES)
  165. if(!strcasecmp(var, "ncurses")) return ncurses_install(dp);
  166. #endif
  167. #if defined(USE_VGA)
  168. if(!strcasecmp(var, "vga")) return vga_install(dp);
  169. #endif
  170. return -1;
  171. }
  172. #endif
  173. #if defined(USE_WIN32)
  174. if(win32_install(dp) == 0) return 0;
  175. #endif
  176. #if defined(USE_CONIO)
  177. if(conio_install(dp) == 0) return 0;
  178. #endif
  179. #if defined(USE_VGA)
  180. if(vga_install(dp) == 0) return 0;
  181. #endif
  182. #if defined(USE_X11)
  183. if(x11_install(dp) == 0) return 0;
  184. #endif
  185. #if defined(USE_GL)
  186. if(gl_install(dp) == 0) return 0;
  187. #endif
  188. /* ncurses has a higher priority than slang because it has better colour
  189. * support across terminal types, despite being slightly slower. */
  190. #if defined(USE_NCURSES)
  191. if(ncurses_install(dp) == 0) return 0;
  192. #endif
  193. #if defined(USE_SLANG)
  194. if(slang_install(dp) == 0) return 0;
  195. #endif
  196. return -1;
  197. }
  198. #if defined(USE_PLUGINS)
  199. static int caca_plugin_install(char const *name, caca_display_t *dp)
  200. {
  201. char buf[512];
  202. int (*sym) (caca_display_t *);
  203. sprintf(buf, "%s/lib%s_plugin.so", PLUGINDIR, name);
  204. dp->plugin = dlopen(buf, RTLD_NOW);
  205. if(!dp->plugin)
  206. {
  207. sprintf(buf, "lib%s_plugin.so", name);
  208. dp->plugin = dlopen(buf, RTLD_NOW);
  209. if(!dp->plugin)
  210. return -1;
  211. }
  212. sprintf(buf, "%s_install", name);
  213. sym = dlsym(dp->plugin, buf);
  214. if(!sym)
  215. {
  216. dlclose(dp->plugin);
  217. return -1;
  218. }
  219. return sym(dp);
  220. }
  221. #endif