tinybox

Owner: IIIlllIIIllI URL: git@github.com:nyangkosense/tinybox.git

using posix compliant consts and ops

Commit fff7665fa8f4232ef9bf9be7da269c0f937b5ab9 by SM <seb.michalk@gmail.com> on 2025-09-24 10:09:25 +0200
diff --git a/tinybox/tb.go b/tinybox/tb.go
index 9938611..4010303 100644
--- a/tinybox/tb.go
+++ b/tinybox/tb.go
@@ -39,18 +39,22 @@ const (
 	TCGETS     = 0x5401
 	TCSETS     = 0x5402
 	TIOCGWINSZ = 0x5413
-	TCSANOW    = 0
-	ICANON     = 0x00000002
-	ECHO       = 0x00000008
-	ISIG       = 0x00000001
-	ICRNL      = 0x00000100
-	INPCK      = 0x00000010
-	ISTRIP     = 0x00000020
-	IXON       = 0x00000400
-	OPOST      = 0x00000001
-	CS8        = 0x00000030
+	ICANON     = 0x2
+	ECHO       = 0x8
+	ISIG       = 0x1
+	IEXTEN     = 0x8000
+	BRKINT     = 0x2
+	ICRNL      = 0x100
+	INPCK      = 0x10
+	ISTRIP     = 0x20
+	IXON       = 0x400
+	OPOST      = 0x1
+	CS8        = 0x30
 	VMIN       = 6
 	VTIME      = 5
+	F_GETFL    = 3
+	F_SETFL    = 4
+	O_NONBLOCK = 0x800
 
 	ESC = "\033"
 	BEL = "\x07"
@@ -109,14 +113,14 @@ var (
 )
 
 type termios struct {
-	Iflag  uint32
-	Oflag  uint32
-	Cflag  uint32
-	Lflag  uint32
-	Line   uint8
-	Cc     [32]uint8
-	Ispeed uint32
-	Ospeed uint32
+	Iflag, Oflag, Cflag, Lflag uint32
+	Line                       uint8
+	Cc                         [32]uint8
+	Ispeed, Ospeed             uint32
+}
+
+type winsize struct {
+	Row, Col, Xpixel, Ypixel uint16
 }
 
 type Cell struct {
@@ -242,62 +246,88 @@ var term Terminal
 
 func getTermios(fd int) (*termios, error) {
 	var t termios
-	_, _, errno := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), TCGETS, uintptr(unsafe.Pointer(&t)))
-	if errno != 0 {
-		return nil, errno
+	_, _, e := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), TCGETS, uintptr(unsafe.Pointer(&t)))
+	if e != 0 {
+		return nil, e
 	}
 	return &t, nil
 }
 
 func setTermios(fd int, t *termios) error {
-	_, _, errno := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), TCSETS, uintptr(unsafe.Pointer(t)))
-	if errno != 0 {
-		return errno
+	_, _, e := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), TCSETS, uintptr(unsafe.Pointer(t)))
+	if e != 0 {
+		return e
 	}
 	return nil
 }
 
 func enableRawMode() error {
-	orig, err := getTermios(syscall.Stdin)
+	orig, err := getTermios(int(syscall.Stdin))
 	if err != nil {
 		return err
 	}
 	term.origTermios = *orig
-
 	raw := *orig
-	raw.Lflag &= ^uint32(ECHO | ICANON | ISIG)
-	raw.Iflag &= ^uint32(ICRNL | INPCK | ISTRIP | IXON)
+	raw.Lflag &= ^uint32(ECHO | ICANON | ISIG | IEXTEN)
+	raw.Iflag &= ^uint32(BRKINT | ICRNL | INPCK | ISTRIP | IXON)
 	raw.Oflag &= ^uint32(OPOST)
 	raw.Cflag |= CS8
 	raw.Cc[VMIN] = 1
 	raw.Cc[VTIME] = 0
-
-	return setTermios(syscall.Stdin, &raw)
+	return setTermios(int(syscall.Stdin), &raw)
 }
 
 func disableRawMode() error {
-	return setTermios(syscall.Stdin, &term.origTermios)
+	return setTermios(int(syscall.Stdin), &term.origTermios)
 }
 
-type winsize struct {
-	Row    uint16
-	Col    uint16
-	Xpixel uint16
-	Ypixel uint16
+func queryTermSize() (int, int, error) {
+	writeString("\033[999;999H\033[6n")
+
+	var buf [32]byte
+	fd := int(syscall.Stdin)
+
+	fdSet := &syscall.FdSet{}
+	fdSet.Bits[fd/64] |= 1 << (uint(fd) % 64)
+	tv := syscall.Timeval{Sec: 1, Usec: 0}
+
+	n, err := syscall.Select(fd+1, fdSet, nil, nil, &tv)
+	if err != nil || n == 0 {
+		return 80, 24, fmt.Errorf("terminal size query timeout")
+	}
+
+	n, err = syscall.Read(syscall.Stdin, buf[:])
+	if err != nil || n < 6 {
+		return 80, 24, fmt.Errorf("failed to read terminal response")
+	}
+
+	response := string(buf[:n])
+	if len(response) >= 6 && response[0] == '\x1b' && response[1] == '[' {
+		var row, col int
+		if _, err := fmt.Sscanf(response[2:], "%d;%dR", &row, &col); err == nil {
+			return col, row, nil
+		}
+	}
+	return 80, 24, nil
 }
 
-func getTerminalSize() (int, int, error) {
+func getTermSize() (int, int, error) {
+	cols, _ := strconv.Atoi(os.Getenv("COLUMNS"))
+	lines, _ := strconv.Atoi(os.Getenv("LINES"))
+	if cols > 0 && lines > 0 {
+		return cols, lines, nil
+	}
 	var ws winsize
-	_, _, errno := syscall.Syscall(syscall.SYS_IOCTL, uintptr(syscall.Stdout), TIOCGWINSZ, uintptr(unsafe.Pointer(&ws)))
-	if errno != 0 {
-		return 0, 0, errno
+	_, _, e := syscall.Syscall(syscall.SYS_IOCTL, uintptr(syscall.Stdout), TIOCGWINSZ, uintptr(unsafe.Pointer(&ws)))
+	if e == 0 {
+		return int(ws.Col), int(ws.Row), nil
 	}
-	return int(ws.Col), int(ws.Row), nil
+	return queryTermSize()
 }
 
 func handleSigwinch() {
 	for range term.sigwinchCh {
-		width, height, err := getTerminalSize()
+		width, height, err := getTermSize()
 		if err == nil && (width != term.width || height != term.height) {
 			term.width = width
 			term.height = height
@@ -337,7 +367,7 @@ func Init() error {
 		return fmt.Errorf("terminal already initialized")
 	}
 
-	width, height, err := getTerminalSize()
+	width, height, err := getTermSize()
 	if err != nil {
 		return err
 	}
@@ -1134,13 +1164,9 @@ func SetInputMode(escDelay int) {
 }
 
 func FlushInput() {
-	flags, _, err := syscall.Syscall(syscall.SYS_FCNTL, uintptr(syscall.Stdin), syscall.F_GETFL, 0)
-	if err != 0 {
-		return
-	}
-
-	syscall.Syscall(syscall.SYS_FCNTL, uintptr(syscall.Stdin), syscall.F_SETFL, flags|syscall.O_NONBLOCK)
-
+	fd := int(syscall.Stdin)
+	flags, _, _ := syscall.Syscall(syscall.SYS_FCNTL, uintptr(fd), F_GETFL, 0)
+	syscall.Syscall(syscall.SYS_FCNTL, uintptr(fd), F_SETFL, flags|O_NONBLOCK)
 	var buf [1024]byte
 	for {
 		_, err := syscall.Read(syscall.Stdin, buf[:])
@@ -1148,8 +1174,7 @@ func FlushInput() {
 			break
 		}
 	}
-
-	syscall.Syscall(syscall.SYS_FCNTL, uintptr(syscall.Stdin), syscall.F_SETFL, flags)
+	syscall.Syscall(syscall.SYS_FCNTL, uintptr(fd), F_SETFL, flags)
 }
 
 func SaveBuffer() {