func (s *cScreen) writeString(x, y int, style Style, ch []uint16) { // we assume the caller has hidden the cursor if len(ch) == 0 { return } nw := uint32(len(ch)) procSetConsoleTextAttribute.Call( uintptr(s.out), uintptr(mapStyle(style))) s.setCursorPos(x, y) syscall.WriteConsole(s.out, &ch[0], nw, &nw, nil) }
// writeConsole writes len(b) bytes to the console File. // It returns the number of bytes written and an error, if any. func (f *File) writeConsole(b []byte) (n int, err error) { n = len(b) runes := make([]rune, 0, 256) if len(f.lastbits) > 0 { b = append(f.lastbits, b...) f.lastbits = nil } for len(b) >= utf8.UTFMax || utf8.FullRune(b) { r, l := utf8.DecodeRune(b) runes = append(runes, r) b = b[l:] } if len(b) > 0 { f.lastbits = make([]byte, len(b)) copy(f.lastbits, b) } // syscall.WriteConsole seems to fail, if given large buffer. // So limit the buffer to 16000 characters. This number was // discovered by experimenting with syscall.WriteConsole. const maxWrite = 16000 for len(runes) > 0 { m := len(runes) if m > maxWrite { m = maxWrite } chunk := runes[:m] runes = runes[m:] uint16s := utf16.Encode(chunk) for len(uint16s) > 0 { var written uint32 err = syscall.WriteConsole(f.fd, &uint16s[0], uint32(len(uint16s)), &written, nil) if err != nil { return 0, nil } uint16s = uint16s[written:] } } return n, nil }