// readOneUTF16FromConsole reads single character from console, // converts it into utf16 and return it to the caller. func (f *File) readOneUTF16FromConsole() (uint16, error) { var buf [1]byte mbytes := make([]byte, 0, 4) cp := getCP() for { var nmb uint32 err := readFile(f.fd, buf[:], &nmb, nil) if err != nil { return 0, err } if nmb == 0 { continue } mbytes = append(mbytes, buf[0]) // Convert from 8-bit console encoding to UTF16. // MultiByteToWideChar defaults to Unicode NFC form, which is the expected one. nwc, err := windows.MultiByteToWideChar(cp, windows.MB_ERR_INVALID_CHARS, &mbytes[0], int32(len(mbytes)), nil, 0) if err != nil { if err == windows.ERROR_NO_UNICODE_TRANSLATION { continue } return 0, err } if nwc != 1 { return 0, errors.New("MultiByteToWideChar returns " + itoa(int(nwc)) + " characters, but only 1 expected") } var wchars [1]uint16 nwc, err = windows.MultiByteToWideChar(cp, windows.MB_ERR_INVALID_CHARS, &mbytes[0], int32(len(mbytes)), &wchars[0], nwc) if err != nil { return 0, err } return wchars[0], nil } }
// readConsole reads utf16 characters from console File, // encodes them into utf8 and stores them in buffer b. // It returns the number of utf8 bytes read and an error, if any. func (f *File) readConsole(b []byte) (n int, err error) { if len(b) == 0 { return 0, nil } if len(f.readbuf) == 0 { numBytes := len(b) // Windows can't read bytes over max of int16. if numBytes > 32767 { numBytes = 32767 } mbytes := make([]byte, numBytes) var nmb uint32 err := syscall.ReadFile(f.fd, mbytes, &nmb, nil) if err != nil { return 0, err } if nmb > 0 { var pmb *byte if len(b) > 0 { pmb = &mbytes[0] } acp, err := windows.GetACP() if err != nil { return 0, err } nwc, err := windows.MultiByteToWideChar(acp, 2, pmb, int32(nmb), nil, 0) if err != nil { return 0, err } wchars := make([]uint16, nwc) pwc := &wchars[0] nwc, err = windows.MultiByteToWideChar(acp, 2, pmb, int32(nmb), pwc, int32(nwc)) if err != nil { return 0, err } f.readbuf = utf16.Decode(wchars[:nwc]) } } for i, r := range f.readbuf { if utf8.RuneLen(r) > len(b) { f.readbuf = f.readbuf[i:] return n, nil } nr := utf8.EncodeRune(b, r) b = b[nr:] n += nr } f.readbuf = nil return n, nil }