go-ncurses/input.go

74 lines
1.8 KiB
Go

package ncurses
import (
"os"
"bufio"
"sync/atomic"
)
func bitmatch(b byte, pattern byte, length int) bool {
mask := ^(byte(1 << (8 - length)) - 1)
return (b ^ pattern) & mask == 0
}
func UTF8Listen(reader *bufio.Reader, channel chan []byte, active *atomic.Bool) {
for active.Load() {
out := make([]byte, 4)
reader.Read(out[0:1])
if out[0] == 0x1B { // Escape sequences
if reader.Buffered() != 0 {
reader.Read(out[1:2])
if out[1] == 0x5B { // CSI
out := []byte{0x1B, 0x5B}
next := [1]byte{}
for true { // TODO: safety
reader.Read(next[0:1])
if (next[0] >= 0x20) && (next[0] <= 0x3F) {
out = append(out, next[0])
} else if (next[0] >= 0x40) && (next[0] <= 0x7F) {
out = append(out, next[0])
break
} else {
break
}
}
channel<-out
}
} else {
channel <- out[0:1]
}
} else if bitmatch(out[0], 0b00000000, 1) {
channel <- out[0:1]
} else if bitmatch(out[0], 0b11000000, 3) {
if reader.Buffered() >= 1 {
reader.Read(out[1:2])
channel <- out[0:2]
}
} else if bitmatch(out[0], 0b11100000, 4) {
if reader.Buffered() >= 2 {
reader.Read(out[1:3])
channel <- out[0:3]
}
} else if bitmatch(out[0], 0b11110000, 5) {
if reader.Buffered() >= 3 {
reader.Read(out[1:4])
channel <- out[0:4]
}
}
}
}
// To cleanup, set active to false then close the channel
func UTF8Listener(buffer int, file *os.File) (chan []byte, *atomic.Bool) {
channel := make(chan []byte, buffer)
reader := bufio.NewReader(file)
active := new(atomic.Bool)
active.Store(true)
go UTF8Listen(reader, channel, active)
return channel, active
}