Example #1
0
// 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
	}
}
Example #2
0
// 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
}