source: libcaca/trunk/src/caca.c @ 535

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