1// +build darwin dragonfly freebsd linux,!appengine netbsd openbsd solaris
2
3package readline
4
5import (
6	"io"
7	"os"
8	"os/signal"
9	"sync"
10	"syscall"
11)
12
13type winsize struct {
14	Row    uint16
15	Col    uint16
16	Xpixel uint16
17	Ypixel uint16
18}
19
20// SuspendMe use to send suspend signal to myself, when we in the raw mode.
21// For OSX it need to send to parent's pid
22// For Linux it need to send to myself
23func SuspendMe() {
24	p, _ := os.FindProcess(os.Getppid())
25	p.Signal(syscall.SIGTSTP)
26	p, _ = os.FindProcess(os.Getpid())
27	p.Signal(syscall.SIGTSTP)
28}
29
30// get width of the terminal
31func getWidth(stdoutFd int) int {
32	cols, _, err := GetSize(stdoutFd)
33	if err != nil {
34		return -1
35	}
36	return cols
37}
38
39func GetScreenWidth() int {
40	w := getWidth(syscall.Stdout)
41	if w < 0 {
42		w = getWidth(syscall.Stderr)
43	}
44	return w
45}
46
47// ClearScreen clears the console screen
48func ClearScreen(w io.Writer) (int, error) {
49	return w.Write([]byte("\033[H"))
50}
51
52func DefaultIsTerminal() bool {
53	return IsTerminal(syscall.Stdin) && (IsTerminal(syscall.Stdout) || IsTerminal(syscall.Stderr))
54}
55
56func GetStdin() int {
57	return syscall.Stdin
58}
59
60// -----------------------------------------------------------------------------
61
62var (
63	widthChange         sync.Once
64	widthChangeCallback func()
65)
66
67func DefaultOnWidthChanged(f func()) {
68	widthChangeCallback = f
69	widthChange.Do(func() {
70		ch := make(chan os.Signal, 1)
71		signal.Notify(ch, syscall.SIGWINCH)
72
73		go func() {
74			for {
75				_, ok := <-ch
76				if !ok {
77					break
78				}
79				widthChangeCallback()
80			}
81		}()
82	})
83}
84