mirror of
http://mpg123.de/trunk/.git
synced 2025-08-06 10:02:38 +03:00
term: the new switchery to later enable term_type=win32
git-svn-id: svn://scm.orgis.org/mpg123/trunk@5082 35dc7657-300d-0410-a2e5-dc2837fedb53
This commit is contained in:
14
configure.ac
14
configure.ac
@@ -1209,11 +1209,13 @@ if test "x$have_mmap" = "xno"; then
|
|||||||
AC_CHECK_FUNCS([shmget shmat shmdt shmctl],[], [buffer=disabled])
|
AC_CHECK_FUNCS([shmget shmat shmdt shmctl],[], [buffer=disabled])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
term_type=none
|
||||||
# Check if system supports termios
|
# Check if system supports termios
|
||||||
AC_SYS_POSIX_TERMIOS
|
AC_SYS_POSIX_TERMIOS
|
||||||
if test "x$ac_cv_sys_posix_termios" = "xyes"; then
|
if test "x$ac_cv_sys_posix_termios" = "xyes"; then
|
||||||
AC_DEFINE_UNQUOTED([HAVE_TERMIOS], 1,
|
AC_DEFINE_UNQUOTED([HAVE_TERMIOS], 1,
|
||||||
[Define this if you have the POSIX termios library])
|
[Define this if you have the POSIX termios library])
|
||||||
|
term_type=posix
|
||||||
fi
|
fi
|
||||||
|
|
||||||
AC_CHECK_FUNCS( random )
|
AC_CHECK_FUNCS( random )
|
||||||
@@ -2659,6 +2661,12 @@ AM_CONDITIONAL([NET123_EXEC], [ test x$network_type = xexec ])
|
|||||||
AM_CONDITIONAL([NET123_WINHTTP], [ test x$network_type = xwinhttp ])
|
AM_CONDITIONAL([NET123_WINHTTP], [ test x$network_type = xwinhttp ])
|
||||||
AM_CONDITIONAL([NET123_WININET], [ test x$network_type = xwininet ])
|
AM_CONDITIONAL([NET123_WININET], [ test x$network_type = xwininet ])
|
||||||
|
|
||||||
|
dnl ############## Terminal choice
|
||||||
|
|
||||||
|
AM_CONDITIONAL( [TERM_POSIX], [test "x$term_type" = xposix] )
|
||||||
|
AM_CONDITIONAL( [TERM_NONE], [test "x$term_type" = xnone] )
|
||||||
|
AM_CONDITIONAL( [TERM_WIN32], [test "x$term_type" = xwin32] )
|
||||||
|
|
||||||
dnl ############## FIFO enable
|
dnl ############## FIFO enable
|
||||||
|
|
||||||
if test x"$fifo" = xauto; then
|
if test x"$fifo" = xauto; then
|
||||||
@@ -2718,6 +2726,11 @@ AC_CONFIG_FILES([
|
|||||||
src/libsyn123/syn123.h
|
src/libsyn123/syn123.h
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
|
AM_CONDITIONAL( [TERM_POSIX], [test "x$term_type" = xposix] )
|
||||||
|
AM_CONDITIONAL( [TERM_NONE], [test "x$term_type" = xnone] )
|
||||||
|
|
||||||
|
|
||||||
AC_OUTPUT
|
AC_OUTPUT
|
||||||
|
|
||||||
|
|
||||||
@@ -2732,6 +2745,7 @@ echo "
|
|||||||
Compiler Optimization ... $with_optimization
|
Compiler Optimization ... $with_optimization
|
||||||
Gapless Support ......... $gapless
|
Gapless Support ......... $gapless
|
||||||
Debugging ............... $debugging
|
Debugging ............... $debugging
|
||||||
|
Terminal control ........ $term_type
|
||||||
Extreme debugging ....... $xdebugging
|
Extreme debugging ....... $xdebugging
|
||||||
Seek table size ......... $seektable
|
Seek table size ......... $seektable
|
||||||
FIFO support ............ $fifo
|
FIFO support ............ $fifo
|
||||||
|
@@ -75,6 +75,7 @@ src_mpg123_SOURCES = \
|
|||||||
src/streamdump.c \
|
src/streamdump.c \
|
||||||
src/term.c \
|
src/term.c \
|
||||||
src/term.h \
|
src/term.h \
|
||||||
|
src/terms.h \
|
||||||
src/win32_support.h
|
src/win32_support.h
|
||||||
|
|
||||||
# Does that finally work to build/link the correct object file?
|
# Does that finally work to build/link the correct object file?
|
||||||
@@ -105,6 +106,18 @@ src_mpg123_strip_SOURCES = \
|
|||||||
src/getlopt.c \
|
src/getlopt.c \
|
||||||
src/getlopt.h
|
src/getlopt.h
|
||||||
|
|
||||||
|
if TERM_POSIX
|
||||||
|
src_mpg123_SOURCES += src/term_posix.c
|
||||||
|
endif
|
||||||
|
|
||||||
|
if TERM_WIN32
|
||||||
|
src_mpg123_SOURCES += src/term_win32.c
|
||||||
|
endif
|
||||||
|
|
||||||
|
if TERM_NONE
|
||||||
|
src_mpg123_SOURCES += src/term_none.c
|
||||||
|
endif
|
||||||
|
|
||||||
if NET123_EXEC
|
if NET123_EXEC
|
||||||
src_mpg123_SOURCES += src/net123.h src/net123_exec.c
|
src_mpg123_SOURCES += src/net123.h src/net123_exec.c
|
||||||
endif
|
endif
|
||||||
|
@@ -15,6 +15,7 @@
|
|||||||
#include "out123.h"
|
#include "out123.h"
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "terms.h"
|
||||||
|
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
|
||||||
|
60
src/local.c
60
src/local.c
@@ -112,66 +112,6 @@ static int is_utf8(const char *lang)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int term_have_fun(int fd, int want_visuals)
|
|
||||||
{
|
|
||||||
if(term_is_fun > -1)
|
|
||||||
return term_is_fun;
|
|
||||||
else
|
|
||||||
term_is_fun = 0;
|
|
||||||
#ifdef HAVE_TERMIOS
|
|
||||||
if(term_width(fd) > 0 && want_visuals)
|
|
||||||
{
|
|
||||||
/* Only play with non-dumb terminals. */
|
|
||||||
char *tname = compat_getenv("TERM");
|
|
||||||
if(tname)
|
|
||||||
{
|
|
||||||
if(strcmp(tname, "") && strcmp(tname, "dumb"))
|
|
||||||
term_is_fun = 1;
|
|
||||||
free(tname);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return term_is_fun;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Also serves as a way to detect if we have an interactive terminal. */
|
|
||||||
int term_width(int fd)
|
|
||||||
{
|
|
||||||
#ifdef HAVE_TERMIOS
|
|
||||||
/* POSIX */
|
|
||||||
struct winsize geometry;
|
|
||||||
geometry.ws_col = 0;
|
|
||||||
if(ioctl(fd, TIOCGWINSZ, &geometry) >= 0)
|
|
||||||
return (int)geometry.ws_col;
|
|
||||||
#elif defined(WIN32)
|
|
||||||
CONSOLE_SCREEN_BUFFER_INFO pinfo;
|
|
||||||
HANDLE hStdout;
|
|
||||||
DWORD handle;
|
|
||||||
|
|
||||||
switch(fd){
|
|
||||||
case STDIN_FILENO:
|
|
||||||
handle = STD_INPUT_HANDLE;
|
|
||||||
break;
|
|
||||||
case STDOUT_FILENO:
|
|
||||||
handle = STD_OUTPUT_HANDLE;
|
|
||||||
break;
|
|
||||||
case STDERR_FILENO:
|
|
||||||
handle = STD_ERROR_HANDLE;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
hStdout = GetStdHandle(handle);
|
|
||||||
if(hStdout == INVALID_HANDLE_VALUE || hStdout == NULL)
|
|
||||||
return -1;
|
|
||||||
if(GetConsoleScreenBufferInfo(hStdout, &pinfo)){
|
|
||||||
return pinfo.dwMaximumWindowSize.X;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Moved encoding stuff over from metaprint.c and removed references to libmpg123,
|
// Moved encoding stuff over from metaprint.c and removed references to libmpg123,
|
||||||
// meaning no mpg123_string for you!
|
// meaning no mpg123_string for you!
|
||||||
|
|
||||||
|
@@ -36,6 +36,7 @@
|
|||||||
#include "sysutil.h"
|
#include "sysutil.h"
|
||||||
#include "getlopt.h"
|
#include "getlopt.h"
|
||||||
#include "term.h"
|
#include "term.h"
|
||||||
|
#include "terms.h"
|
||||||
#include "playlist.h"
|
#include "playlist.h"
|
||||||
#include "metaprint.h"
|
#include "metaprint.h"
|
||||||
#include "httpget.h"
|
#include "httpget.h"
|
||||||
|
@@ -88,9 +88,6 @@ enum runmodes
|
|||||||
|
|
||||||
static int runmode = RUN_MAIN;
|
static int runmode = RUN_MAIN;
|
||||||
|
|
||||||
int stdout_is_term = FALSE; // It's an interactive terminal.
|
|
||||||
int stderr_is_term = FALSE; // It's an interactive terminal.
|
|
||||||
|
|
||||||
static FILE* input = NULL;
|
static FILE* input = NULL;
|
||||||
static char *encoding_name = NULL;
|
static char *encoding_name = NULL;
|
||||||
static int encoding = MPG123_ENC_SIGNED_16;
|
static int encoding = MPG123_ENC_SIGNED_16;
|
||||||
@@ -1511,8 +1508,6 @@ int main(int sys_argc, char ** sys_argv)
|
|||||||
_wildcard(&argc,&argv);
|
_wildcard(&argc,&argv);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
stderr_is_term = term_width(STDERR_FILENO) >= 0;
|
|
||||||
stdout_is_term = term_width(STDOUT_FILENO) >= 0;
|
|
||||||
while ((result = getlopt(argc, argv, opts)))
|
while ((result = getlopt(argc, argv, opts)))
|
||||||
switch (result) {
|
switch (result) {
|
||||||
case GLO_UNKNOWN:
|
case GLO_UNKNOWN:
|
||||||
|
139
src/term.c
139
src/term.c
@@ -8,30 +8,21 @@
|
|||||||
|
|
||||||
#include "mpg123app.h"
|
#include "mpg123app.h"
|
||||||
|
|
||||||
#ifdef HAVE_TERMIOS
|
|
||||||
|
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
#include "term.h"
|
#include "term.h"
|
||||||
|
#include "terms.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "playlist.h"
|
#include "playlist.h"
|
||||||
#include "metaprint.h"
|
#include "metaprint.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
|
||||||
static int term_enable = 0;
|
static int term_enable = 0;
|
||||||
// This now always refers to a freshly opened terminal descriptor (e.g. /dev/tty).
|
|
||||||
// Printouts to stderr are independent of this.
|
|
||||||
static int term_fd = -1;
|
|
||||||
static struct termios old_tio;
|
|
||||||
int seeking = FALSE;
|
int seeking = FALSE;
|
||||||
|
|
||||||
extern out123_handle *ao;
|
extern out123_handle *ao;
|
||||||
|
|
||||||
/* Buffered key from a signal or whatnot.
|
|
||||||
We ignore the null character... */
|
|
||||||
static char prekey = 0;
|
|
||||||
|
|
||||||
/* Hm, next step would be some system in this, plus configurability...
|
/* Hm, next step would be some system in this, plus configurability...
|
||||||
Two keys for everything? It's just stop/pause for now... */
|
Two keys for everything? It's just stop/pause for now... */
|
||||||
struct keydef { const char key; const char key2; const char* desc; };
|
struct keydef { const char key; const char key2; const char* desc; };
|
||||||
@@ -74,51 +65,6 @@ struct keydef term_help[] =
|
|||||||
,{ MPG123_TREBLE_DOWN_KEY, 0, "less treble" }
|
,{ MPG123_TREBLE_DOWN_KEY, 0, "less treble" }
|
||||||
};
|
};
|
||||||
|
|
||||||
void term_sigcont(int sig);
|
|
||||||
static void term_sigusr(int sig);
|
|
||||||
|
|
||||||
/* This must call only functions safe inside a signal handler. */
|
|
||||||
int term_setup(struct termios *pattern)
|
|
||||||
{
|
|
||||||
mdebug("setup on fd %d", term_fd);
|
|
||||||
|
|
||||||
/* One might want to use sigaction instead. */
|
|
||||||
signal(SIGCONT, term_sigcont);
|
|
||||||
signal(SIGUSR1, term_sigusr);
|
|
||||||
signal(SIGUSR2, term_sigusr);
|
|
||||||
#ifndef __OS2__
|
|
||||||
struct termios tio = *pattern;
|
|
||||||
tio.c_lflag &= ~(ICANON|ECHO);
|
|
||||||
tio.c_cc[VMIN] = 1;
|
|
||||||
tio.c_cc[VTIME] = 0;
|
|
||||||
return tcsetattr(term_fd,TCSANOW,&tio);
|
|
||||||
#else
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void term_sigcont(int sig)
|
|
||||||
{
|
|
||||||
term_enable = 0;
|
|
||||||
|
|
||||||
if (term_setup(&old_tio) < 0)
|
|
||||||
{
|
|
||||||
fprintf(stderr,"Can't set terminal attributes\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
term_enable = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void term_sigusr(int sig)
|
|
||||||
{
|
|
||||||
switch(sig)
|
|
||||||
{
|
|
||||||
case SIGUSR1: prekey=*param.term_usr1; break;
|
|
||||||
case SIGUSR2: prekey=*param.term_usr2; break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* initialze terminal */
|
/* initialze terminal */
|
||||||
void term_init(void)
|
void term_init(void)
|
||||||
{
|
{
|
||||||
@@ -133,41 +79,15 @@ void term_init(void)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
term_enable = 0;
|
term_enable = 0;
|
||||||
const char *term_name;
|
errno = 0;
|
||||||
#ifdef HAVE_CTERMID
|
if(term_setup() < 0)
|
||||||
term_name = ctermid(NULL);
|
|
||||||
#else
|
|
||||||
term_name = "/dev/tty";
|
|
||||||
#endif
|
|
||||||
if(term_name)
|
|
||||||
mdebug("accessing terminal for control via %s", term_name);
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
error("no controlling terminal");
|
if(errno)
|
||||||
|
merror("failed to set up terminal: %s", strerror(errno));
|
||||||
|
else
|
||||||
|
error("failed to set up terminal");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
term_fd = open(term_name, O_RDONLY);
|
|
||||||
if(term_fd < 0)
|
|
||||||
{
|
|
||||||
merror("failed to open terminal: %s", strerror(errno));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Testing if OS2 works without the attr fun, at all.
|
|
||||||
#ifndef __OS2__
|
|
||||||
if(tcgetattr(term_fd, &old_tio) < 0)
|
|
||||||
{
|
|
||||||
merror("failed to get terminal attributes: %s", strerror(errno));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(term_setup(&old_tio) < 0)
|
|
||||||
{
|
|
||||||
close(term_fd);
|
|
||||||
error("failure setting terminal attributes");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
term_enable = 1;
|
term_enable = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -286,37 +206,6 @@ static void seekmode(mpg123_handle *mh, out123_handle *ao)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the next pressed key, if any.
|
|
||||||
Returns 1 when there is a key, 0 if not. */
|
|
||||||
static int get_key(int do_delay, char *val)
|
|
||||||
{
|
|
||||||
fd_set r;
|
|
||||||
struct timeval t;
|
|
||||||
|
|
||||||
/* Shortcut: If some other means sent a key, use it. */
|
|
||||||
if(prekey)
|
|
||||||
{
|
|
||||||
debug1("Got prekey: %c\n", prekey);
|
|
||||||
*val = prekey;
|
|
||||||
prekey = 0;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
t.tv_sec=0;
|
|
||||||
t.tv_usec=(do_delay) ? 10*1000 : 0;
|
|
||||||
|
|
||||||
FD_ZERO(&r);
|
|
||||||
FD_SET(term_fd,&r);
|
|
||||||
if(select(term_fd+1,&r,NULL,NULL,&t) > 0 && FD_ISSET(term_fd,&r))
|
|
||||||
{
|
|
||||||
if(read(term_fd,val,1) <= 0)
|
|
||||||
return 0; /* Well, we couldn't read the key, so there is none. */
|
|
||||||
else
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void term_handle_key(mpg123_handle *fr, out123_handle *ao, char val)
|
static void term_handle_key(mpg123_handle *fr, out123_handle *ao, char val)
|
||||||
{
|
{
|
||||||
debug1("term_handle_key: %c", val);
|
debug1("term_handle_key: %c", val);
|
||||||
@@ -622,7 +511,7 @@ static void term_handle_input(mpg123_handle *fr, out123_handle *ao, int do_delay
|
|||||||
{
|
{
|
||||||
char val;
|
char val;
|
||||||
/* Do we really want that while loop? This means possibly handling multiple inputs that come very rapidly in one go. */
|
/* Do we really want that while loop? This means possibly handling multiple inputs that come very rapidly in one go. */
|
||||||
while(get_key(do_delay, &val))
|
while(term_get_key(do_delay, &val))
|
||||||
{
|
{
|
||||||
term_handle_key(fr, ao, val);
|
term_handle_key(fr, ao, val);
|
||||||
}
|
}
|
||||||
@@ -638,15 +527,5 @@ void term_exit(void)
|
|||||||
|
|
||||||
if(!term_enable) return;
|
if(!term_enable) return;
|
||||||
|
|
||||||
#ifndef __OS2__
|
term_restore();
|
||||||
debug("reset attrbutes");
|
|
||||||
tcsetattr(term_fd,TCSAFLUSH,&old_tio);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if(term_fd > -1)
|
|
||||||
close(term_fd);
|
|
||||||
term_fd = -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
31
src/term_none.c
Normal file
31
src/term_none.c
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
term_none: no-op terminal, nothing at all
|
||||||
|
|
||||||
|
copyright 2008-2022 by the mpg123 project - free software under the terms of the LGPL 2.1
|
||||||
|
see COPYING and AUTHORS files in distribution or http://mpg123.org
|
||||||
|
initially written by Thomas Orgis and Jonathan Yong
|
||||||
|
*/
|
||||||
|
|
||||||
|
int term_have_fun(int fd, int want_visuals)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int term_width(int fd)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int term_setup(void)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void term_restore(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int term_get_key(int do_delay, char *val)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
199
src/term_posix.c
Normal file
199
src/term_posix.c
Normal file
@@ -0,0 +1,199 @@
|
|||||||
|
/*
|
||||||
|
term_posix: POSIX-specifc terminal functionality
|
||||||
|
|
||||||
|
HAVE_TERMIOS is a prerequisite.
|
||||||
|
|
||||||
|
copyright 2008-2022 by the mpg123 project - free software under the terms of the LGPL 2.1
|
||||||
|
see COPYING and AUTHORS files in distribution or http://mpg123.org
|
||||||
|
initially written by Thomas Orgis
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "compat.h"
|
||||||
|
|
||||||
|
#ifndef HAVE_TERMIOS
|
||||||
|
#error "No TERMIOS? Here?"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// for param struct
|
||||||
|
#include "mpg123app.h"
|
||||||
|
|
||||||
|
#include <termios.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
|
||||||
|
#include "terms.h"
|
||||||
|
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
static int term_is_fun = -1;
|
||||||
|
// This now always refers to a ;freshly opened terminal descriptor (e.g. /dev/tty).
|
||||||
|
// Printouts to stderr are independent of this.
|
||||||
|
static int term_fd = -1;
|
||||||
|
static struct termios old_tio;
|
||||||
|
|
||||||
|
/* Buffered key from a signal or whatnot.
|
||||||
|
We ignore the null character... */
|
||||||
|
static char prekey = 0;
|
||||||
|
|
||||||
|
int term_have_fun(int fd, int want_visuals)
|
||||||
|
{
|
||||||
|
if(term_is_fun > -1)
|
||||||
|
return term_is_fun;
|
||||||
|
else
|
||||||
|
term_is_fun = 0;
|
||||||
|
if(term_width(fd) > 0 && want_visuals)
|
||||||
|
{
|
||||||
|
/* Only play with non-dumb terminals. */
|
||||||
|
char *tname = compat_getenv("TERM");
|
||||||
|
if(tname)
|
||||||
|
{
|
||||||
|
if(strcmp(tname, "") && strcmp(tname, "dumb"))
|
||||||
|
term_is_fun = 1;
|
||||||
|
free(tname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return term_is_fun;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Also serves as a way to detect if we have an interactive terminal. */
|
||||||
|
int term_width(int fd)
|
||||||
|
{
|
||||||
|
struct winsize geometry;
|
||||||
|
geometry.ws_col = 0;
|
||||||
|
if(ioctl(fd, TIOCGWINSZ, &geometry) >= 0)
|
||||||
|
return (int)geometry.ws_col;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int term_setup_detail(struct termios *pattern);
|
||||||
|
|
||||||
|
static void term_sigcont(int sig)
|
||||||
|
{
|
||||||
|
if(term_setup_detail(&old_tio) < 0)
|
||||||
|
{
|
||||||
|
debug("Can't set terminal attributes");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void term_sigusr(int sig)
|
||||||
|
{
|
||||||
|
switch(sig)
|
||||||
|
{
|
||||||
|
case SIGUSR1: prekey=*param.term_usr1; break;
|
||||||
|
case SIGUSR2: prekey=*param.term_usr2; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This must call only functions safe inside a signal handler. */
|
||||||
|
static int term_setup_detail(struct termios *pattern)
|
||||||
|
{
|
||||||
|
mdebug("setup on fd %d", term_fd);
|
||||||
|
|
||||||
|
/* One might want to use sigaction instead. */
|
||||||
|
signal(SIGCONT, term_sigcont);
|
||||||
|
signal(SIGUSR1, term_sigusr);
|
||||||
|
signal(SIGUSR2, term_sigusr);
|
||||||
|
struct termios tio = *pattern;
|
||||||
|
tio.c_lflag &= ~(ICANON|ECHO);
|
||||||
|
tio.c_cc[VMIN] = 1;
|
||||||
|
tio.c_cc[VTIME] = 0;
|
||||||
|
#ifdef __OS2__
|
||||||
|
// Do not care for the error until OS/2 is known to work.
|
||||||
|
tcsetattr(term_fd,TCSANOW,&tio);
|
||||||
|
return 0;
|
||||||
|
#else
|
||||||
|
return tcsetattr(term_fd,TCSANOW,&tio);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int term_setup(void)
|
||||||
|
{
|
||||||
|
if(term_fd < 0)
|
||||||
|
{
|
||||||
|
const char *term_name;
|
||||||
|
#ifdef HAVE_CTERMID
|
||||||
|
term_name = ctermid(NULL);
|
||||||
|
#else
|
||||||
|
term_name = "/dev/tty";
|
||||||
|
#endif
|
||||||
|
if(term_name)
|
||||||
|
mdebug("accessing terminal for control via %s", term_name);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
error("no controlling terminal");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
term_fd = open(term_name, O_RDONLY);
|
||||||
|
if(term_fd < 0)
|
||||||
|
{
|
||||||
|
merror("failed to open terminal: %s", strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(tcgetattr(term_fd, &old_tio) < 0)
|
||||||
|
{
|
||||||
|
// For now, this always fails on OS/2, but they might fix things.
|
||||||
|
// So just try to move on.
|
||||||
|
#ifndef __OS2__
|
||||||
|
merror("failed to get terminal attributes: %s", strerror(errno));
|
||||||
|
return -1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
if(term_setup_detail(&old_tio) < 0)
|
||||||
|
{
|
||||||
|
close(term_fd);
|
||||||
|
term_fd = -1;
|
||||||
|
if(errno)
|
||||||
|
merror("failure setting terminal attributes: %s", strerror(errno));
|
||||||
|
else
|
||||||
|
error("failure setting terminal attributes");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the next pressed key, if any.
|
||||||
|
Returns 1 when there is a key, 0 if not. */
|
||||||
|
int term_get_key(int do_delay, char *val)
|
||||||
|
{
|
||||||
|
fd_set r;
|
||||||
|
struct timeval t;
|
||||||
|
|
||||||
|
/* Shortcut: If some other means sent a key, use it. */
|
||||||
|
if(prekey)
|
||||||
|
{
|
||||||
|
debug1("Got prekey: %c\n", prekey);
|
||||||
|
*val = prekey;
|
||||||
|
prekey = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
t.tv_sec=0;
|
||||||
|
t.tv_usec=(do_delay) ? 10*1000 : 0;
|
||||||
|
|
||||||
|
FD_ZERO(&r);
|
||||||
|
FD_SET(term_fd,&r);
|
||||||
|
if(select(term_fd+1,&r,NULL,NULL,&t) > 0 && FD_ISSET(term_fd,&r))
|
||||||
|
{
|
||||||
|
if(read(term_fd,val,1) <= 0)
|
||||||
|
return 0; /* Well, we couldn't read the key, so there is none. */
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void term_restore(void)
|
||||||
|
{
|
||||||
|
debug("reset attrbutes");
|
||||||
|
tcsetattr(term_fd,TCSAFLUSH,&old_tio);
|
||||||
|
|
||||||
|
if(term_fd > -1)
|
||||||
|
close(term_fd);
|
||||||
|
term_fd = -1;
|
||||||
|
}
|
Reference in New Issue
Block a user