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
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
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
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

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

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


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 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,
[ --enable-slang slang graphics support (autodetected)])
AC_ARG_ENABLE(ncurses,
[ --enable-ncurses ncurses graphics support (autodetected)])
AC_ARG_ENABLE(win32,
[ --enable-win32 Windows console support (autodetected)])
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,
[ --enable-x11 X11 support (autodetected)])

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=""

@@ -35,7 +37,7 @@ if test "${enable_conio}" != "no"; then
ac_cv_my_have_conio="no"
AC_CHECK_HEADERS(conio.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_MSG_RESULT(yes)
AC_DEFINE(SCREENUPDATE_IN_PC_H, 1,
@@ -48,6 +50,23 @@ if test "${enable_conio}" != "no"; then
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
ac_cv_my_have_slang="no"
AC_CHECK_HEADERS(slang.h slang/slang.h,


+ 1
- 0
src/Makefile.am View File

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

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;
mousemask(newmask, &oldmask);
mouseinterval(-1); /* No click emulation */

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


+ 10
- 0
src/caca_internals.h View File

@@ -48,6 +48,13 @@ enum caca_driver
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;

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

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

/* Cached screen size */
extern unsigned int _caca_width;
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 <unistd.h>
#include <stdarg.h>
#include <sys/time.h>
#include <time.h>

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

static unsigned int _caca_getticks(void);

/** \brief Set the default colour pair.
*
* This function sets the default colour pair. String functions such as
@@ -828,39 +824,11 @@ unsigned int caca_get_rendertime(void)
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.
*
* 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()
* will use that value to achieve constant framerate: if two consecutive
@@ -873,8 +841,9 @@ void caca_refresh(void)
#if !defined(_DOXYGEN_SKIP_ME)
#define IDLE_USEC 10000
#endif
static struct caca_timer timer = CACA_TIMER_INITIALIZER;
static int lastticks = 0;
int ticks = lastticks + _caca_getticks();
int ticks = lastticks + _caca_getticks(&timer);

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

/* 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);
#elif defined(HAVE_SLEEP)
Sleep(IDLE_USEC / 1000);
#else
SLEEP
#endif
}

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


+ 84
- 5
src/io.c View File

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

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

@@ -63,6 +64,16 @@ static unsigned int _pop_event(void);
static unsigned int eventbuf[EVENTBUF_LEN];
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.
*
* 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)
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)
{
#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();

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

if(intkey < 0x100)
{
_push_event(CACA_EVENT_KEY_RELEASE | 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;
}

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

if(intkey < 0x100)
{
_push_event(CACA_EVENT_KEY_RELEASE | 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;
}

_push_event(CACA_EVENT_KEY_RELEASE | event);
return CACA_EVENT_KEY_PRESS | event;
}
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 *events;
int i, h;
int i, h, quit;

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

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

if(!event)
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();

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

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

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

caca_refresh();
}

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

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

switch(event & 0xff000000)
{
case CACA_EVENT_NONE:
caca_printf(x, y, "CACA_EVENT_NONE");
break;
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;
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;
case CACA_EVENT_MOUSE_MOTION:
caca_printf(x, y, "CACA_EVENT_MOUSE_MOTION %u %u",


Loading…
Cancel
Save