Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.
 
 
 
 
 
 

443 rader
9.9 KiB

  1. /*
  2. * libcaca ASCII-Art library
  3. * Copyright (c) 2002-2006 Sam Hocevar <sam@zoy.org>
  4. * All Rights Reserved
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the Do What The Fuck You Want To
  8. * Public License, Version 2, as published by Sam Hocevar. See
  9. * http://sam.zoy.org/wtfpl/COPYING for more details.
  10. */
  11. /** \file caca.c
  12. * \version \$Id$
  13. * \author Sam Hocevar <sam@zoy.org>
  14. * \brief Main \e libcaca functions
  15. *
  16. * This file contains the main functions used by \e libcaca applications to
  17. * initialise the library, get the screen properties, set the framerate and
  18. * so on.
  19. */
  20. #include "config.h"
  21. #if defined(HAVE_INTTYPES_H) || defined(_DOXYGEN_SKIP_ME)
  22. # include <inttypes.h>
  23. #else
  24. typedef unsigned int uint32_t;
  25. typedef unsigned char uint8_t;
  26. #endif
  27. #if defined(USE_SLANG)
  28. # if defined(HAVE_SLANG_SLANG_H)
  29. # include <slang/slang.h>
  30. # else
  31. # include <slang.h>
  32. # endif
  33. #endif
  34. #if defined(USE_NCURSES)
  35. # if defined(HAVE_NCURSES_H)
  36. # include <ncurses.h>
  37. # else
  38. # include <curses.h>
  39. # endif
  40. #endif
  41. #if defined(USE_CONIO)
  42. # include <dos.h>
  43. # include <conio.h>
  44. #endif
  45. #if defined(USE_X11)
  46. # include <X11/Xlib.h>
  47. #endif
  48. #if defined(USE_WIN32)
  49. # include <windows.h>
  50. #endif
  51. #if defined(USE_GL)
  52. # include <GL/gl.h>
  53. #endif
  54. #include <stdlib.h>
  55. #include <string.h>
  56. #include "cucul.h"
  57. #include "cucul_internals.h"
  58. #include "caca.h"
  59. #include "caca_internals.h"
  60. static void caca_init_driver(caca_t *kk);
  61. static void caca_init_terminal(caca_t *kk);
  62. #if defined(USE_NCURSES)
  63. static mmask_t oldmask;
  64. #endif
  65. #if defined(USE_WIN32)
  66. static CONSOLE_CURSOR_INFO cci;
  67. #endif
  68. caca_t * caca_attach(cucul_t * qq)
  69. {
  70. caca_t *kk = malloc(sizeof(caca_t));
  71. #if defined(USE_NCURSES)
  72. mmask_t newmask;
  73. #endif
  74. caca_init_driver(kk);
  75. if(kk->driver == CACA_DRIVER_NONE)
  76. return NULL;
  77. caca_init_terminal(kk);
  78. #if defined(USE_SLANG)
  79. if(kk->driver == CACA_DRIVER_SLANG)
  80. {
  81. /* Initialise slang library */
  82. SLsig_block_signals();
  83. SLtt_get_terminfo();
  84. if(SLkp_init() == -1)
  85. {
  86. SLsig_unblock_signals();
  87. return NULL;
  88. }
  89. SLang_init_tty(-1, 0, 1);
  90. if(SLsmg_init_smg() == -1)
  91. {
  92. SLsig_unblock_signals();
  93. return NULL;
  94. }
  95. SLsig_unblock_signals();
  96. SLsmg_cls();
  97. SLtt_set_cursor_visibility(0);
  98. SLkp_define_keysym("\e[M", 1001);
  99. SLtt_set_mouse_mode(1, 0);
  100. SLsmg_refresh();
  101. /* Disable scrolling so that hashmap scrolling optimization code
  102. * does not cause ugly refreshes due to slow terminals */
  103. SLtt_Term_Cannot_Scroll = 1;
  104. }
  105. else
  106. #endif
  107. #if defined(USE_NCURSES)
  108. if(kk->driver == CACA_DRIVER_NCURSES)
  109. {
  110. initscr();
  111. keypad(stdscr, TRUE);
  112. nonl();
  113. raw();
  114. noecho();
  115. nodelay(stdscr, TRUE);
  116. curs_set(0);
  117. /* Activate mouse */
  118. newmask = REPORT_MOUSE_POSITION | ALL_MOUSE_EVENTS;
  119. mousemask(newmask, &oldmask);
  120. mouseinterval(-1); /* No click emulation */
  121. /* Set the escape delay to a ridiculously low value */
  122. ESCDELAY = 10;
  123. }
  124. else
  125. #endif
  126. #if defined(USE_CONIO)
  127. if(kk->driver == CACA_DRIVER_CONIO)
  128. {
  129. _wscroll = 0;
  130. _setcursortype(_NOCURSOR);
  131. clrscr();
  132. }
  133. else
  134. #endif
  135. #if defined(USE_X11)
  136. if(kk->driver == CACA_DRIVER_X11)
  137. {
  138. /* Nothing to do */
  139. kk->x11.event_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask
  140. | ButtonReleaseMask | PointerMotionMask | StructureNotifyMask
  141. | ExposureMask;
  142. }
  143. else
  144. #endif
  145. #if defined(USE_WIN32)
  146. if(kk->driver == CACA_DRIVER_WIN32)
  147. {
  148. /* This call is allowed to fail in case we already have a console */
  149. AllocConsole();
  150. kk->win32.hin = GetStdHandle(STD_INPUT_HANDLE);
  151. kk->win32.hout = CreateFile("CONOUT$", GENERIC_READ | GENERIC_WRITE,
  152. FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
  153. OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  154. if(kk->win32.hout == INVALID_HANDLE_VALUE)
  155. return NULL;
  156. GetConsoleCursorInfo(kk->win32.hout, &cci);
  157. cci.bVisible = FALSE;
  158. SetConsoleCursorInfo(kk->win32.hout, &cci);
  159. SetConsoleMode(kk->win32.hout, ENABLE_MOUSE_INPUT);
  160. }
  161. else
  162. #endif
  163. #if defined(USE_GL)
  164. if(kk->driver == CACA_DRIVER_GL)
  165. {
  166. /* Nothing to do */
  167. }
  168. else
  169. #endif
  170. {
  171. /* Dummy */
  172. }
  173. /* Initialise events stuff */
  174. kk->events.key_timer.last_sec = 0;
  175. kk->events.key_timer.last_usec = 0;
  176. kk->events.last_key_ticks = 0;
  177. kk->events.autorepeat_ticks = 0;
  178. kk->events.last_key = 0;
  179. qq->refcount++;
  180. kk->qq = qq;
  181. kk->timer.last_sec = 0;
  182. kk->timer.last_usec = 0;
  183. kk->lastticks = 0;
  184. kk->resize = 0;
  185. kk->resize_event = 0;
  186. if(_caca_init_graphics(kk))
  187. return NULL;
  188. return kk;
  189. }
  190. void caca_detach(caca_t *kk)
  191. {
  192. _caca_end_graphics(kk);
  193. #if defined(USE_SLANG)
  194. if(kk->driver == CACA_DRIVER_SLANG)
  195. {
  196. SLtt_set_mouse_mode(0, 0);
  197. SLtt_set_cursor_visibility(1);
  198. SLang_reset_tty();
  199. SLsmg_reset_smg();
  200. }
  201. else
  202. #endif
  203. #if defined(USE_NCURSES)
  204. if(kk->driver == CACA_DRIVER_NCURSES)
  205. {
  206. mousemask(oldmask, NULL);
  207. curs_set(1);
  208. noraw();
  209. endwin();
  210. }
  211. else
  212. #endif
  213. #if defined(USE_CONIO)
  214. if(kk->driver == CACA_DRIVER_CONIO)
  215. {
  216. _wscroll = 1;
  217. textcolor((enum COLORS)WHITE);
  218. textbackground((enum COLORS)BLACK);
  219. gotoxy(_caca_width, _caca_height);
  220. cputs("\r\n");
  221. _setcursortype(_NORMALCURSOR);
  222. }
  223. else
  224. #endif
  225. #if defined(USE_X11)
  226. if(kk->driver == CACA_DRIVER_X11)
  227. {
  228. /* Nothing to do */
  229. }
  230. else
  231. #endif
  232. #if defined(USE_WIN32)
  233. if(kk->driver == CACA_DRIVER_WIN32)
  234. {
  235. SetConsoleTextAttribute(kk->win32.hout, FOREGROUND_INTENSITY
  236. | FOREGROUND_RED
  237. | FOREGROUND_GREEN
  238. | FOREGROUND_BLUE);
  239. cci.bVisible = TRUE;
  240. SetConsoleCursorInfo(kk->win32.hout, &cci);
  241. CloseHandle(kk->win32.hout);
  242. }
  243. else
  244. #endif
  245. #if defined(USE_GL)
  246. if(kk->driver == CACA_DRIVER_GL)
  247. {
  248. /* Nothing to do */
  249. }
  250. else
  251. #endif
  252. {
  253. /* Dummy */
  254. }
  255. kk->qq->refcount--;
  256. free(kk);
  257. }
  258. /*
  259. * XXX: The following functions are local.
  260. */
  261. static void caca_init_driver(caca_t *kk)
  262. {
  263. #if defined(HAVE_GETENV) && defined(HAVE_STRCASECMP)
  264. char *var = getenv("CACA_DRIVER");
  265. /* If the environment variable was set, use it */
  266. if(var && *var)
  267. {
  268. #if defined(USE_WIN32)
  269. if(!strcasecmp(var, "win32"))
  270. kk->driver = CACA_DRIVER_WIN32;
  271. else
  272. #endif
  273. #if defined(USE_CONIO)
  274. if(!strcasecmp(var, "conio"))
  275. kk->driver = CACA_DRIVER_CONIO;
  276. else
  277. #endif
  278. #if defined(USE_X11)
  279. if(!strcasecmp(var, "x11"))
  280. kk->driver = CACA_DRIVER_X11;
  281. else
  282. #endif
  283. #if defined(USE_GL)
  284. if(!strcasecmp(var, "gl"))
  285. kk->driver = CACA_DRIVER_GL;
  286. else
  287. #endif
  288. #if defined(USE_SLANG)
  289. if(!strcasecmp(var, "slang"))
  290. kk->driver = CACA_DRIVER_SLANG;
  291. else
  292. #endif
  293. #if defined(USE_NCURSES)
  294. if(!strcasecmp(var, "ncurses"))
  295. kk->driver = CACA_DRIVER_NCURSES;
  296. else
  297. #endif
  298. kk->driver = CACA_DRIVER_NONE;
  299. return;
  300. }
  301. #endif
  302. #if defined(USE_WIN32)
  303. kk->driver = CACA_DRIVER_WIN32;
  304. return;
  305. #endif
  306. #if defined(USE_CONIO)
  307. kk->driver = CACA_DRIVER_CONIO;
  308. return;
  309. #endif
  310. #if defined(USE_X11)
  311. #if defined(HAVE_GETENV)
  312. if(getenv("DISPLAY") && *(getenv("DISPLAY")))
  313. #endif
  314. {
  315. kk->driver = CACA_DRIVER_X11;
  316. return;
  317. }
  318. #endif
  319. #if defined(USE_GL)
  320. #if defined(HAVE_GETENV) && defined(GLUT_XLIB_IMPLEMENTATION)
  321. if(getenv("DISPLAY") && *(getenv("DISPLAY")))
  322. #endif
  323. {
  324. kk->driver = CACA_DRIVER_GL;
  325. return;
  326. }
  327. #endif
  328. #if defined(USE_SLANG)
  329. kk->driver = CACA_DRIVER_SLANG;
  330. return;
  331. #endif
  332. #if defined(USE_NCURSES)
  333. kk->driver = CACA_DRIVER_NCURSES;
  334. return;
  335. #endif
  336. kk->driver = CACA_DRIVER_NONE;
  337. return;
  338. }
  339. static void caca_init_terminal(caca_t *kk)
  340. {
  341. #if defined(HAVE_GETENV) && defined(HAVE_PUTENV) && \
  342. (defined(USE_SLANG) || defined(USE_NCURSES))
  343. char *term, *colorterm, *other;
  344. #endif
  345. #if defined(USE_SLANG)
  346. if(kk->driver != CACA_DRIVER_SLANG)
  347. #endif
  348. #if defined(USE_NCURSES)
  349. if(kk->driver != CACA_DRIVER_NCURSES)
  350. #endif
  351. return;
  352. #if defined(HAVE_GETENV) && defined(HAVE_PUTENV) && \
  353. (defined(USE_SLANG) || defined(USE_NCURSES))
  354. term = getenv("TERM");
  355. colorterm = getenv("COLORTERM");
  356. if(term && !strcmp(term, "xterm"))
  357. {
  358. /* If we are using gnome-terminal, it's really a 16 colour terminal */
  359. if(colorterm && !strcmp(colorterm, "gnome-terminal"))
  360. {
  361. #if defined(USE_NCURSES)
  362. if(kk->driver == CACA_DRIVER_NCURSES)
  363. {
  364. SCREEN *screen;
  365. screen = newterm("xterm-16color", stdout, stdin);
  366. if(screen == NULL)
  367. return;
  368. endwin();
  369. }
  370. #endif
  371. (void)putenv("TERM=xterm-16color");
  372. return;
  373. }
  374. /* Ditto if we are using Konsole */
  375. other = getenv("KONSOLE_DCOP_SESSION");
  376. if(other)
  377. {
  378. #if defined(USE_NCURSES)
  379. if(kk->driver == CACA_DRIVER_NCURSES)
  380. {
  381. SCREEN *screen;
  382. screen = newterm("xterm-16color", stdout, stdin);
  383. if(screen == NULL)
  384. return;
  385. endwin();
  386. }
  387. #endif
  388. (void)putenv("TERM=xterm-16color");
  389. return;
  390. }
  391. }
  392. #endif
  393. }