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