Browse Source

* test/event.c:

+ Do not refresh after each event, but only when there is no event
      pending.
    + If the pressed key is a printable character, display it.
  * src/time.c:
    + Moved _caca_getticks() to this file.
  * src/caca.c:
    + Set the escape delay to a very low value in the ncurses driver,
      because I don't want escape sequences to be entered manually.
  * src/io.c:
    + Autorepeat emulation in the ncurses and slang drivers: do not
      immediately send the key release event.
  * configure.ac:
    + Check for usleep.
    + Improvements in the win32 platform detection.
tags/v0.99.beta14
Sam Hocevar sam 21 years ago
parent
commit
dd4083f9d1
11 changed files with 232 additions and 63 deletions
  1. +2
    -3
      BUGS
  2. +2
    -0
      NOTES
  3. +3
    -1
      README
  4. +23
    -4
      configure.ac
  5. +1
    -0
      src/Makefile.am
  6. +3
    -0
      src/caca.c
  7. +10
    -0
      src/caca_internals.h
  8. +16
    -37
      src/graphics.c
  9. +84
    -5
      src/io.c
  10. +65
    -0
      src/time.c
  11. +23
    -13
      test/event.c

+ 2
- 3
BUGS View File

@@ -4,9 +4,8 @@ Video rendering


o ncurses' hashmap scrolling optimisation code causes the screen to o ncurses' hashmap scrolling optimisation code causes the screen to
occasionally flicker because it tries to optimise the vertical occasionally flicker because it tries to optimise the vertical
scrolling.

o the X11 driver is very slow.
scrolling. With S-Lang, SLtt_Term_Cannot_Scroll prevents this
unwanted behaviour.


o some terminal emulators (Konsole, or the Linux VGA console) honour o some terminal emulators (Konsole, or the Linux VGA console) honour
the blink attribute instead of using it for bold or bright like any the blink attribute instead of using it for bold or bright like any


+ 2
- 0
NOTES View File

@@ -193,3 +193,5 @@ $Id$
o MS-DOS: all bright colours, bright backgrounds, and bright combinations o MS-DOS: all bright colours, bright backgrounds, and bright combinations
work using <conio.h>. No need to kludge anything. work using <conio.h>. No need to kludge anything.


o Win32: we use GetConsoleScreenBufferInfo etc.


+ 3
- 1
README View File

@@ -11,10 +11,12 @@ Building libcaca


--disable-imlib2: remove Imlib2 support in cacaview --disable-imlib2: remove Imlib2 support in cacaview


o Cross-compilation example:
o Cross-compilation examples:
./configure --disable-imlib2 --host=i386-pc-msdosdjgpp ./configure --disable-imlib2 --host=i386-pc-msdosdjgpp


./configure --disable-imlib2 --host=i586-mingw32msvc



Using libcaca Using libcaca




+ 23
- 4
configure.ac View File

@@ -15,19 +15,21 @@ AC_PROG_RANLIB


dnl AC_PROG_EGREP only exists in autoconf 2.54+, so we use AC_EGREP_CPP right dnl AC_PROG_EGREP only exists in autoconf 2.54+, so we use AC_EGREP_CPP right
dnl now otherwise it might be set in an obscure if statement. dnl now otherwise it might be set in an obscure if statement.
AC_EGREP_CPP(foo,foo)
AC_EGREP_CPP(foo, foo)


AC_ARG_ENABLE(slang, AC_ARG_ENABLE(slang,
[ --enable-slang slang graphics support (autodetected)]) [ --enable-slang slang graphics support (autodetected)])
AC_ARG_ENABLE(ncurses, AC_ARG_ENABLE(ncurses,
[ --enable-ncurses ncurses graphics support (autodetected)]) [ --enable-ncurses ncurses graphics support (autodetected)])
AC_ARG_ENABLE(win32,
[ --enable-win32 Windows console support (autodetected)])
AC_ARG_ENABLE(conio, AC_ARG_ENABLE(conio,
[ --enable-conio DOS conio.h graphics support (default disabled)])
[ --enable-conio DOS conio.h graphics support (autodetected)])
AC_ARG_ENABLE(x11, AC_ARG_ENABLE(x11,
[ --enable-x11 X11 support (autodetected)]) [ --enable-x11 X11 support (autodetected)])


AC_CHECK_HEADERS(inttypes.h endian.h) AC_CHECK_HEADERS(inttypes.h endian.h)
AC_CHECK_FUNCS(vsnprintf getenv putenv strcasecmp)
AC_CHECK_FUNCS(vsnprintf getenv putenv strcasecmp usleep Sleep)


CACA_DRIVERS="" CACA_DRIVERS=""


@@ -35,7 +37,7 @@ if test "${enable_conio}" != "no"; then
ac_cv_my_have_conio="no" ac_cv_my_have_conio="no"
AC_CHECK_HEADERS(conio.h, AC_CHECK_HEADERS(conio.h,
[AC_MSG_CHECKING(for ScreenUpdate in pc.h) [AC_MSG_CHECKING(for ScreenUpdate in pc.h)
AC_EGREP_HEADER(ScreenUpdate,pc.h,
AC_EGREP_HEADER(ScreenUpdate, pc.h,
[ac_cv_my_have_conio="yes" [ac_cv_my_have_conio="yes"
AC_MSG_RESULT(yes) AC_MSG_RESULT(yes)
AC_DEFINE(SCREENUPDATE_IN_PC_H, 1, AC_DEFINE(SCREENUPDATE_IN_PC_H, 1,
@@ -48,6 +50,23 @@ if test "${enable_conio}" != "no"; then
fi fi
fi fi


if test "${enable_win32}" != "no"; then
ac_cv_my_have_win32="no"
AC_CHECK_HEADERS(windows.h,
[AC_MSG_CHECKING(for AllocConsole in windows.h)
AC_EGREP_HEADER(AllocConsole, windows.h,
[ac_cv_my_have_win32="yes"
AC_MSG_RESULT(yes)
AC_DEFINE(ALLOCCONSOLE_IN_WINDOWS_H, 1,
Define if <windows.h> defines AllocConsole.)
AC_DEFINE(USE_WIN32, 1, Define to activate the win32 backend driver)
CACA_DRIVERS="${CACA_DRIVERS} win32"],
[AC_MSG_RESULT(no)])])
if test "${ac_cv_my_have_win32}" = "no" -a "${enable_win32}" = "yes"; then
AC_MSG_ERROR([cannot find win32 console development files])
fi
fi

if test "${enable_slang}" != "no"; then if test "${enable_slang}" != "no"; then
ac_cv_my_have_slang="no" ac_cv_my_have_slang="no"
AC_CHECK_HEADERS(slang.h slang/slang.h, AC_CHECK_HEADERS(slang.h slang/slang.h,


+ 1
- 0
src/Makefile.am View File

@@ -18,6 +18,7 @@ libcaca_a_SOURCES = \
triangle.c \ triangle.c \
sprite.c \ sprite.c \
bitmap.c \ bitmap.c \
time.c \
$(NULL) $(NULL)


if NEED_PIC if NEED_PIC


+ 3
- 0
src/caca.c View File

@@ -140,6 +140,9 @@ int caca_init(void)
newmask = REPORT_MOUSE_POSITION | ALL_MOUSE_EVENTS; newmask = REPORT_MOUSE_POSITION | ALL_MOUSE_EVENTS;
mousemask(newmask, &oldmask); mousemask(newmask, &oldmask);
mouseinterval(-1); /* No click emulation */ mouseinterval(-1); /* No click emulation */

/* Set the escape delay to a ridiculously low value */
ESCDELAY = 10;
} }
else else
#endif #endif


+ 10
- 0
src/caca_internals.h View File

@@ -48,6 +48,13 @@ enum caca_driver
CACA_DRIVER_NONE = 0 CACA_DRIVER_NONE = 0
}; };


/* Timer structure */
#define CACA_TIMER_INITIALIZER { 0, 0 }
struct caca_timer
{
int last_sec, last_usec;
};

extern enum caca_driver _caca_driver; extern enum caca_driver _caca_driver;


/* Initialisation functions */ /* Initialisation functions */
@@ -56,6 +63,9 @@ extern int _caca_end_graphics(void);
extern int _caca_init_bitmap(void); extern int _caca_init_bitmap(void);
extern int _caca_end_bitmap(void); extern int _caca_end_bitmap(void);


/* Timer functions */
extern unsigned int _caca_getticks(struct caca_timer *);

/* Cached screen size */ /* Cached screen size */
extern unsigned int _caca_width; extern unsigned int _caca_width;
extern unsigned int _caca_height; extern unsigned int _caca_height;


+ 16
- 37
src/graphics.c View File

@@ -63,8 +63,6 @@ typedef unsigned char uint8_t;
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include <stdarg.h> #include <stdarg.h>
#include <sys/time.h>
#include <time.h>


#include "caca.h" #include "caca.h"
#include "caca_internals.h" #include "caca_internals.h"
@@ -187,8 +185,6 @@ static void slang_init_palette(void);
static int x11_error_handler(Display *, XErrorEvent *); static int x11_error_handler(Display *, XErrorEvent *);
#endif #endif


static unsigned int _caca_getticks(void);

/** \brief Set the default colour pair. /** \brief Set the default colour pair.
* *
* This function sets the default colour pair. String functions such as * This function sets the default colour pair. String functions such as
@@ -828,39 +824,11 @@ unsigned int caca_get_rendertime(void)
return _caca_rendertime; return _caca_rendertime;
} }


static unsigned int _caca_getticks(void)
{
static int last_sec = 0, last_usec = 0;

struct timeval tv;
unsigned int ticks = 0;

gettimeofday(&tv, NULL);

if(last_sec != 0)
{
/* If the delay was greater than 60 seconds, return 10 seconds
* otherwise we may overflow our ticks counter. */
if(tv.tv_sec >= last_sec + 60)
ticks = 60 * 1000000;
else
{
ticks = (tv.tv_sec - last_sec) * 1000000;
ticks += tv.tv_usec;
ticks -= last_usec;
}
}

last_sec = tv.tv_sec;
last_usec = tv.tv_usec;

return ticks;
}

/** \brief Flush pending changes and redraw the screen. /** \brief Flush pending changes and redraw the screen.
* *
* This function flushes all graphical operations and prints them to the * This function flushes all graphical operations and prints them to the
* screen. Nothing will show on the screen caca_refresh() is not called.
* screen. Nothing will show on the screen until caca_refresh() is
* called.
* *
* If caca_set_delay() was called with a non-zero value, caca_refresh() * If caca_set_delay() was called with a non-zero value, caca_refresh()
* will use that value to achieve constant framerate: if two consecutive * will use that value to achieve constant framerate: if two consecutive
@@ -873,8 +841,9 @@ void caca_refresh(void)
#if !defined(_DOXYGEN_SKIP_ME) #if !defined(_DOXYGEN_SKIP_ME)
#define IDLE_USEC 10000 #define IDLE_USEC 10000
#endif #endif
static struct caca_timer timer = CACA_TIMER_INITIALIZER;
static int lastticks = 0; static int lastticks = 0;
int ticks = lastticks + _caca_getticks();
int ticks = lastticks + _caca_getticks(&timer);


#if defined(USE_SLANG) #if defined(USE_SLANG)
if(_caca_driver == CACA_DRIVER_SLANG) if(_caca_driver == CACA_DRIVER_SLANG)
@@ -958,9 +927,19 @@ void caca_refresh(void)
#endif #endif


/* Wait until _caca_delay + time of last call */ /* Wait until _caca_delay + time of last call */
ticks += _caca_getticks();
for(; ticks + IDLE_USEC < (int)_caca_delay; ticks += _caca_getticks())
ticks += _caca_getticks(&timer);
for(ticks += _caca_getticks(&timer);
ticks + IDLE_USEC < (int)_caca_delay;
ticks += _caca_getticks(&timer))
{
#if defined(HAVE_USLEEP)
usleep(IDLE_USEC); usleep(IDLE_USEC);
#elif defined(HAVE_SLEEP)
Sleep(IDLE_USEC / 1000);
#else
SLEEP
#endif
}


/* Update the sliding mean of the render time */ /* Update the sliding mean of the render time */
_caca_rendertime = (7 * _caca_rendertime + ticks) / 8; _caca_rendertime = (7 * _caca_rendertime + ticks) / 8;


+ 84
- 5
src/io.c View File

@@ -54,6 +54,7 @@
#include "caca_internals.h" #include "caca_internals.h"


static unsigned int _get_next_event(void); static unsigned int _get_next_event(void);
static unsigned int _lowlevel_event(void);
static void _push_event(unsigned int); static void _push_event(unsigned int);
static unsigned int _pop_event(void); static unsigned int _pop_event(void);


@@ -63,6 +64,16 @@ static unsigned int _pop_event(void);
static unsigned int eventbuf[EVENTBUF_LEN]; static unsigned int eventbuf[EVENTBUF_LEN];
static int events = 0; static int events = 0;


#if !defined(_DOXYGEN_SKIP_ME)
/* If no new key was pressed after AUTOREPEAT_THRESHOLD usec, assume the
* key was released */
#define AUTOREPEAT_THRESHOLD 200000
/* Start repeating key after AUTOREPEAT_TRIGGER usec and send keypress
* events every AUTOREPEAT_RATE usec. */
#define AUTOREPEAT_TRIGGER 300000
#define AUTOREPEAT_RATE 100000
#endif

/** \brief Get the next mouse or keyboard input event. /** \brief Get the next mouse or keyboard input event.
* *
* This function polls the event queue for mouse or keyboard events matching * This function polls the event queue for mouse or keyboard events matching
@@ -104,7 +115,13 @@ unsigned int caca_wait_event(unsigned int event_mask)
if(event & event_mask) if(event & event_mask)
return event; return event;


usleep(1000);
#if defined(HAVE_USLEEP)
usleep(10000);
#elif defined(HAVE_SLEEP)
Sleep(10);
#else
SLEEP
#endif
} }
} }


@@ -113,6 +130,72 @@ unsigned int caca_wait_event(unsigned int event_mask)
*/ */


static unsigned int _get_next_event(void) static unsigned int _get_next_event(void)
{
#if defined(USE_SLANG) || defined(USE_NCURSES)
static struct caca_timer key_timer = CACA_TIMER_INITIALIZER;
static unsigned int last_key_ticks = 0;
static unsigned int autorepeat_ticks = 0;
static unsigned int last_key = 0;
unsigned int ticks;
#endif
unsigned int event = _lowlevel_event();

#if defined(USE_SLANG)
if(_caca_driver != CACA_DRIVER_SLANG)
#endif
#if defined(USE_NCURSES)
if(_caca_driver != CACA_DRIVER_NCURSES)
#endif
return event;

#if defined(USE_SLANG) || defined(USE_NCURSES)
/* Simulate long keypresses using autorepeat features */
ticks = _caca_getticks(&key_timer);
last_key_ticks += ticks;
autorepeat_ticks += ticks;

/* Handle autorepeat */
if(last_key && autorepeat_ticks > AUTOREPEAT_TRIGGER
&& autorepeat_ticks > AUTOREPEAT_THRESHOLD
&& autorepeat_ticks > AUTOREPEAT_RATE)
{
_push_event(event);
autorepeat_ticks -= AUTOREPEAT_RATE;
return CACA_EVENT_KEY_PRESS | last_key;
}

/* We are in autorepeat mode and the same key was just pressed, ignore
* this event and return the next one by calling ourselves. */
if(event == (CACA_EVENT_KEY_PRESS | last_key))
{
last_key_ticks = 0;
return _get_next_event();
}

/* We are in autorepeat mode, but key has expired or a new key was
* pressed - store our event and return a key release event first */
if(last_key && (last_key_ticks > AUTOREPEAT_THRESHOLD
|| (event & CACA_EVENT_KEY_PRESS)))
{
_push_event(event);
event = CACA_EVENT_KEY_RELEASE | last_key;
last_key = 0;
return event;
}

/* A new key was pressed, enter autorepeat mode */
if(event & CACA_EVENT_KEY_PRESS)
{
last_key_ticks = 0;
autorepeat_ticks = 0;
last_key = event & 0x00ffffff;
}

return event;
#endif
}

static unsigned int _lowlevel_event(void)
{ {
unsigned int event = _pop_event(); unsigned int event = _pop_event();


@@ -213,7 +296,6 @@ static unsigned int _get_next_event(void)


if(intkey < 0x100) if(intkey < 0x100)
{ {
_push_event(CACA_EVENT_KEY_RELEASE | intkey);
return CACA_EVENT_KEY_PRESS | intkey; return CACA_EVENT_KEY_PRESS | intkey;
} }


@@ -360,7 +442,6 @@ static unsigned int _get_next_event(void)
case KEY_F(12): event = CACA_KEY_F12; break; case KEY_F(12): event = CACA_KEY_F12; break;
} }


_push_event(CACA_EVENT_KEY_RELEASE | event);
return CACA_EVENT_KEY_PRESS | event; return CACA_EVENT_KEY_PRESS | event;
} }
else else
@@ -377,7 +458,6 @@ static unsigned int _get_next_event(void)


if(intkey < 0x100) if(intkey < 0x100)
{ {
_push_event(CACA_EVENT_KEY_RELEASE | intkey);
return CACA_EVENT_KEY_PRESS | intkey; return CACA_EVENT_KEY_PRESS | intkey;
} }


@@ -412,7 +492,6 @@ static unsigned int _get_next_event(void)
case SL_KEY_F(12): event = CACA_KEY_F12; break; case SL_KEY_F(12): event = CACA_KEY_F12; break;
} }


_push_event(CACA_EVENT_KEY_RELEASE | event);
return CACA_EVENT_KEY_PRESS | event; return CACA_EVENT_KEY_PRESS | event;
} }
else else


+ 65
- 0
src/time.c View File

@@ -0,0 +1,65 @@
/*
* libcaca ASCII-Art library
* Copyright (c) 2002, 2003, 2004 Sam Hocevar <sam@zoy.org>
* All Rights Reserved
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307 USA
*/

/** \file time.c
* \version \$Id$
* \author Sam Hocevar <sam@zoy.org>
* \brief Timer routines
*
* This file contains simple timer routines.
*/

#include "config.h"

#include <stdlib.h>
#include <sys/time.h>
#include <time.h>

#include "caca.h"
#include "caca_internals.h"

unsigned int _caca_getticks(struct caca_timer *timer)
{
struct timeval tv;
unsigned int ticks = 0;

gettimeofday(&tv, NULL);

if(timer->last_sec != 0)
{
/* If the delay was greater than 60 seconds, return 10 seconds
* otherwise we may overflow our ticks counter. */
if(tv.tv_sec >= timer->last_sec + 60)
ticks = 60 * 1000000;
else
{
ticks = (tv.tv_sec - timer->last_sec) * 1000000;
ticks += tv.tv_usec;
ticks -= timer->last_usec;
}
}

timer->last_sec = tv.tv_sec;
timer->last_usec = tv.tv_usec;

return ticks;
}


+ 23
- 13
test/event.c View File

@@ -33,7 +33,7 @@ static void print_event(int, int, unsigned int);
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
int *events; int *events;
int i, h;
int i, h, quit;


if(caca_init()) if(caca_init())
return 1; return 1;
@@ -48,32 +48,38 @@ int main(int argc, char **argv)
events = malloc(h * sizeof(int)); events = malloc(h * sizeof(int));
memset(events, 0, h * sizeof(int)); memset(events, 0, h * sizeof(int));


for( ; ; )
for(quit = 0; !quit; )
{ {
unsigned int event = caca_wait_event(CACA_EVENT_ANY); unsigned int event = caca_wait_event(CACA_EVENT_ANY);


if(!event) if(!event)
continue; continue;


memmove(events + 1, events, (h - 1) * sizeof(int));
events[0] = event;
do
{
/* q quits */
if(event == (CACA_EVENT_KEY_PRESS | 'q'))
quit = 1;

memmove(events + 1, events, (h - 1) * sizeof(int));
events[0] = event;

event = caca_get_event(CACA_EVENT_ANY);
}
while(event);


caca_clear(); caca_clear();


/* Print current event */ /* Print current event */
caca_set_color(CACA_COLOR_WHITE, CACA_COLOR_BLUE); caca_set_color(CACA_COLOR_WHITE, CACA_COLOR_BLUE);
caca_draw_line(0, 0, caca_get_width() - 1, 0, ' '); caca_draw_line(0, 0, caca_get_width() - 1, 0, ' ');
print_event(0, 0, event);
print_event(0, 0, events[0]);


/* Print previous events */ /* Print previous events */
caca_set_color(CACA_COLOR_WHITE, CACA_COLOR_BLACK); caca_set_color(CACA_COLOR_WHITE, CACA_COLOR_BLACK);
for(i = 1; i < h && events[i]; i++) for(i = 1; i < h && events[i]; i++)
print_event(0, i, events[i]); print_event(0, i, events[i]);


/* q quits */
if(event == (CACA_EVENT_KEY_PRESS | 'q'))
break;

caca_refresh(); caca_refresh();
} }


@@ -85,18 +91,22 @@ int main(int argc, char **argv)


static void print_event(int x, int y, unsigned int event) static void print_event(int x, int y, unsigned int event)
{ {
int character;

switch(event & 0xff000000) switch(event & 0xff000000)
{ {
case CACA_EVENT_NONE: case CACA_EVENT_NONE:
caca_printf(x, y, "CACA_EVENT_NONE"); caca_printf(x, y, "CACA_EVENT_NONE");
break; break;
case CACA_EVENT_KEY_PRESS: case CACA_EVENT_KEY_PRESS:
caca_printf(x, y, "CACA_EVENT_KEY_PRESS 0x%02x",
event & 0x00ffffff);
character = event & 0x00ffffff;
caca_printf(x, y, "CACA_EVENT_KEY_PRESS 0x%02x (%c)", character,
(character > 0x20 && character < 0x80) ? character : '?');
break; break;
case CACA_EVENT_KEY_RELEASE: case CACA_EVENT_KEY_RELEASE:
caca_printf(x, y, "CACA_EVENT_KEY_RELEASE 0x2%x",
event & 0x00ffffff);
character = event & 0x00ffffff;
caca_printf(x, y, "CACA_EVENT_KEY_RELEASE 0x%02x (%c)", character,
(character > 0x20 && character < 0x80) ? character : '?');
break; break;
case CACA_EVENT_MOUSE_MOTION: case CACA_EVENT_MOUSE_MOTION:
caca_printf(x, y, "CACA_EVENT_MOUSE_MOTION %u %u", caca_printf(x, y, "CACA_EVENT_MOUSE_MOTION %u %u",


Loading…
Cancel
Save