source: libcaca/branches/0.4/src/caca.c

Last change on this file was 268, checked in by Sam Hocevar, 19 years ago
  • src/io.c: + Added caca_wait_event(), a blocking caca_get_event().
  • src/ examples/: + More documentation.
  • doc/doxygen.cfg.in: + doc/doxygen.cfg is now generated by configure, so that we can use

@top_srcdir@ and we no longer need to hardcode PROJECT_NUMBER.

+ Create manpages.

  • Property svn:keywords set to Id
File size: 12.9 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 268 2003-12-23 13:27:40Z 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/** \brief Initialise \e libcaca.
65 *
66 *  This function initialises internal \e libcaca structures and the backend
67 *  that will be used for subsequent graphical operations. It must be the
68 *  first \e libcaca function to be called in a function. caca_end() should
69 *  be called at the end of the program to free all allocated resources.
70 *
71 *  \return 0 upon success, a non-zero value if an error occurs.
72 */
73int caca_init(void)
74{
75#if defined(USE_NCURSES)
76    mmask_t newmask;
77#endif
78
79    caca_init_driver();
80
81    if(_caca_driver == CACA_DRIVER_NONE)
82        return -1;
83
84    caca_init_features();
85    caca_init_terminal();
86
87#if defined(USE_SLANG)
88    if(_caca_driver == CACA_DRIVER_SLANG)
89    {
90        /* Initialise slang library */
91        SLsig_block_signals();
92        SLtt_get_terminfo();
93
94        if(SLkp_init() == -1)
95        {
96            SLsig_unblock_signals();
97            return -1;
98        }
99
100        SLang_init_tty(-1, 0, 1);
101
102        if(SLsmg_init_smg() == -1)
103        {
104            SLsig_unblock_signals();
105            return -1;
106        }
107
108        SLsig_unblock_signals();
109
110        SLsmg_cls();
111        SLtt_set_cursor_visibility(0);
112        SLkp_define_keysym("\e[M", 1001);
113        SLtt_set_mouse_mode(1, 0);
114        SLsmg_refresh();
115
116        /* Disable scrolling so that hashmap scrolling optimization code
117         * does not cause ugly refreshes due to slow terminals */
118        SLtt_Term_Cannot_Scroll = 1;
119    }
120    else
121#endif
122#if defined(USE_NCURSES)
123    if(_caca_driver == CACA_DRIVER_NCURSES)
124    {
125        initscr();
126        keypad(stdscr, TRUE);
127        nonl();
128        cbreak();
129        noecho();
130        nodelay(stdscr, TRUE);
131        curs_set(0);
132
133        /* Activate mouse */
134        newmask = ALL_MOUSE_EVENTS;
135        mousemask(newmask, &oldmask);
136    }
137    else
138#endif
139#if defined(USE_CONIO)
140    if(_caca_driver == CACA_DRIVER_CONIO)
141    {
142        _wscroll = 0;
143        _setcursortype(_NOCURSOR);
144        clrscr();
145    }
146    else
147#endif
148#if defined(USE_X11)
149    {
150        /* Nothing to do */
151    }
152#endif
153
154    if(_caca_init_graphics())
155        return -1;
156
157    return 0;
158}
159
160/** \brief Get the screen width.
161 *
162 *  This function returns the current screen width, in character cells.
163 *
164 *  \return The screen width.
165 */
166unsigned int caca_get_width(void)
167{
168    return _caca_width;
169}
170
171/** \brief Get the screen height.
172 *
173 *  This function returns the current screen height, in character cells.
174 *
175 *  \return The screen height.
176 */
177unsigned int caca_get_height(void)
178{
179    return _caca_height;
180}
181
182/** \brief Translate a colour index into the colour's name.
183 *
184 *  This function translates a caca_color enum into a human-readable
185 *  description string of the associated colour.
186 *
187 *  \param color The colour value.
188 *  \return A static string containing the colour's name.
189 */
190const char *caca_get_color_name(enum caca_color color)
191{
192    static const char *color_names[] =
193    {
194        "black",
195        "blue",
196        "green",
197        "cyan",
198        "red",
199        "magenta",
200        "brown",
201        "light gray",
202        "dark gray",
203        "light blue",
204        "light green",
205        "light cyan",
206        "light red",
207        "light magenta",
208        "yellow",
209        "white",
210    };
211
212    if(color < 0 || color > 15)
213        return "unknown";
214
215    return color_names[color];
216}
217
218/** \brief Get the current value of a feature.
219 *
220 *  This function retrieves the value of an internal \e libcaca feature. A
221 *  generic feature value is expected, such as CACA_ANTIALIASING.
222 *
223 *  \param feature The requested feature.
224 *  \return The current value of the feature or CACA_UNKNOWN_FEATURE if an
225 *          error occurred..
226 */
227enum caca_feature caca_get_feature(enum caca_feature feature)
228{
229    switch(feature)
230    {
231        case CACA_BACKGROUND:
232            return _caca_background;
233        case CACA_ANTIALIASING:
234            return _caca_antialiasing;
235        case CACA_DITHERING:
236            return _caca_dithering;
237
238        default:
239            return CACA_UNKNOWN_FEATURE;
240    }
241}
242
243/** \brief Set a feature.
244 *
245 *  This function sets an internal \e libcaca feature such as the antialiasing
246 *  or dithering modes. If a specific feature such as CACA_DITHERING_RANDOM,
247 *  caca_set_feature() will set it immediately. If a generic feature is given
248 *  instead, such as CACA_DITHERING, the default value will be used instead.
249 *
250 *  \param feature The requested feature.
251 */
252void caca_set_feature(enum caca_feature feature)
253{
254    switch(feature)
255    {
256        case CACA_BACKGROUND:
257            feature = CACA_BACKGROUND_SOLID;
258        case CACA_BACKGROUND_BLACK:
259        case CACA_BACKGROUND_SOLID:
260            _caca_background = feature;
261            break;
262
263        case CACA_ANTIALIASING:
264            feature = CACA_ANTIALIASING_PREFILTER;
265        case CACA_ANTIALIASING_NONE:
266        case CACA_ANTIALIASING_PREFILTER:
267            _caca_antialiasing = feature;
268            break;
269
270        case CACA_DITHERING:
271            feature = CACA_DITHERING_ORDERED4;
272        case CACA_DITHERING_NONE:
273        case CACA_DITHERING_ORDERED2:
274        case CACA_DITHERING_ORDERED4:
275        case CACA_DITHERING_ORDERED8:
276        case CACA_DITHERING_RANDOM:
277            _caca_dithering = feature;
278            break;
279
280        case CACA_UNKNOWN_FEATURE:
281            break;
282    }
283}
284
285/** \brief Translate a feature value into the feature's name.
286 *
287 *  This function translates a caca_feature enum into a human-readable
288 *  description string of the associated feature.
289 *
290 *  \param feature The feature value.
291 *  \return A static string containing the feature's name.
292 */
293const char *caca_get_feature_name(enum caca_feature feature)
294{
295    switch(feature)
296    {
297        case CACA_BACKGROUND_BLACK: return "black background";
298        case CACA_BACKGROUND_SOLID: return "solid background";
299
300        case CACA_ANTIALIASING_NONE:      return "no antialiasing";
301        case CACA_ANTIALIASING_PREFILTER: return "prefilter antialiasing";
302
303        case CACA_DITHERING_NONE:     return "no dithering";
304        case CACA_DITHERING_ORDERED2: return "2x2 ordered dithering";
305        case CACA_DITHERING_ORDERED4: return "4x4 ordered dithering";
306        case CACA_DITHERING_ORDERED8: return "8x8 ordered dithering";
307        case CACA_DITHERING_RANDOM:   return "random dithering";
308
309        default: return "unknown";
310    }
311}
312
313/** \brief Uninitialise \e libcaca.
314 *
315 *  This function frees all resources allocated by caca_init(). After
316 *  caca_end() has been called, no other \e libcaca functions may be used
317 *  unless a new call to caca_init() is done.
318 */
319void caca_end(void)
320{
321    _caca_end_graphics();
322
323#if defined(USE_SLANG)
324    if(_caca_driver == CACA_DRIVER_SLANG)
325    {
326        SLtt_set_mouse_mode(0, 0);
327        SLtt_set_cursor_visibility(1);
328        SLang_reset_tty();
329        SLsmg_reset_smg();
330    }
331    else
332#endif
333#if defined(USE_NCURSES)
334    if(_caca_driver == CACA_DRIVER_NCURSES)
335    {
336        mousemask(oldmask, NULL);
337        curs_set(1);
338        endwin();
339    }
340    else
341#endif
342#if defined(USE_CONIO)
343    if(_caca_driver == CACA_DRIVER_CONIO)
344    {
345        _wscroll = 1;
346        textcolor((enum COLORS)WHITE);
347        textbackground((enum COLORS)BLACK);
348        gotoxy(_caca_width, _caca_height);
349        cputs("\r\n");
350        _setcursortype(_NORMALCURSOR);
351    }
352    else
353#endif
354#if defined(USE_X11)
355    if(_caca_driver == CACA_DRIVER_X11)
356    {
357        /* Nothing to do */
358    }
359#endif
360}
361
362/*
363 * XXX: The following functions are local.
364 */
365
366static void caca_init_driver(void)
367{
368#if defined(HAVE_GETENV) && defined(HAVE_STRCASECMP)
369    char *var = getenv("CACA_DRIVER");
370
371    /* If the environment variable was set, use it */
372    if(var && *var)
373    {
374#if defined(USE_CONIO)
375        if(!strcasecmp(var, "conio"))
376            _caca_driver = CACA_DRIVER_CONIO;
377        else
378#endif
379#if defined(USE_NCURSES)
380        if(!strcasecmp(var, "ncurses"))
381            _caca_driver = CACA_DRIVER_NCURSES;
382        else
383#endif
384#if defined(USE_SLANG)
385        if(!strcasecmp(var, "slang"))
386            _caca_driver = CACA_DRIVER_SLANG;
387        else
388#endif
389#if defined(USE_X11)
390        if(!strcasecmp(var, "x11"))
391            _caca_driver = CACA_DRIVER_X11;
392        else
393#endif
394        _caca_driver = CACA_DRIVER_NONE;
395
396        return;
397    }
398#endif
399
400#if defined(USE_CONIO)
401    _caca_driver = CACA_DRIVER_CONIO;
402    return;
403#endif
404#if defined(USE_NCURSES)
405    _caca_driver = CACA_DRIVER_NCURSES;
406    return;
407#endif
408#if defined(USE_SLANG)
409    _caca_driver = CACA_DRIVER_SLANG;
410    return;
411#endif
412#if defined(USE_X11)
413    _caca_driver = CACA_DRIVER_X11;
414    return;
415#endif
416    _caca_driver = CACA_DRIVER_NONE;
417    return;
418}
419
420static void caca_init_features(void)
421{
422    /* FIXME: if strcasecmp isn't available, use strcmp */
423#if defined(HAVE_GETENV) && defined(HAVE_STRCASECMP)
424    char *var;
425#endif
426
427    caca_set_feature(CACA_BACKGROUND);
428    caca_set_feature(CACA_ANTIALIASING);
429    caca_set_feature(CACA_DITHERING);
430
431#if defined(HAVE_GETENV) && defined(HAVE_STRCASECMP)
432    if((var = getenv("CACA_BACKGROUND")))
433    {
434        if(!strcasecmp("black", var))
435            caca_set_feature(CACA_BACKGROUND_BLACK);
436        else if(!strcasecmp("solid", var))
437            caca_set_feature(CACA_BACKGROUND_SOLID);
438    }
439
440    if((var = getenv("CACA_ANTIALIASING")))
441    {
442        if(!strcasecmp("none", var))
443            caca_set_feature(CACA_ANTIALIASING_NONE);
444        else if(!strcasecmp("prefilter", var))
445            caca_set_feature(CACA_ANTIALIASING_PREFILTER);
446    }
447
448    if((var = getenv("CACA_DITHERING")))
449    {
450        if(!strcasecmp("none", var))
451            caca_set_feature(CACA_DITHERING_NONE);
452        else if(!strcasecmp("ordered2", var))
453            caca_set_feature(CACA_DITHERING_ORDERED2);
454        else if(!strcasecmp("ordered4", var))
455            caca_set_feature(CACA_DITHERING_ORDERED4);
456        else if(!strcasecmp("ordered8", var))
457            caca_set_feature(CACA_DITHERING_ORDERED8);
458        else if(!strcasecmp("random", var))
459            caca_set_feature(CACA_DITHERING_RANDOM);
460    }
461#endif
462}
463
464static void caca_init_terminal(void)
465{
466#if defined(HAVE_GETENV) && defined(HAVE_PUTENV) \
467     && (defined(USE_SLANG) || defined(USE_NCURSES))
468    char *term, *colorterm, *other;
469
470    if(_caca_driver != CACA_DRIVER_NCURSES &&
471       _caca_driver != CACA_DRIVER_SLANG)
472        return;
473
474    term = getenv("TERM");
475    colorterm = getenv("COLORTERM");
476
477    if(term && !strcmp(term, "xterm"))
478    {
479        /* If we are using gnome-terminal, it's really a 16 colour terminal */
480        if(colorterm && !strcmp(colorterm, "gnome-terminal"))
481        {
482#if defined(USE_NCURSES)
483            if(_caca_driver == CACA_DRIVER_NCURSES)
484            {
485                SCREEN *screen;
486                screen = newterm("xterm-16color", stdout, stdin);
487                if(screen == NULL)
488                    return;
489                endwin();
490            }
491#endif
492            (void)putenv("TERM=xterm-16color");
493            return;
494        }
495
496        /* Ditto if we are using Konsole */
497        other = getenv("KONSOLE_DCOP_SESSION");
498        if(other)
499        {
500#if defined(USE_NCURSES)
501            if(_caca_driver == CACA_DRIVER_NCURSES)
502            {
503                SCREEN *screen;
504                screen = newterm("xterm-16color", stdout, stdin);
505                if(screen == NULL)
506                    return;
507                endwin();
508            }
509#endif
510            (void)putenv("TERM=xterm-16color");
511            return;
512        }
513    }
514#endif
515}
516
Note: See TracBrowser for help on using the repository browser.