conwrap.c 4.21 KiB
/* conwrap.c */
/* DOS's kbhit and getch functions for Unix - Casey Martin 2000 */
/* $Id$ */
/****************************************************************************
* @format.tab-size 4 (Plain Text/Source Code File Header) *
* @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) *
* *
* Copyright 2004 Rob Swindell - http://www.synchro.net/copyright.html *
* *
* 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. *
* See the GNU Lesser General Public License for more details: lgpl.txt or *
* http://www.fsf.org/copyleft/lesser.html *
* *
* Anonymous FTP access to the most recent released source is available at *
* ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net *
* *
* Anonymous CVS access to the development source and modification history *
* is available at cvs.synchro.net:/cvsroot/sbbs, example: *
* cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs login *
* (just hit return, no password is necessary) *
* cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs checkout src *
* *
* For Synchronet coding style and modification guidelines, see *
* http://www.synchro.net/source.html *
* *
* You are encouraged to submit any modifications (preferably in Unix diff *
* format) via e-mail to mods@synchro.net *
* *
* Note: If this box doesn't appear square, then you need to fix your tabs. *
****************************************************************************/
#if defined(__unix__)
#include <stdlib.h>
#include <string.h> /* memcpy */
#include <unistd.h>
#include <termios.h>
#if defined(__FreeBSD__)
#include <sys/kbio.h>
#elif defined(__linux__)
#include <sys/kd.h>
#endif
#include <sys/time.h>
#include <sys/types.h>
#include <signal.h>
#include "conwrap.h" /* Verify prototypes */
static struct termios current; /* our current term settings */
static struct termios original; /* old termios settings */
static int beensetup = 0; /* has _termios_setup() been called? */
static int istty = 0; /* is stdin a tty? */
/* Resets the termios to its previous state */
void _termios_reset(void)
{
tcsetattr(STDIN_FILENO, TCSANOW, &original);
}
/************************************************
This pair of functions handles Ctrl-Z presses
************************************************/
#if defined(__BORLANDC__)
#pragma argsused
#endif
void _sighandler_stop(int sig)
{
/* clean up the terminal */
_termios_reset();
/* ... and stop */
kill(getpid(), SIGSTOP);
}
#if defined(__BORLANDC__)
#pragma argsused
#endif
void _sighandler_cont(int sig)
{
/* restore terminal */
tcsetattr(STDIN_FILENO, TCSANOW, ¤t);
}
/* Prepares termios for non-blocking action */
void _termios_setup(void)
{
beensetup = 1;
tcgetattr(STDIN_FILENO, &original);
memcpy(¤t, &original, sizeof(struct termios));
current.c_cc[VMIN] = 1; /* read() will return with one char */
current.c_cc[VTIME] = 0; /* read() blocks forever */
current.c_lflag &= ~ICANON; /* character mode */
current.c_lflag &= ~ECHO; /* turn off echoing */
tcsetattr(STDIN_FILENO, TCSANOW, ¤t);
/* Let's install an exit function, also. This way, we can reset
* the termios silently
*/
atexit(_termios_reset);
/* install the Ctrl-Z handler */
signal(SIGSTOP, _sighandler_stop);
signal(SIGCONT, _sighandler_cont);
}
int kbhit(void)
{
fd_set inp;
struct timeval timeout = {0, 0};
if(!istty) {
istty = isatty(STDIN_FILENO);
if(!istty)
return 0;
}
/* set up select() args */
FD_ZERO(&inp);
FD_SET(STDIN_FILENO, &inp);
if(select(STDIN_FILENO+1, &inp, NULL, NULL, &timeout)<1)
return 0;
return 1;
}
int getch(void)
{
char c;
if(!beensetup)
_termios_setup();
/* get a char out of stdin */
read(STDIN_FILENO, &c, 1);
return c;
}
#endif /* __unix__ */