mirror of https://github.com/gdamore/tcell.git
fixes #277 Build fails on mips architectures
This commit is contained in:
parent
30e78c7859
commit
061f3f89b0
153
tscreen_linux.go
153
tscreen_linux.go
|
@ -20,20 +20,100 @@ import (
|
|||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
type termiosPrivate syscall.Termios
|
||||
type termiosPrivate struct {
|
||||
tio *unix.Termios
|
||||
}
|
||||
|
||||
// Linux is a little weird, in that it supports the ospeed and
|
||||
// ispeed fields for most architectures, which can be set to nearly
|
||||
// any valid value. However, for some (e.g. MIPS) it does not have
|
||||
// those fields. In all cases it also uses the old BXXX values
|
||||
// and attempts to find the closest match unless something different
|
||||
// was specified by the application. Since we can't rely on
|
||||
// ospeed or ispeed everywhere, we settle for the legacy method.
|
||||
// (Alternatively we could have different versions of this for
|
||||
// different CPU architectures, but that's no fun either.)
|
||||
func getbaud(tios *unix.Termios) int {
|
||||
bval := tios.Cflag & unix.CBAUD
|
||||
|
||||
// This gives us the appropriate BXXX value, so convert.
|
||||
// Note that if we ever have SPARC on Linux, it will need
|
||||
// a different set of values.
|
||||
switch bval {
|
||||
case unix.B0:
|
||||
return 0
|
||||
case unix.B50:
|
||||
return 50
|
||||
case unix.B75:
|
||||
return 75
|
||||
case unix.B110:
|
||||
return 110
|
||||
case unix.B134:
|
||||
return 134
|
||||
case unix.B150:
|
||||
return 150
|
||||
case unix.B200:
|
||||
return 200
|
||||
case unix.B300:
|
||||
return 300
|
||||
case unix.B600:
|
||||
return 600
|
||||
case unix.B1200:
|
||||
return 1200
|
||||
case unix.B1800:
|
||||
return 1800
|
||||
case unix.B2400:
|
||||
return 2400
|
||||
case unix.B4800:
|
||||
return 4800
|
||||
case unix.B9600:
|
||||
return 9600
|
||||
case unix.B19200:
|
||||
return 19200
|
||||
case unix.B38400:
|
||||
return 38400
|
||||
case unix.B57600:
|
||||
return 57600
|
||||
case unix.B115200:
|
||||
return 115200
|
||||
case unix.B230400:
|
||||
return 230400
|
||||
case unix.B460800:
|
||||
return 460800
|
||||
case unix.B500000:
|
||||
return 500000
|
||||
case unix.B576000:
|
||||
return 576000
|
||||
case unix.B921600:
|
||||
return 921600
|
||||
case unix.B1000000:
|
||||
return 1000000
|
||||
case unix.B1152000:
|
||||
return 1152000
|
||||
case unix.B1500000:
|
||||
return 1500000
|
||||
case unix.B2000000:
|
||||
return 2000000
|
||||
case unix.B2500000:
|
||||
return 2500000
|
||||
case unix.B3000000:
|
||||
return 3000000
|
||||
case unix.B3500000:
|
||||
return 3500000
|
||||
case unix.B4000000:
|
||||
return 4000000
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (t *tScreen) termioInit() error {
|
||||
var e error
|
||||
var newtios termiosPrivate
|
||||
var fd uintptr
|
||||
var tios uintptr
|
||||
var ioc uintptr
|
||||
t.tiosp = &termiosPrivate{}
|
||||
var raw *unix.Termios
|
||||
var tio *unix.Termios
|
||||
|
||||
if t.in, e = os.OpenFile("/dev/tty", os.O_RDONLY, 0); e != nil {
|
||||
goto failed
|
||||
|
@ -42,41 +122,39 @@ func (t *tScreen) termioInit() error {
|
|||
goto failed
|
||||
}
|
||||
|
||||
tios = uintptr(unsafe.Pointer(t.tiosp))
|
||||
ioc = uintptr(syscall.TCGETS)
|
||||
fd = uintptr(t.out.Fd())
|
||||
if _, _, e1 := syscall.Syscall6(syscall.SYS_IOCTL, fd, ioc, tios, 0, 0, 0); e1 != 0 {
|
||||
e = e1
|
||||
tio, e = unix.IoctlGetTermios(int(t.out.Fd()), unix.TCGETS)
|
||||
if e != nil {
|
||||
goto failed
|
||||
}
|
||||
|
||||
// On this platform, the baud rate is stored
|
||||
// directly as an integer in termios.c_ospeed.
|
||||
t.baud = int(t.tiosp.Ospeed)
|
||||
newtios = *t.tiosp
|
||||
newtios.Iflag &^= syscall.IGNBRK | syscall.BRKINT | syscall.PARMRK |
|
||||
syscall.ISTRIP | syscall.INLCR | syscall.IGNCR |
|
||||
syscall.ICRNL | syscall.IXON
|
||||
newtios.Oflag &^= syscall.OPOST
|
||||
newtios.Lflag &^= syscall.ECHO | syscall.ECHONL | syscall.ICANON |
|
||||
syscall.ISIG | syscall.IEXTEN
|
||||
newtios.Cflag &^= syscall.CSIZE | syscall.PARENB
|
||||
newtios.Cflag |= syscall.CS8
|
||||
t.tiosp = &termiosPrivate{tio: tio}
|
||||
t.baud = getbaud(tio)
|
||||
|
||||
// make a local copy, to make it raw
|
||||
raw = &unix.Termios{
|
||||
Cflag: tio.Cflag,
|
||||
Oflag: tio.Oflag,
|
||||
Iflag: tio.Iflag,
|
||||
Lflag: tio.Lflag,
|
||||
Cc: tio.Cc,
|
||||
}
|
||||
raw.Iflag &^= (unix.IGNBRK | unix.BRKINT | unix.PARMRK | unix.ISTRIP |
|
||||
unix.INLCR | unix.IGNCR | unix.ICRNL | unix.IXON)
|
||||
raw.Oflag &^= unix.OPOST
|
||||
raw.Lflag &^= (unix.ECHO | unix.ECHONL | unix.ICANON | unix.ISIG |
|
||||
unix.IEXTEN)
|
||||
raw.Cflag &^= (unix.CSIZE | unix.PARENB)
|
||||
raw.Cflag |= unix.CS8
|
||||
|
||||
// This is setup for blocking reads. In the past we attempted to
|
||||
// use non-blocking reads, but now a separate input loop and timer
|
||||
// copes with the problems we had on some systems (BSD/Darwin)
|
||||
// where close hung forever.
|
||||
newtios.Cc[syscall.VMIN] = 1
|
||||
newtios.Cc[syscall.VTIME] = 0
|
||||
raw.Cc[syscall.VMIN] = 1
|
||||
raw.Cc[syscall.VTIME] = 0
|
||||
|
||||
tios = uintptr(unsafe.Pointer(&newtios))
|
||||
|
||||
// Well this kind of sucks, because we don't have TCSETSF, but only
|
||||
// TCSETS. This can leave some output unflushed.
|
||||
ioc = uintptr(syscall.TCSETS)
|
||||
if _, _, e1 := syscall.Syscall6(syscall.SYS_IOCTL, fd, ioc, tios, 0, 0, 0); e1 != 0 {
|
||||
e = e1
|
||||
e = unix.IoctlSetTermios(int(t.out.Fd()), unix.TCSETS, raw)
|
||||
if e != nil {
|
||||
goto failed
|
||||
}
|
||||
|
||||
|
@ -104,14 +182,11 @@ func (t *tScreen) termioFini() {
|
|||
|
||||
<-t.indoneq
|
||||
|
||||
if t.out != nil {
|
||||
fd := uintptr(t.out.Fd())
|
||||
// XXX: We'd really rather do TCSETSF here!
|
||||
ioc := uintptr(syscall.TCSETS)
|
||||
tios := uintptr(unsafe.Pointer(t.tiosp))
|
||||
syscall.Syscall6(syscall.SYS_IOCTL, fd, ioc, tios, 0, 0, 0)
|
||||
if t.out != nil && t.tiosp != nil {
|
||||
unix.IoctlSetTermios(int(t.out.Fd()), unix.TCSETSF, t.tiosp.tio)
|
||||
t.out.Close()
|
||||
}
|
||||
|
||||
if t.in != nil {
|
||||
t.in.Close()
|
||||
}
|
||||
|
|
|
@ -110,14 +110,12 @@ func (t *tScreen) termioInit() error {
|
|||
goto failed
|
||||
}
|
||||
|
||||
t.tiosp = &termiosPrivate{}
|
||||
|
||||
tio, e = unix.IoctlGetTermios(int(t.out.Fd()), unix.TCGETS)
|
||||
if e != nil {
|
||||
goto failed
|
||||
}
|
||||
|
||||
t.tiosp.tio = tio
|
||||
t.tiosp = &termiosPrivate{tio: tio}
|
||||
t.baud = getbaud(tio)
|
||||
|
||||
// make a local copy, to make it raw
|
||||
|
|
Loading…
Reference in New Issue