2024-04-23 22:10:40 -06:00
|
|
|
package ncurses
|
|
|
|
|
|
|
|
import (
|
|
|
|
"os"
|
2024-04-24 19:08:45 -06:00
|
|
|
"bufio"
|
2024-04-23 22:10:40 -06:00
|
|
|
"sync/atomic"
|
|
|
|
)
|
|
|
|
|
|
|
|
func bitmatch(b byte, pattern byte, length int) bool {
|
|
|
|
mask := ^(byte(1 << (8 - length)) - 1)
|
|
|
|
return (b ^ pattern) & mask == 0
|
|
|
|
}
|
|
|
|
|
2024-04-24 19:08:45 -06:00
|
|
|
func UTF8Listen(reader *bufio.Reader, channel chan []byte, active *atomic.Bool) {
|
2024-04-23 22:10:40 -06:00
|
|
|
for active.Load() {
|
2024-04-23 22:24:38 -06:00
|
|
|
out := make([]byte, 4)
|
2024-04-24 19:08:45 -06:00
|
|
|
|
|
|
|
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) {
|
2024-04-23 22:24:38 -06:00
|
|
|
channel <- out[0:1]
|
2024-04-24 19:08:45 -06:00
|
|
|
} 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]
|
|
|
|
}
|
2024-04-23 22:10:40 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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)
|
2024-04-24 19:08:45 -06:00
|
|
|
reader := bufio.NewReader(file)
|
2024-04-23 22:10:40 -06:00
|
|
|
active := new(atomic.Bool)
|
|
|
|
active.Store(true)
|
|
|
|
|
2024-04-24 19:08:45 -06:00
|
|
|
go UTF8Listen(reader, channel, active)
|
2024-04-23 22:10:40 -06:00
|
|
|
|
|
|
|
return channel, active
|
|
|
|
}
|