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.

пре 20 година
пре 21 година
пре 21 година
пре 21 година
пре 20 година
пре 20 година
пре 20 година
пре 20 година
пре 20 година
пре 20 година
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442
  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. }