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

Last change on this file since 226 was 226, checked in by Sam Hocevar, 19 years ago
  • NOTES: + Added setab/setaf quotes from the XTerm terminfo. + Proposed a workaround for bright colours on any terminal.
  • src/caca.c: + 16 colour support for ncurses and conio.
  • src/graphics.c: + Ported to 16 colour support. + Added a missing <stdio.h> for BUFSIZ. + Disabled vsnprintf under DOS (only vsprintf exists).
  • examples/: + Don't abort if the caca.txt sprite was not found. + Ported to 16 colour support.
  • Property svn:keywords set to Id
File size: 7.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 226 2003-11-27 21:56:30Z 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#elif defined(USE_NCURSES)
37#   include <curses.h>
38#elif defined(USE_CONIO)
39#   include <dos.h>
40#   include <conio.h>
41#   if defined(SCREENUPDATE_IN_PC_H)
42#       include <pc.h>
43#   endif
44#else
45#   error "no graphics library detected"
46#endif
47
48#include <stdlib.h>
49#include <unistd.h>
50#include <string.h>
51#include <sys/time.h>
52#include <time.h>
53
54#include "caca.h"
55#include "caca_internals.h"
56
57static unsigned int _caca_delay;
58static unsigned int _caca_rendertime;
59char *_caca_empty_line;
60char *_caca_scratch_line;
61
62#if defined(USE_NCURSES)
63static mmask_t oldmask;
64int _caca_attr[16*16];
65#endif
66
67#if defined(USE_CONIO)
68static struct text_info ti;
69char *_caca_screen;
70#endif
71
72int caca_init(void)
73{
74#if defined(USE_SLANG)
75    /* See SLang ref., 5.4.4. */
76    static char *slang_colors[16] =
77    {
78        "black",
79        "blue",
80        "green",
81        "cyan",
82        "red",
83        "magenta",
84        "brown",
85        "lightgray",
86        "gray",
87        "brightblue",
88        "brightgreen",
89        "brightcyan",
90        "brightred",
91        "brightmagenta",
92        "yellow",
93        "white",
94    };
95
96    int fg, bg;
97
98    /* Initialize slang library */
99    SLsig_block_signals();
100    SLtt_get_terminfo();
101
102    if(SLkp_init() == -1)
103    {
104        SLsig_unblock_signals();
105        return -1;
106    }
107
108    SLang_init_tty(-1, 0, 1);
109
110    if(SLsmg_init_smg() == -1)
111    {
112        SLsig_unblock_signals();
113        return -1;
114    }
115
116    SLsig_unblock_signals();
117
118    SLsmg_cls();
119    SLtt_set_cursor_visibility(0);
120    SLkp_define_keysym("\e[M", 1001);
121    SLtt_set_mouse_mode(1, 0);
122    SLsmg_refresh();
123
124    for(bg = 0; bg < 16; bg++)
125        for(fg = 0; fg < 16; fg++)
126        {
127            int i = fg + 16 * bg;
128            SLtt_set_color(i, NULL, slang_colors[fg], slang_colors[bg]);
129        }
130
131#elif defined(USE_NCURSES)
132    static int curses_colors[] =
133    {
134        COLOR_BLACK,
135        COLOR_BLUE,
136        COLOR_GREEN,
137        COLOR_CYAN,
138        COLOR_RED,
139        COLOR_MAGENTA,
140        COLOR_YELLOW,
141        COLOR_WHITE,
142        /* Extra values for xterm-16color */
143        COLOR_BLACK + 8,
144        COLOR_BLUE + 8,
145        COLOR_GREEN + 8,
146        COLOR_CYAN + 8,
147        COLOR_RED + 8,
148        COLOR_MAGENTA + 8,
149        COLOR_YELLOW + 8,
150        COLOR_WHITE + 8
151    };
152
153    int fg, bg, max;
154    mmask_t newmask;
155
156    initscr();
157    keypad(stdscr, TRUE);
158    nonl();
159    cbreak();
160    noecho();
161    nodelay(stdscr, TRUE);
162    curs_set(0);
163
164    /* Activate mouse */
165    newmask = ALL_MOUSE_EVENTS;
166    mousemask(newmask, &oldmask);
167
168    /* Activate colour */
169    start_color();
170
171    max = COLORS >= 16 ? 16 : 8;
172
173    for(bg = 0; bg < max; bg++)
174        for(fg = 0; fg < max; fg++)
175        {
176            /* Use ((max + 7 - fg) % max) instead of fg so that colour 0
177             * is light gray on black, since some terminals don't like
178             * this colour pair to be redefined. */
179            int col = ((max + 7 - fg) % max) + max * bg;
180            init_pair(col, curses_colors[fg], curses_colors[bg]);
181            _caca_attr[fg + 16 * bg] = COLOR_PAIR(col);
182
183            if(max == 8)
184            {
185                /* Bright fg on simple bg */
186                _caca_attr[fg + 8 + 16 * bg] = A_BOLD | COLOR_PAIR(col);
187                /* Simple fg on bright bg */
188                _caca_attr[fg + 16 * (bg + 8)] = A_BLINK | COLOR_PAIR(col);
189                /* Bright fg on bright bg */
190                _caca_attr[fg + 8 + 16 * (bg + 8)] = A_BLINK | A_BOLD | COLOR_PAIR(col);
191            }
192        }
193
194#elif defined(USE_CONIO)
195    gettextinfo(&ti);
196    _caca_screen = malloc(2 * ti.screenwidth * ti.screenheight);
197    if(_caca_screen == NULL)
198        return -1;
199    _wscroll = 0;
200    _setcursortype(_NOCURSOR);
201    clrscr();
202#   if defined(SCREENUPDATE_IN_PC_H)
203    ScreenRetrieve(_caca_screen);
204#   else
205    /* FIXME */
206#   endif
207
208#endif
209    _caca_empty_line = malloc(caca_get_width() + 1);
210    memset(_caca_empty_line, ' ', caca_get_width());
211    _caca_empty_line[caca_get_width()] = '\0';
212
213    _caca_scratch_line = malloc(caca_get_width() + 1);
214
215    _caca_delay = 0;
216    _caca_rendertime = 0;
217
218    return 0;
219}
220
221unsigned int caca_get_width(void)
222{
223#if defined(USE_SLANG)
224    return SLtt_Screen_Cols;
225#elif defined(USE_NCURSES)
226    return COLS;
227#elif defined(USE_CONIO)
228    return ti.screenwidth;
229#endif
230}
231
232unsigned int caca_get_height(void)
233{
234#if defined(USE_SLANG)
235    return SLtt_Screen_Rows;
236#elif defined(USE_NCURSES)
237    return LINES;
238#else
239    return ti.screenheight;
240#endif
241}
242
243void caca_set_delay(unsigned int usec)
244{
245    _caca_delay = usec;
246}
247
248unsigned int caca_get_rendertime(void)
249{
250    return _caca_rendertime;
251}
252
253const char *caca_get_color_name(unsigned int color)
254{
255    static const char *color_names[16] =
256    {
257        "black",
258        "blue",
259        "green",
260        "cyan",
261        "red",
262        "magenta",
263        "brown",
264        "light gray",
265        "dark gray",
266        "light blue",
267        "light green",
268        "light cyan",
269        "light red",
270        "light magenta",
271        "yellow",
272        "white",
273    };
274
275    if(color < 0 || color > 15)
276        return "unknown color";
277
278    return color_names[color];
279}
280
281static unsigned int _caca_getticks(void)
282{
283    static unsigned int last_sec = 0, last_usec = 0;
284
285    struct timeval tv;
286    unsigned int ticks = 0;
287
288    gettimeofday(&tv, NULL);
289
290    if(last_sec != 0)
291    {
292        ticks = (tv.tv_sec - last_sec) * 1000000 + (tv.tv_usec - last_usec);
293    }
294
295    last_sec = tv.tv_sec;
296    last_usec = tv.tv_usec;
297
298    return ticks;
299}
300
301void caca_refresh(void)
302{
303#define IDLE_USEC 10000
304    static int lastticks = 0;
305    int ticks = lastticks + _caca_getticks();
306
307#if defined(USE_SLANG)
308    SLsmg_refresh();
309#elif defined(USE_NCURSES)
310    refresh();
311#elif defined(USE_CONIO)
312#   if defined(SCREENUPDATE_IN_PC_H)
313    ScreenUpdate(_caca_screen);
314#   else
315    /* FIXME */
316#   endif
317#endif
318
319    /* Wait until _caca_delay + time of last call */
320    ticks += _caca_getticks();
321    for(; ticks + IDLE_USEC < (int)_caca_delay; ticks += _caca_getticks())
322        usleep(IDLE_USEC);
323
324    /* Update the sliding mean of the render time */
325    _caca_rendertime = (7 * _caca_rendertime + ticks) / 8;
326
327    lastticks = ticks - _caca_delay;
328
329    /* If we drifted too much, it's bad, bad, bad. */
330    if(lastticks > (int)_caca_delay)
331        lastticks = 0;
332}
333
334void caca_end(void)
335{
336#if defined(USE_SLANG)
337    SLtt_set_mouse_mode(0, 0);
338    SLtt_set_cursor_visibility(1);
339    SLang_reset_tty();
340    SLsmg_reset_smg();
341#elif defined(USE_NCURSES)
342    mousemask(oldmask, NULL);
343    curs_set(1);
344    endwin();
345#elif defined(USE_CONIO)
346    _wscroll = 1;
347    textcolor((enum COLORS)WHITE);
348    textbackground((enum COLORS)BLACK);
349    gotoxy(caca_get_width(), caca_get_height());
350    cputs("\r\n");
351    _setcursortype(_NORMALCURSOR);
352#endif
353}
354
Note: See TracBrowser for help on using the repository browser.