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

Last change on this file since 322 was 322, checked in by Sam Hocevar, 17 years ago
  • libcaca.spec debian/control: + Updated the package descriptions to include cacaball.
  • doc/cacademo.1 doc/Makefile.am: + Use the cacademo manpage as the cacaball manpage.
  • src/: + Added #ifdef _DOXYGEN_SKIP_ME here and there to prvent Doxygen from

documenting bizarre stuff.

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