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

Last change on this file since 265 was 265, checked in by Sam Hocevar, 17 years ago
  • src/graphics.c src/caca.c src/io.c: + Support for simultaneously compiled-in drivers. + Honour the CACA_DRIVER environment variable.
  • configure.ac: + Drivers are no longer mutually exclusive.
  • Property svn:keywords set to Id
File size: 11.5 KB
Line 
1/*
2 *   libcaca       ASCII-Art library
3 *   Copyright (c) 2002, 2003 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 GNU Lesser General Public
8 *   License as published by the Free Software Foundation; either
9 *   version 2 of the License, or (at your option) any later version.
10 *
11 *   This library is distributed in the hope that it will be useful,
12 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
13 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 *   Lesser General Public License for more details.
15 *
16 *   You should have received a copy of the GNU Lesser General Public
17 *   License along with this library; if not, write to the Free Software
18 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 *   02111-1307  USA
20 */
21
22/**  \file caca.c
23 *   \version \$Id: caca.c 265 2003-12-22 15:26:12Z sam $
24 *   \author Sam Hocevar <sam@zoy.org>
25 *   \brief Main \e libcaca functions
26 *
27 *   This file contains the main functions used by \e libcaca applications to
28 *   initialise the library, get the screen properties, set the framerate and
29 *   so on.
30 */
31
32#include "config.h"
33
34#if defined(USE_SLANG)
35#   include <slang.h>
36#endif
37#if defined(USE_NCURSES)
38#   include <curses.h>
39#endif
40#if defined(USE_CONIO)
41#   include <dos.h>
42#   include <conio.h>
43#endif
44#if defined(USE_X11)
45#   include <X11/Xlib.h>
46#endif
47
48#include <stdlib.h>
49#include <string.h>
50
51#include "caca.h"
52#include "caca_internals.h"
53
54static void caca_init_driver(void);
55static void caca_init_features(void);
56static void caca_init_terminal(void);
57
58enum caca_driver _caca_driver;
59
60#if defined(USE_NCURSES)
61static mmask_t oldmask;
62#endif
63
64/**
65 * \brief Initialise libcaca.
66 *
67 * \return 0 upon success, a non-zero value if an error occurs.
68 */
69int caca_init(void)
70{
71#if defined(USE_NCURSES)
72    mmask_t newmask;
73#endif
74
75    caca_init_driver();
76
77    if(_caca_driver == CACA_DRIVER_NONE)
78        return -1;
79
80    caca_init_features();
81    caca_init_terminal();
82
83#if defined(USE_SLANG)
84    if(_caca_driver == CACA_DRIVER_SLANG)
85    {
86        /* Initialise slang library */
87        SLsig_block_signals();
88        SLtt_get_terminfo();
89
90        if(SLkp_init() == -1)
91        {
92            SLsig_unblock_signals();
93            return -1;
94        }
95
96        SLang_init_tty(-1, 0, 1);
97
98        if(SLsmg_init_smg() == -1)
99        {
100            SLsig_unblock_signals();
101            return -1;
102        }
103
104        SLsig_unblock_signals();
105
106        SLsmg_cls();
107        SLtt_set_cursor_visibility(0);
108        SLkp_define_keysym("\e[M", 1001);
109        SLtt_set_mouse_mode(1, 0);
110        SLsmg_refresh();
111
112        /* Disable scrolling so that hashmap scrolling optimization code
113         * does not cause ugly refreshes due to slow terminals */
114        SLtt_Term_Cannot_Scroll = 1;
115    }
116    else
117#endif
118#if defined(USE_NCURSES)
119    if(_caca_driver == CACA_DRIVER_NCURSES)
120    {
121        initscr();
122        keypad(stdscr, TRUE);
123        nonl();
124        cbreak();
125        noecho();
126        nodelay(stdscr, TRUE);
127        curs_set(0);
128
129        /* Activate mouse */
130        newmask = ALL_MOUSE_EVENTS;
131        mousemask(newmask, &oldmask);
132    }
133    else
134#endif
135#if defined(USE_CONIO)
136    if(_caca_driver == CACA_DRIVER_CONIO)
137    {
138        _wscroll = 0;
139        _setcursortype(_NOCURSOR);
140        clrscr();
141    }
142    else
143#endif
144#if defined(USE_X11)
145    {
146        /* Nothing to do */
147    }
148#endif
149
150    if(_caca_init_graphics())
151        return -1;
152
153    return 0;
154}
155
156/**
157 * \brief Get the screen width.
158 *
159 * \return The screen width, in character cells.
160 */
161unsigned int caca_get_width(void)
162{
163    return _caca_width;
164}
165
166/**
167 * \brief Get the screen height.
168 *
169 * \return The screen height, in character cells.
170 */
171unsigned int caca_get_height(void)
172{
173    return _caca_height;
174}
175
176/**
177 * \brief Translate a colour value into its name.
178 *
179 * \param color The colour value.
180 * \return A static string containing the colour's name.
181 */
182const char *caca_get_color_name(enum caca_color color)
183{
184    static const char *color_names[] =
185    {
186        "black",
187        "blue",
188        "green",
189        "cyan",
190        "red",
191        "magenta",
192        "brown",
193        "light gray",
194        "dark gray",
195        "light blue",
196        "light green",
197        "light cyan",
198        "light red",
199        "light magenta",
200        "yellow",
201        "white",
202    };
203
204    if(color < 0 || color > 15)
205        return "unknown";
206
207    return color_names[color];
208}
209
210/**
211 * \brief Get the current value of a feature.
212 *
213 * \param feature The requested feature.
214 * \return The current value of the feature.
215 */
216enum caca_feature caca_get_feature(enum caca_feature feature)
217{
218    switch(feature)
219    {
220        case CACA_BACKGROUND:
221            return _caca_background;
222        case CACA_ANTIALIASING:
223            return _caca_antialiasing;
224        case CACA_DITHERING:
225            return _caca_dithering;
226
227        default:
228            return CACA_UNKNOWN_FEATURE;
229    }
230}
231
232/**
233 * \brief Set a feature.
234 *
235 * \param feature The wanted feature.
236 * \return void
237 */
238void caca_set_feature(enum caca_feature feature)
239{
240    switch(feature)
241    {
242        case CACA_BACKGROUND:
243            feature = CACA_BACKGROUND_SOLID;
244        case CACA_BACKGROUND_BLACK:
245        case CACA_BACKGROUND_SOLID:
246            _caca_background = feature;
247            break;
248
249        case CACA_ANTIALIASING:
250            feature = CACA_ANTIALIASING_PREFILTER;
251        case CACA_ANTIALIASING_NONE:
252        case CACA_ANTIALIASING_PREFILTER:
253            _caca_antialiasing = feature;
254            break;
255
256        case CACA_DITHERING:
257            feature = CACA_DITHERING_ORDERED4;
258        case CACA_DITHERING_NONE:
259        case CACA_DITHERING_ORDERED2:
260        case CACA_DITHERING_ORDERED4:
261        case CACA_DITHERING_ORDERED8:
262        case CACA_DITHERING_RANDOM:
263            _caca_dithering = feature;
264            break;
265
266        case CACA_UNKNOWN_FEATURE:
267            break;
268    }
269}
270
271/**
272 * \brief Translate a feature value into its name.
273 *
274 * \param feature The feature value.
275 * \return A static string containing the feature's name.
276 */
277const char *caca_get_feature_name(enum caca_feature feature)
278{
279    switch(feature)
280    {
281        case CACA_BACKGROUND_BLACK: return "black background";
282        case CACA_BACKGROUND_SOLID: return "solid background";
283
284        case CACA_ANTIALIASING_NONE:      return "no antialiasing";
285        case CACA_ANTIALIASING_PREFILTER: return "prefilter antialiasing";
286
287        case CACA_DITHERING_NONE:     return "no dithering";
288        case CACA_DITHERING_ORDERED2: return "2x2 ordered dithering";
289        case CACA_DITHERING_ORDERED4: return "4x4 ordered dithering";
290        case CACA_DITHERING_ORDERED8: return "8x8 ordered dithering";
291        case CACA_DITHERING_RANDOM:   return "random dithering";
292
293        default: return "unknown";
294    }
295}
296
297/**
298 * \brief Uninitialise libcaca.
299 *
300 * \return void
301 */
302void caca_end(void)
303{
304    _caca_end_graphics();
305
306#if defined(USE_SLANG)
307    if(_caca_driver == CACA_DRIVER_SLANG)
308    {
309        SLtt_set_mouse_mode(0, 0);
310        SLtt_set_cursor_visibility(1);
311        SLang_reset_tty();
312        SLsmg_reset_smg();
313    }
314    else
315#endif
316#if defined(USE_NCURSES)
317    if(_caca_driver == CACA_DRIVER_NCURSES)
318    {
319        mousemask(oldmask, NULL);
320        curs_set(1);
321        endwin();
322    }
323    else
324#endif
325#if defined(USE_CONIO)
326    if(_caca_driver == USE_CONIO)
327    {
328        _wscroll = 1;
329        textcolor((enum COLORS)WHITE);
330        textbackground((enum COLORS)BLACK);
331        gotoxy(_caca_width, _caca_height);
332        cputs("\r\n");
333        _setcursortype(_NORMALCURSOR);
334    }
335    else
336#endif
337#if defined(USE_X11)
338    if(_caca_driver == USE_X11)
339    {
340        /* Nothing to do */
341    }
342#endif
343}
344
345static void caca_init_driver(void)
346{
347#if defined(HAVE_GETENV) && defined(HAVE_STRCASECMP)
348    char *var = getenv("CACA_DRIVER");
349
350    /* If the environment variable was set, use it */
351    if(var && *var)
352    {
353#if defined(USE_CONIO)
354        if(!strcasecmp(var, "conio"))
355            _caca_driver = CACA_DRIVER_CONIO;
356        else
357#endif
358#if defined(USE_NCURSES)
359        if(!strcasecmp(var, "ncurses"))
360            _caca_driver = CACA_DRIVER_NCURSES;
361        else
362#endif
363#if defined(USE_SLANG)
364        if(!strcasecmp(var, "slang"))
365            _caca_driver = CACA_DRIVER_SLANG;
366        else
367#endif
368#if defined(USE_X11)
369        if(!strcasecmp(var, "x11"))
370            _caca_driver = CACA_DRIVER_X11;
371        else
372#endif
373        _caca_driver = CACA_DRIVER_NONE;
374
375        return;
376    }
377#endif
378
379#if defined(USE_CONIO)
380    _caca_driver = CACA_DRIVER_CONIO;
381    return;
382#endif
383#if defined(USE_NCURSES)
384    _caca_driver = CACA_DRIVER_NCURSES;
385    return;
386#endif
387#if defined(USE_SLANG)
388    _caca_driver = CACA_DRIVER_SLANG;
389    return;
390#endif
391#if defined(USE_X11)
392    _caca_driver = CACA_DRIVER_X11;
393    return;
394#endif
395    _caca_driver = CACA_DRIVER_NONE;
396    return;
397}
398
399static void caca_init_features(void)
400{
401    /* FIXME: if strcasecmp isn't available, use strcmp */
402#if defined(HAVE_GETENV) && defined(HAVE_STRCASECMP)
403    char *var;
404#endif
405
406    caca_set_feature(CACA_BACKGROUND);
407    caca_set_feature(CACA_ANTIALIASING);
408    caca_set_feature(CACA_DITHERING);
409
410#if defined(HAVE_GETENV) && defined(HAVE_STRCASECMP)
411    if((var = getenv("CACA_BACKGROUND")))
412    {
413        if(!strcasecmp("black", var))
414            caca_set_feature(CACA_BACKGROUND_BLACK);
415        else if(!strcasecmp("solid", var))
416            caca_set_feature(CACA_BACKGROUND_SOLID);
417    }
418
419    if((var = getenv("CACA_ANTIALIASING")))
420    {
421        if(!strcasecmp("none", var))
422            caca_set_feature(CACA_ANTIALIASING_NONE);
423        else if(!strcasecmp("prefilter", var))
424            caca_set_feature(CACA_ANTIALIASING_PREFILTER);
425    }
426
427    if((var = getenv("CACA_DITHERING")))
428    {
429        if(!strcasecmp("none", var))
430            caca_set_feature(CACA_DITHERING_NONE);
431        else if(!strcasecmp("ordered2", var))
432            caca_set_feature(CACA_DITHERING_ORDERED2);
433        else if(!strcasecmp("ordered4", var))
434            caca_set_feature(CACA_DITHERING_ORDERED4);
435        else if(!strcasecmp("ordered8", var))
436            caca_set_feature(CACA_DITHERING_ORDERED8);
437        else if(!strcasecmp("random", var))
438            caca_set_feature(CACA_DITHERING_RANDOM);
439    }
440#endif
441}
442
443static void caca_init_terminal(void)
444{
445#if defined(HAVE_GETENV) && defined(HAVE_PUTENV) \
446     && (defined(USE_SLANG) || defined(USE_NCURSES))
447    char *term, *colorterm, *other;
448
449    if(_caca_driver != CACA_DRIVER_NCURSES &&
450       _caca_driver != CACA_DRIVER_SLANG)
451        return;
452
453    term = getenv("TERM");
454    colorterm = getenv("COLORTERM");
455
456    if(term && !strcmp(term, "xterm"))
457    {
458        /* If we are using gnome-terminal, it's really a 16 colour terminal */
459        if(colorterm && !strcmp(colorterm, "gnome-terminal"))
460        {
461#if defined(USE_NCURSES)
462            if(_caca_driver == USE_NCURSES)
463            {
464                SCREEN *screen;
465                screen = newterm("xterm-16color", stdout, stdin);
466                if(screen == NULL)
467                    return;
468                endwin();
469            }
470#endif
471            (void)putenv("TERM=xterm-16color");
472            return;
473        }
474
475        /* Ditto if we are using Konsole */
476        other = getenv("KONSOLE_DCOP_SESSION");
477        if(other)
478        {
479#if defined(USE_NCURSES)
480            if(_caca_driver == USE_NCURSES)
481            {
482                SCREEN *screen;
483                screen = newterm("xterm-16color", stdout, stdin);
484                if(screen == NULL)
485                    return;
486                endwin();
487            }
488#endif
489            (void)putenv("TERM=xterm-16color");
490            return;
491        }
492    }
493#endif
494}
495
Note: See TracBrowser for help on using the repository browser.