/** @file Implementation of translation upon VT-UTF8. Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include "Terminal.h" /** Translate all VT-UTF8 characters in the Raw FIFI into unicode characters, and insert them into Unicode FIFO. @param TerminalDevice The terminal device. **/ VOID VTUTF8RawDataToUnicode ( IN TERMINAL_DEV *TerminalDevice ) { UTF8_CHAR Utf8Char; UINT8 ValidBytes; UINT16 UnicodeChar; ValidBytes = 0; // // pop the raw data out from the raw fifo, // and translate it into unicode, then push // the unicode into unicode fifo, until the raw fifo is empty. // while (!IsRawFiFoEmpty (TerminalDevice) && !IsUnicodeFiFoFull (TerminalDevice)) { GetOneValidUtf8Char (TerminalDevice, &Utf8Char, &ValidBytes); if (ValidBytes < 1 || ValidBytes > 3) { continue; } Utf8ToUnicode (Utf8Char, ValidBytes, (CHAR16 *) &UnicodeChar); UnicodeFiFoInsertOneKey (TerminalDevice, UnicodeChar); } } /** Get one valid VT-UTF8 characters set from Raw Data FIFO. @param Utf8Device The terminal device. @param Utf8Char Returned valid VT-UTF8 characters set. @param ValidBytes The count of returned VT-VTF8 characters. If ValidBytes is zero, no valid VT-UTF8 returned. **/ VOID GetOneValidUtf8Char ( IN TERMINAL_DEV *Utf8Device, OUT UTF8_CHAR *Utf8Char, OUT UINT8 *ValidBytes ) { UINT8 Temp; UINT8 Index; BOOLEAN FetchFlag; Temp = 0; Index = 0; FetchFlag = TRUE; // // if no valid Utf8 char is found in the RawFiFo, // then *ValidBytes will be zero. // *ValidBytes = 0; while (!IsRawFiFoEmpty (Utf8Device)) { RawFiFoRemoveOneKey (Utf8Device, &Temp); switch (*ValidBytes) { case 0: if ((Temp & 0x80) == 0) { // // one-byte utf8 char // *ValidBytes = 1; Utf8Char->Utf8_1 = Temp; FetchFlag = FALSE; } else if ((Temp & 0xe0) == 0xc0) { // // two-byte utf8 char // *ValidBytes = 2; Utf8Char->Utf8_2[1] = Temp; } else if ((Temp & 0xf0) == 0xe0) { // // three-byte utf8 char // *ValidBytes = 3; Utf8Char->Utf8_3[2] = Temp; Index++; } else { // // reset *ValidBytes to zero, let valid utf8 char search restart // *ValidBytes = 0; } break; case 2: // // two-byte utf8 char go on // if ((Temp & 0xc0) == 0x80) { Utf8Char->Utf8_2[0] = Temp; FetchFlag = FALSE; } else { *ValidBytes = 0; } break; case 3: // // three-byte utf8 char go on // if ((Temp & 0xc0) == 0x80) { if (Index == 1) { Utf8Char->Utf8_3[1] = Temp; Index++; } else { Utf8Char->Utf8_3[0] = Temp; FetchFlag = FALSE; } } else { // // reset *ValidBytes and Index to zero, let valid utf8 char search restart // *ValidBytes = 0; Index = 0; } break; default: break; } if (!FetchFlag) { break; } } return ; } /** Translate VT-UTF8 characters into one Unicode character. UTF8 Encoding Table Bits per Character | Unicode Character Range | Unicode Binary Encoding | UTF8 Binary Encoding 0-7 | 0x0000 - 0x007F | 00000000 0xxxxxxx | 0xxxxxxx 8-11 | 0x0080 - 0x07FF | 00000xxx xxxxxxxx | 110xxxxx 10xxxxxx 12-16 | 0x0800 - 0xFFFF | xxxxxxxx xxxxxxxx | 1110xxxx 10xxxxxx 10xxxxxx @param Utf8Char VT-UTF8 character set needs translating. @param ValidBytes The count of valid VT-UTF8 characters. @param UnicodeChar Returned unicode character. **/ VOID Utf8ToUnicode ( IN UTF8_CHAR Utf8Char, IN UINT8 ValidBytes, OUT CHAR16 *UnicodeChar ) { UINT8 UnicodeByte0; UINT8 UnicodeByte1; UINT8 Byte0; UINT8 Byte1; UINT8 Byte2; *UnicodeChar = 0; // // translate utf8 code to unicode, in terminal standard, // up to 3 bytes utf8 code is supported. // switch (ValidBytes) { case 1: // // one-byte utf8 code // *UnicodeChar = (UINT16) Utf8Char.Utf8_1; break; case 2: // // two-byte utf8 code // Byte0 = Utf8Char.Utf8_2[0]; Byte1 = Utf8Char.Utf8_2[1]; UnicodeByte0 = (UINT8) ((Byte1 << 6) | (Byte0 & 0x3f)); UnicodeByte1 = (UINT8) ((Byte1 >> 2) & 0x07); *UnicodeChar = (UINT16) (UnicodeByte0 | (UnicodeByte1 << 8)); break; case 3: // // three-byte utf8 code // Byte0 = Utf8Char.Utf8_3[0]; Byte1 = Utf8Char.Utf8_3[1]; Byte2 = Utf8Char.Utf8_3[2]; UnicodeByte0 = (UINT8) ((Byte1 << 6) | (Byte0 & 0x3f)); UnicodeByte1 = (UINT8) ((Byte2 << 4) | ((Byte1 >> 2) & 0x0f)); *UnicodeChar = (UINT16) (UnicodeByte0 | (UnicodeByte1 << 8)); default: break; } return ; } /** Translate one Unicode character into VT-UTF8 characters. UTF8 Encoding Table Bits per Character | Unicode Character Range | Unicode Binary Encoding | UTF8 Binary Encoding 0-7 | 0x0000 - 0x007F | 00000000 0xxxxxxx | 0xxxxxxx 8-11 | 0x0080 - 0x07FF | 00000xxx xxxxxxxx | 110xxxxx 10xxxxxx 12-16 | 0x0800 - 0xFFFF | xxxxxxxx xxxxxxxx | 1110xxxx 10xxxxxx 10xxxxxx @param Unicode Unicode character need translating. @param Utf8Char Return VT-UTF8 character set. @param ValidBytes The count of valid VT-UTF8 characters. If ValidBytes is zero, no valid VT-UTF8 returned. **/ VOID UnicodeToUtf8 ( IN CHAR16 Unicode, OUT UTF8_CHAR *Utf8Char, OUT UINT8 *ValidBytes ) { UINT8 UnicodeByte0; UINT8 UnicodeByte1; // // translate unicode to utf8 code // UnicodeByte0 = (UINT8) Unicode; UnicodeByte1 = (UINT8) (Unicode >> 8); if (Unicode < 0x0080) { Utf8Char->Utf8_1 = (UINT8) (UnicodeByte0 & 0x7f); *ValidBytes = 1; } else if (Unicode < 0x0800) { // // byte sequence: high -> low // Utf8_2[0], Utf8_2[1] // Utf8Char->Utf8_2[1] = (UINT8) ((UnicodeByte0 & 0x3f) + 0x80); Utf8Char->Utf8_2[0] = (UINT8) ((((UnicodeByte1 << 2) + (UnicodeByte0 >> 6)) & 0x1f) + 0xc0); *ValidBytes = 2; } else { // // byte sequence: high -> low // Utf8_3[0], Utf8_3[1], Utf8_3[2] // Utf8Char->Utf8_3[2] = (UINT8) ((UnicodeByte0 & 0x3f) + 0x80); Utf8Char->Utf8_3[1] = (UINT8) ((((UnicodeByte1 << 2) + (UnicodeByte0 >> 6)) & 0x3f) + 0x80); Utf8Char->Utf8_3[0] = (UINT8) (((UnicodeByte1 >> 4) & 0x0f) + 0xe0); *ValidBytes = 3; } } /** Check if input string is valid VT-UTF8 string. @param TerminalDevice The terminal device. @param WString The input string. @retval EFI_SUCCESS If all input characters are valid. **/ EFI_STATUS VTUTF8TestString ( IN TERMINAL_DEV *TerminalDevice, IN CHAR16 *WString ) { // // to utf8, all kind of characters are supported. // return EFI_SUCCESS; }