source: libcaca/trunk/src/graphics.c @ 274

Last change on this file since 274 was 274, checked in by Sam Hocevar, 19 years ago
  • src/graphics.c: + Replace CACA_WIDTH and CACA_HEIGHT with CACA_GEOMETRY.
  • src/caca.c: + Documented the CACA_GEOMETRY environment variable.
  • Property svn:keywords set to Id
File size: 21.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 graphics.c
23 *  \version \$Id: graphics.c 274 2003-12-24 15:43:45Z sam $
24 *  \author Sam Hocevar <sam@zoy.org>
25 *  \brief Character drawing functions
26 *
27 *  This file contains character and string drawing functions.
28 */
29
30#include "config.h"
31
32#if defined(USE_SLANG)
33#   include <slang.h>
34#endif
35#if defined(USE_NCURSES)
36#   include <curses.h>
37#endif
38#if defined(USE_CONIO)
39#   include <conio.h>
40#   if defined(SCREENUPDATE_IN_PC_H)
41#       include <pc.h>
42#   endif
43#endif
44#if defined(USE_X11)
45#   include <X11/Xlib.h>
46#endif
47
48#if defined(HAVE_INTTYPES_H)
49#   include <inttypes.h>
50#endif
51
52#include <stdio.h> /* BUFSIZ */
53#include <string.h>
54#include <stdlib.h>
55#include <unistd.h>
56#include <stdarg.h>
57#include <sys/time.h>
58#include <time.h>
59
60#include "caca.h"
61#include "caca_internals.h"
62
63/*
64 * Global variables
65 */
66unsigned int _caca_width = 0;
67unsigned int _caca_height = 0;
68
69/*
70 * Local variables
71 */
72#if defined(USE_NCURSES)
73static int ncurses_attr[16*16];
74#endif
75
76#if defined(USE_CONIO)
77static struct text_info conio_ti;
78static char *conio_screen;
79#endif
80
81#if defined(USE_X11)
82Display *x11_dpy;
83Window x11_window;
84int x11_font_width, x11_font_height;
85static GC x11_gc;
86static Pixmap x11_pixmap;
87static int *x11_screen;
88static int x11_colors[16];
89static Font x11_font;
90static XFontStruct *x11_font_struct;
91static int x11_font_offset;
92#endif
93
94static char *_caca_empty_line;
95static char *_caca_scratch_line;
96
97static unsigned int _caca_delay;
98static unsigned int _caca_rendertime;
99
100static enum caca_color _caca_fgcolor = CACA_COLOR_LIGHTGRAY;
101static enum caca_color _caca_bgcolor = CACA_COLOR_BLACK;
102
103/** \brief Set the default colour pair.
104 *
105 *  This function sets the default colour pair. String functions such as
106 *  caca_printf() and graphical primitive functions such as caca_draw_line()
107 *  will use these colour pairs.
108 *
109 *  \param fgcolor The requested foreground colour.
110 *  \param bgcolor The requested background colour.
111 */
112void caca_set_color(enum caca_color fgcolor, enum caca_color bgcolor)
113{
114    if(fgcolor < 0 || fgcolor > 15 || bgcolor < 0 || bgcolor > 15)
115        return;
116
117    _caca_fgcolor = fgcolor;
118    _caca_bgcolor = bgcolor;
119    switch(_caca_driver)
120    {
121#if defined(USE_SLANG)
122    case CACA_DRIVER_SLANG:
123        SLsmg_set_color((bgcolor + 16 * fgcolor) /*% 128*/);
124        break;
125#endif
126#if defined(USE_NCURSES)
127    case CACA_DRIVER_NCURSES:
128        attrset(ncurses_attr[fgcolor + 16 * bgcolor]);
129        break;
130#endif
131#if defined(USE_CONIO)
132    case CACA_DRIVER_CONIO:
133        textbackground(bgcolor);
134        textcolor(fgcolor);
135        break;
136#endif
137#if defined(USE_X11)
138    case CACA_DRIVER_X11:
139        /* FIXME */
140        break;
141#endif
142    default:
143        break;
144    }
145}
146
147/** \brief Get the current foreground colour.
148 *
149 *  This function returns the current foreground colour that was set with
150 *  caca_set_color().
151 *
152 *  \return The current foreground colour.
153 */
154enum caca_color caca_get_fg_color(void)
155{
156    return _caca_fgcolor;
157}
158
159/** \brief Get the current background colour.
160 *
161 *  This function returns the current background colour that was set with
162 *  caca_set_color().
163 *
164 *  \return The current background colour.
165 */
166enum caca_color caca_get_bg_color(void)
167{
168    return _caca_bgcolor;
169}
170
171/** \brief Print a character.
172 *
173 *  This function prints a character at the given coordinates, using the
174 *  default foreground and background values. If the coordinates are outside
175 *  the screen boundaries, nothing is printed.
176 *
177 *  \param x X coordinate.
178 *  \param y Y coordinate.
179 *  \param c The character to print.
180 */
181void caca_putchar(int x, int y, char c)
182{
183#if defined(USE_CONIO)
184    char *data;
185#endif
186    if(x < 0 || x >= (int)_caca_width ||
187       y < 0 || y >= (int)_caca_height)
188        return;
189
190    switch(_caca_driver)
191    {
192#if defined(USE_SLANG)
193    case CACA_DRIVER_SLANG:
194        SLsmg_gotorc(y, x);
195        SLsmg_write_char(c);
196        break;
197#endif
198#if defined(USE_NCURSES)
199    case CACA_DRIVER_NCURSES:
200        move(y, x);
201        addch(c);
202        break;
203#endif
204#if defined(USE_CONIO)
205    case CACA_DRIVER_CONIO:
206        data = conio_screen + 2 * (x + y * _caca_width);
207        data[0] = c;
208        data[1] = (_caca_bgcolor << 4) | _caca_fgcolor;
209//        gotoxy(x + 1, y + 1);
210//        putch(c);
211        break;
212#endif
213#if defined(USE_X11)
214    case CACA_DRIVER_X11:
215        x11_screen[x + y * _caca_width] =
216            ((int)c << 8) | ((int)_caca_bgcolor << 4) | (int)_caca_fgcolor;
217        break;
218#endif
219    default:
220        break;
221    }
222}
223
224/** \brief Print a string.
225 *
226 *  This function prints a string at the given coordinates, using the
227 *  default foreground and background values. The coordinates may be outside
228 *  the screen boundaries (eg. a negative Y coordinate) and the string will
229 *  be cropped accordingly if it is too long.
230 *
231 *  \param x X coordinate.
232 *  \param y Y coordinate.
233 *  \param s The string to print.
234 */
235void caca_putstr(int x, int y, const char *s)
236{
237#if defined(USE_CONIO)
238    char *charbuf;
239#endif
240#if defined(USE_X11)
241    int *intbuf;
242#endif
243    unsigned int len;
244
245    if(y < 0 || y >= (int)_caca_height || x >= (int)_caca_width)
246        return;
247
248    len = strlen(s);
249
250    if(x < 0)
251    {
252        len -= -x;
253        if(len < 0)
254            return;
255        s += -x;
256        x = 0;
257    }
258
259    if(x + len >= _caca_width)
260    {
261        memcpy(_caca_scratch_line, s, _caca_width - x);
262        _caca_scratch_line[_caca_width - x] = '\0';
263        s = _caca_scratch_line;
264    }
265
266    switch(_caca_driver)
267    {
268#if defined(USE_SLANG)
269    case CACA_DRIVER_SLANG:
270        SLsmg_gotorc(y, x);
271        SLsmg_write_string((char *)(intptr_t)s);
272        break;
273#endif
274#if defined(USE_NCURSES)
275    case CACA_DRIVER_NCURSES:
276        move(y, x);
277        addstr(s);
278        break;
279#endif
280#if defined(USE_CONIO)
281    case CACA_DRIVER_CONIO:
282        charbuf = conio_screen + 2 * (x + y * _caca_width);
283        while(*s)
284        {
285            *charbuf++ = *s++;
286            *charbuf++ = (_caca_bgcolor << 4) | _caca_fgcolor;
287        }
288//        gotoxy(x + 1, y + 1);
289//        cputs(s);
290        break;
291#endif
292#if defined(USE_X11)
293    case CACA_DRIVER_X11:
294        intbuf = x11_screen + x + y * _caca_width;
295        while(*s)
296            *intbuf++ = ((int)*s++ << 8)
297                         | ((int)_caca_bgcolor << 4) | (int)_caca_fgcolor;
298        break;
299#endif
300    default:
301        break;
302    }
303}
304
305/** \brief Format a string.
306 *
307 *  This function formats a string at the given coordinates, using the
308 *  default foreground and background values. The coordinates may be outside
309 *  the screen boundaries (eg. a negative Y coordinate) and the string will
310 *  be cropped accordingly if it is too long. The syntax of the format
311 *  string is the same as for the C printf() function.
312 *
313 *  \param x X coordinate.
314 *  \param y Y coordinate.
315 *  \param format The format string to print.
316 *  \param ... Arguments to the format string.
317 */
318void caca_printf(int x, int y, const char *format, ...)
319{
320    char tmp[BUFSIZ];
321    char *buf = tmp;
322    va_list args;
323
324    if(y < 0 || y >= (int)_caca_height || x >= (int)_caca_width)
325        return;
326
327    if(_caca_width - x + 1 > BUFSIZ)
328        buf = malloc(_caca_width - x + 1);
329
330    va_start(args, format);
331#if defined(HAVE_VSNPRINTF)
332    vsnprintf(buf, _caca_width - x + 1, format, args);
333#else
334    vsprintf(buf, format, args);
335#endif
336    buf[_caca_width - x] = '\0';
337    va_end(args);
338
339    caca_putstr(x, y, buf);
340
341    if(buf != tmp)
342        free(buf);
343}
344
345/** \brief Clear the screen.
346 *
347 *  This function clears the screen using a black background.
348 */
349void caca_clear(void)
350{
351    enum caca_color oldfg = caca_get_fg_color();
352    enum caca_color oldbg = caca_get_bg_color();
353    int y = _caca_height;
354
355    caca_set_color(CACA_COLOR_LIGHTGRAY, CACA_COLOR_BLACK);
356
357    /* We could use SLsmg_cls() etc., but drawing empty lines is much faster */
358    while(y--)
359        caca_putstr(0, y, _caca_empty_line);
360
361    caca_set_color(oldfg, oldbg);
362}
363
364int _caca_init_graphics(void)
365{
366#if defined(USE_SLANG)
367    if(_caca_driver == CACA_DRIVER_SLANG)
368    {
369        /* See SLang ref., 5.4.4. */
370        static char *slang_colors[16] =
371        {
372            /* Standard colours */
373            "black",
374            "blue",
375            "green",
376            "cyan",
377            "red",
378            "magenta",
379            "brown",
380            "lightgray",
381            /* Bright colours */
382            "gray",
383            "brightblue",
384            "brightgreen",
385            "brightcyan",
386            "brightred",
387            "brightmagenta",
388            "yellow",
389            "white",
390        };
391
392        int fg, bg;
393
394        for(fg = 0; fg < 16; fg++)
395            for(bg = 0; bg < 16; bg++)
396            {
397                int i = bg + 16 * fg;
398                SLtt_set_color(i, NULL, slang_colors[fg], slang_colors[bg]);
399            }
400
401        /* Disable alt charset support so that we get all 256 colour pairs */
402        SLtt_Has_Alt_Charset = 0;
403
404        _caca_width = SLtt_Screen_Cols;
405        _caca_height = SLtt_Screen_Rows;
406    }
407    else
408#endif
409#if defined(USE_NCURSES)
410    if(_caca_driver == CACA_DRIVER_NCURSES)
411    {
412        static int curses_colors[] =
413        {
414            /* Standard curses colours */
415            COLOR_BLACK,
416            COLOR_BLUE,
417            COLOR_GREEN,
418            COLOR_CYAN,
419            COLOR_RED,
420            COLOR_MAGENTA,
421            COLOR_YELLOW,
422            COLOR_WHITE,
423            /* Extra values for xterm-16color */
424            COLOR_BLACK + 8,
425            COLOR_BLUE + 8,
426            COLOR_GREEN + 8,
427            COLOR_CYAN + 8,
428            COLOR_RED + 8,
429            COLOR_MAGENTA + 8,
430            COLOR_YELLOW + 8,
431            COLOR_WHITE + 8
432        };
433
434        int fg, bg, max;
435
436        /* Activate colour */
437        start_color();
438
439        /* If COLORS == 16, it means the terminal supports full bright colours
440         * using setab and setaf (will use \e[90m \e[91m etc. for colours >= 8),
441         * we can build 16*16 colour pairs.
442         * If COLORS == 8, it means the terminal does not know about bright
443         * colours and we need to get them through A_BOLD and A_BLINK (\e[1m
444         * and \e[5m). We can only build 8*8 colour pairs. */
445        max = COLORS >= 16 ? 16 : 8;
446
447        for(bg = 0; bg < max; bg++)
448            for(fg = 0; fg < max; fg++)
449            {
450                /* Use ((max + 7 - fg) % max) instead of fg so that colour 0
451                 * is light gray on black, since some terminals don't like
452                 * this colour pair to be redefined. */
453                int col = ((max + 7 - fg) % max) + max * bg;
454                init_pair(col, curses_colors[fg], curses_colors[bg]);
455                ncurses_attr[fg + 16 * bg] = COLOR_PAIR(col);
456
457                if(max == 8)
458                {
459                    /* Bright fg on simple bg */
460                    ncurses_attr[fg + 8 + 16 * bg] = A_BOLD | COLOR_PAIR(col);
461                    /* Simple fg on bright bg */
462                    ncurses_attr[fg + 16 * (bg + 8)] = A_BLINK
463                                                        | COLOR_PAIR(col);
464                    /* Bright fg on bright bg */
465                    ncurses_attr[fg + 8 + 16 * (bg + 8)] = A_BLINK | A_BOLD
466                                                            | COLOR_PAIR(col);
467                }
468            }
469
470        _caca_width = COLS;
471        _caca_height = LINES;
472    }
473    else
474#endif
475#if defined(USE_CONIO)
476    if(_caca_driver == CACA_DRIVER_CONIO)
477    {
478        gettextinfo(&conio_ti);
479        conio_screen = malloc(2 * conio_ti.screenwidth
480                                 * conio_ti.screenheight * sizeof(char));
481        if(conio_screen == NULL)
482            return -1;
483#   if defined(SCREENUPDATE_IN_PC_H)
484        ScreenRetrieve(conio_screen);
485#   else
486        /* FIXME */
487#   endif
488        _caca_width = conio_ti.screenwidth;
489        _caca_height = conio_ti.screenheight;
490    }
491    else
492#endif
493#if defined(USE_X11)
494    if(_caca_driver == CACA_DRIVER_X11)
495    {
496        static int x11_palette[] =
497        {
498            /* Standard curses colours */
499            0, 0, 0,
500            0, 0, 32768,
501            0, 32768, 0,
502            0, 32768, 32768,
503            32768, 0, 0,
504            32768, 0, 32768,
505            32768, 32768, 0,
506            32768, 32768, 32768,
507            /* Extra values for xterm-16color */
508            16384, 16384, 16384,
509            16384, 16384, 65535,
510            16384, 65535, 16384,
511            16384, 65535, 65535,
512            65535, 16384, 16384,
513            65535, 16384, 65535,
514            65535, 65535, 16384,
515            65535, 65535, 65535,
516        };
517
518        Colormap colormap;
519        XSetWindowAttributes x11_attr;
520        const char *font_name = "8x13bold";
521        int i;
522
523        if(getenv("CACA_GEOMETRY"))
524            sscanf(getenv("CACA_GEOMETRY"),
525                   "%ux%u", &_caca_width, &_caca_height);
526
527        if(!_caca_width)
528            _caca_width = 80;
529        if(!_caca_height)
530            _caca_height = 32;
531
532        x11_screen = malloc(_caca_width * _caca_height * sizeof(int));
533        if(x11_screen == NULL)
534            return -1;
535
536        x11_dpy = XOpenDisplay(NULL);
537        if(x11_dpy == NULL)
538        {
539            free(x11_screen);
540            return -1;
541        }
542
543        if(getenv("CACA_FONT"))
544            font_name = getenv("CACA_FONT");
545
546        x11_font = XLoadFont(x11_dpy, font_name);
547        if(!x11_font)
548        {
549            XCloseDisplay(x11_dpy);
550            free(x11_screen);
551            return -1;
552        }
553
554        x11_font_struct = XQueryFont(x11_dpy, x11_font);
555        if(!x11_font_struct)
556        {
557            XUnloadFont(x11_dpy, x11_font);
558            XCloseDisplay(x11_dpy);
559            free(x11_screen);
560            return -1;
561        }
562
563        x11_font_width = x11_font_struct->max_bounds.width;
564        x11_font_height = x11_font_struct->max_bounds.ascent
565                             + x11_font_struct->max_bounds.descent;
566        x11_font_offset = x11_font_struct->max_bounds.descent;
567
568        colormap = DefaultColormap(x11_dpy, DefaultScreen(x11_dpy));
569        for(i = 0; i < 16; i++)
570        {
571            XColor color;
572            color.red = x11_palette[i * 3];
573            color.green = x11_palette[i * 3 + 1];
574            color.blue = x11_palette[i * 3 + 2];
575            XAllocColor(x11_dpy, colormap, &color);
576            x11_colors[i] = color.pixel;
577        }
578
579        x11_attr.backing_store = Always;
580        x11_attr.background_pixel = x11_colors[0];
581        x11_attr.event_mask = ExposureMask | StructureNotifyMask;
582
583        x11_window = XCreateWindow(x11_dpy, DefaultRootWindow(x11_dpy), 0, 0,
584                                   _caca_width * x11_font_width,
585                                   _caca_height * x11_font_height,
586                                   0, 0, InputOutput, 0,
587                                   CWBackingStore | CWBackPixel | CWEventMask,
588                                   &x11_attr);
589
590        XStoreName(x11_dpy, x11_window, "caca for X");
591
592        XSelectInput(x11_dpy, x11_window, StructureNotifyMask);
593        XMapWindow(x11_dpy, x11_window);
594
595        x11_gc = XCreateGC(x11_dpy, x11_window, 0, NULL);
596        XSetForeground(x11_dpy, x11_gc, x11_colors[15]);
597        XSetFont(x11_dpy, x11_gc, x11_font);
598
599        for(;;)
600        {
601            XEvent event;
602            XNextEvent(x11_dpy, &event);
603            if (event.type == MapNotify)
604                break;
605        }
606
607        XSelectInput(x11_dpy, x11_window,
608                     KeyPressMask | ButtonPressMask | PointerMotionMask);
609
610        XSync(x11_dpy, False);
611
612        x11_pixmap = XCreatePixmap(x11_dpy, x11_window,
613                                   _caca_width * x11_font_width,
614                                   _caca_height * x11_font_height,
615                                   DefaultDepth(x11_dpy,
616                                                DefaultScreen(x11_dpy)));
617    }
618#endif
619
620    _caca_empty_line = malloc(_caca_width + 1);
621    memset(_caca_empty_line, ' ', _caca_width);
622    _caca_empty_line[_caca_width] = '\0';
623
624    _caca_scratch_line = malloc(_caca_width + 1);
625
626    _caca_delay = 0;
627    _caca_rendertime = 0;
628
629    return 0;
630}
631
632int _caca_end_graphics(void)
633{
634#if defined(USE_SLANG)
635    /* Nothing to do */
636#endif
637#if defined(USE_NCURSES)
638    /* Nothing to do */
639#endif
640#if defined(USE_CONIO)
641    if(_caca_driver == CACA_DRIVER_CONIO)
642    {
643        free(conio_screen);
644    }
645    else
646#endif
647#if defined(USE_X11)
648    if(_caca_driver == CACA_DRIVER_X11)
649    {
650        XSync(x11_dpy, False);
651        XFreePixmap(x11_dpy, x11_pixmap);
652        XFreeFont(x11_dpy, x11_font_struct);
653        XFreeGC(x11_dpy, x11_gc);
654        XUnmapWindow(x11_dpy, x11_window);
655        XDestroyWindow(x11_dpy, x11_window);
656        XCloseDisplay(x11_dpy);
657        free(x11_screen);
658    }
659#endif
660    free(_caca_empty_line);
661
662    return 0;
663}
664
665/** \brief Set the refresh delay.
666 *
667 *  This function sets the refresh delay in microseconds. The refresh delay
668 *  is used by caca_refresh() to achieve constant framerate. See the
669 *  caca_refresh() documentation for more details.
670 *
671 *  If the argument is zero, constant framerate is disabled. This is the
672 *  default behaviour.
673 *
674 *  \param usec The refresh delay in microseconds.
675 */
676void caca_set_delay(unsigned int usec)
677{
678    _caca_delay = usec;
679}
680
681/** \brief Get the average rendering time.
682 *
683 *  This function returns the average rendering time, which is the average
684 *  measured time between two caca_refresh() calls, in microseconds. If
685 *  constant framerate was activated by calling caca_set_delay(), the average
686 *  rendering time will not be considerably shorter than the requested delay
687 *  even if the real rendering time was shorter.
688 *
689 *  \return The render time in microseconds.
690 */
691unsigned int caca_get_rendertime(void)
692{
693    return _caca_rendertime;
694}
695
696static unsigned int _caca_getticks(void)
697{
698    static unsigned int last_sec = 0, last_usec = 0;
699
700    struct timeval tv;
701    unsigned int ticks = 0;
702
703    gettimeofday(&tv, NULL);
704
705    if(last_sec != 0)
706    {
707        ticks = (tv.tv_sec - last_sec) * 1000000 + (tv.tv_usec - last_usec);
708    }
709
710    last_sec = tv.tv_sec;
711    last_usec = tv.tv_usec;
712
713    return ticks;
714}
715
716/** \brief Flush pending changes and redraw the screen.
717 *
718 *  This function flushes all graphical operations and prints them to the
719 *  screen. Nothing will show on the screen caca_refresh() is not called.
720 *
721 *  If caca_set_delay() was called with a non-zero value, caca_refresh()
722 *  will use that value to achieve constant framerate: if two consecutive
723 *  calls to caca_refresh() are within a time range shorter than the value
724 *  set with caca_set_delay(), the second call will wait a bit before
725 *  performing the screen refresh.
726 */
727void caca_refresh(void)
728{
729#define IDLE_USEC 10000
730    static int lastticks = 0;
731    int ticks = lastticks + _caca_getticks();
732
733#if defined(USE_SLANG)
734    if(_caca_driver == CACA_DRIVER_SLANG)
735    {
736        SLsmg_refresh();
737    }
738    else
739#endif
740#if defined(USE_NCURSES)
741    if(_caca_driver == CACA_DRIVER_NCURSES)
742    {
743        refresh();
744    }
745    else
746#endif
747#if defined(USE_CONIO)
748    if(_caca_driver == CACA_DRIVER_CONIO)
749    {
750#   if defined(SCREENUPDATE_IN_PC_H)
751        ScreenUpdate(conio_screen);
752#   else
753        /* FIXME */
754#   endif
755    }
756    else
757#endif
758#if defined(USE_X11)
759    if(_caca_driver == CACA_DRIVER_X11)
760    {
761        unsigned int x, y;
762
763        /* FIXME: This is very, very slow. There are several things that can
764         * be done in order to speed up things:
765         *  - cache characters once rendered
766         *  - pre-render all characters
767         *  - use our own rendering routine (screen depth dependent) */
768        for(y = 0; y < _caca_height; y++)
769            for(x = 0; x < _caca_width; x++)
770            {
771                int item = x11_screen[x + y * _caca_width];
772                char data = item >> 8;
773                XSetForeground(x11_dpy, x11_gc, x11_colors[(item >> 4) & 0xf]);
774                XFillRectangle(x11_dpy, x11_pixmap, x11_gc,
775                               x * x11_font_width, y * x11_font_height,
776                               x11_font_width, x11_font_height);
777                XSetForeground(x11_dpy, x11_gc, x11_colors[item & 0xf]);
778                XDrawString(x11_dpy, x11_pixmap, x11_gc, x * x11_font_width,
779                            (y + 1) * x11_font_height - x11_font_offset,
780                            &data, 1);
781            }
782        XCopyArea(x11_dpy, x11_pixmap, x11_window, x11_gc, 0, 0,
783                  _caca_width * x11_font_width, _caca_height * x11_font_height,
784                  0, 0);
785        XFlush(x11_dpy);
786    }
787#endif
788
789    /* Wait until _caca_delay + time of last call */
790    ticks += _caca_getticks();
791    for(; ticks + IDLE_USEC < (int)_caca_delay; ticks += _caca_getticks())
792        usleep(IDLE_USEC);
793
794    /* Update the sliding mean of the render time */
795    _caca_rendertime = (7 * _caca_rendertime + ticks) / 8;
796
797    lastticks = ticks - _caca_delay;
798
799    /* If we drifted too much, it's bad, bad, bad. */
800    if(lastticks > (int)_caca_delay)
801        lastticks = 0;
802}
803
Note: See TracBrowser for help on using the repository browser.