/** @file | |
Implementation of translation upon VT-UTF8. | |
Copyright (c) 2006 - 2010, Intel Corporation. <BR> | |
All rights reserved. This program and the accompanying materials | |
are licensed and made available under the terms and conditions of the BSD License | |
which accompanies this distribution. The full text of the license may be found at | |
http://opensource.org/licenses/bsd-license.php | |
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, | |
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. | |
**/ | |
#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)) { | |
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; | |
} |