mirror of
				https://github.com/taigrr/wtf
				synced 2025-01-18 04:03:14 -08:00 
			
		
		
		
	
		
			
				
	
	
		
			189 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			189 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// +build solaris
 | 
						|
 | 
						|
// Copyright 2017 The TCell Authors
 | 
						|
//
 | 
						|
// Licensed under the Apache License, Version 2.0 (the "License");
 | 
						|
// you may not use file except in compliance with the License.
 | 
						|
// You may obtain a copy of the license at
 | 
						|
//
 | 
						|
//    http://www.apache.org/licenses/LICENSE-2.0
 | 
						|
//
 | 
						|
// Unless required by applicable law or agreed to in writing, software
 | 
						|
// distributed under the License is distributed on an "AS IS" BASIS,
 | 
						|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
						|
// See the License for the specific language governing permissions and
 | 
						|
// limitations under the License.
 | 
						|
 | 
						|
package tcell
 | 
						|
 | 
						|
import (
 | 
						|
	"os"
 | 
						|
	"os/signal"
 | 
						|
	"syscall"
 | 
						|
 | 
						|
	"golang.org/x/sys/unix"
 | 
						|
)
 | 
						|
 | 
						|
type termiosPrivate struct {
 | 
						|
	tio *unix.Termios
 | 
						|
}
 | 
						|
 | 
						|
const (
 | 
						|
	// These are for missing CBAUDEXT and CIBAUDEXT.
 | 
						|
	// The values are fixed for Solaris and illumos, and cannot ever
 | 
						|
	// change without breaking applications.
 | 
						|
	cBaudExt  = 0x200000
 | 
						|
	ciBaudExt = 0x400000
 | 
						|
)
 | 
						|
 | 
						|
// getbaud is sort of cfgetospeed, but in Go.
 | 
						|
func getbaud(tios *unix.Termios) int {
 | 
						|
	// First we mask off the rate by looking at the Cflag.
 | 
						|
	bval := tios.Cflag & unix.CBAUD
 | 
						|
	if (tios.Cflag & cBaudExt) != 0 {
 | 
						|
		bval += unix.CBAUD + 1
 | 
						|
	}
 | 
						|
 | 
						|
	// This gives us the appropriate BXXX value, so convert
 | 
						|
	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.B76800:
 | 
						|
		return 76800
 | 
						|
	case unix.B115200:
 | 
						|
		return 115200
 | 
						|
	case unix.B153600:
 | 
						|
		return 153600
 | 
						|
	case unix.B230400:
 | 
						|
		return 230400
 | 
						|
	case unix.B307200:
 | 
						|
		return 307200
 | 
						|
	case unix.B460800:
 | 
						|
		return 460800
 | 
						|
	case unix.B921600:
 | 
						|
		return 921600
 | 
						|
	}
 | 
						|
	return 0
 | 
						|
}
 | 
						|
 | 
						|
func (t *tScreen) termioInit() error {
 | 
						|
	var e error
 | 
						|
	var raw *unix.Termios
 | 
						|
	var tio *unix.Termios
 | 
						|
 | 
						|
	if t.in, e = os.OpenFile("/dev/tty", os.O_RDONLY, 0); e != nil {
 | 
						|
		goto failed
 | 
						|
	}
 | 
						|
	if t.out, e = os.OpenFile("/dev/tty", os.O_WRONLY, 0); e != nil {
 | 
						|
		goto failed
 | 
						|
	}
 | 
						|
 | 
						|
	tio, e = unix.IoctlGetTermios(int(t.out.Fd()), unix.TCGETS)
 | 
						|
	if e != nil {
 | 
						|
		goto failed
 | 
						|
	}
 | 
						|
 | 
						|
	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.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.
 | 
						|
	raw.Cc[unix.VMIN] = 1
 | 
						|
	raw.Cc[unix.VTIME] = 0
 | 
						|
 | 
						|
	e = unix.IoctlSetTermios(int(t.out.Fd()), unix.TCSETS, raw)
 | 
						|
	if e != nil {
 | 
						|
		goto failed
 | 
						|
	}
 | 
						|
 | 
						|
	signal.Notify(t.sigwinch, syscall.SIGWINCH)
 | 
						|
 | 
						|
	if w, h, e := t.getWinSize(); e == nil && w != 0 && h != 0 {
 | 
						|
		t.cells.Resize(w, h)
 | 
						|
	}
 | 
						|
 | 
						|
	return nil
 | 
						|
 | 
						|
failed:
 | 
						|
	if t.in != nil {
 | 
						|
		t.in.Close()
 | 
						|
	}
 | 
						|
	if t.out != nil {
 | 
						|
		t.out.Close()
 | 
						|
	}
 | 
						|
	return e
 | 
						|
}
 | 
						|
 | 
						|
func (t *tScreen) termioFini() {
 | 
						|
 | 
						|
	signal.Stop(t.sigwinch)
 | 
						|
 | 
						|
	<-t.indoneq
 | 
						|
 | 
						|
	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()
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func (t *tScreen) getWinSize() (int, int, error) {
 | 
						|
	wsz, err := unix.IoctlGetWinsize(int(t.out.Fd()), unix.TIOCGWINSZ)
 | 
						|
	if err != nil {
 | 
						|
		return -1, -1, err
 | 
						|
	}
 | 
						|
	return int(wsz.Col), int(wsz.Row), nil
 | 
						|
}
 |