//*****************************************************************************
//
// charmap.c - Routines converting between different text codebases.
//
// Copyright (c) 2011-2020 Texas Instruments Incorporated.  All rights reserved.
// Software License Agreement
// 
// Texas Instruments (TI) is supplying this software for use solely and
// exclusively on TI's microcontroller products. The software is owned by
// TI and/or its suppliers, and is protected under applicable copyright
// laws. You may not combine this software with "viral" open-source
// software in order to form a larger program.
// 
// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
// DAMAGES, FOR ANY REASON WHATSOEVER.
// 
// This is part of revision 2.2.0.295 of the Tiva Graphics Library.
//
//*****************************************************************************

#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_types.h"
#include "driverlib/debug.h"
#include "grlib/grlib.h"

//*****************************************************************************
//
//! \addtogroup primitives_api
//! @{
//
//*****************************************************************************

//*****************************************************************************
//
// Counts the number of zeros at the start of a word.  This macro uses
// compiler-specific constructs to perform an inline insertion of the "clz"
// instruction, which counts the leading zeros directly.
//
//*****************************************************************************
#if defined(ewarm)
#include <intrinsics.h>
#define NumLeadingZeros(x)      __CLZ(x)
#endif
#if defined(codered) || defined(gcc) || defined(sourcerygxx)
#define NumLeadingZeros(x) __extension__                                      \
        ({                                                                    \
            register uint32_t __ret, __inp = x;                               \
            __asm__("clz %0, %1" : "=r" (__ret) : "r" (__inp));               \
            __ret;                                                            \
        })
#endif
#if defined(rvmdk) || defined(__ARMCC_VERSION)
#define NumLeadingZeros(x)      __clz(x)
#endif
#if defined(ccs)
//
// The CCS/TI compiler _norm intrinsic function will generate an inline CLZ
// instruction.
//
#define NumLeadingZeros(x)      _norm(x)
#endif

//*****************************************************************************
//
// An array containing Unicode mappings for ISO8859-2 codes from 0xA1 and above.
//
//*****************************************************************************
const uint16_t g_pui16ISO8859_2_Unicode[] =
{
    0x0104, 0x02D8, 0x0141, 0x00A4, 0x013D, 0x015A, 0x00A7, 0x00A8,
    0x0160, 0x015E, 0x0164, 0x0179, 0x00AD, 0x017D, 0x017B, 0x00B0,
    0x0105, 0x02DB, 0x0142, 0x00B4, 0x013E, 0x015B, 0x02C7, 0x00B8,
    0x0161, 0x015F, 0x0165, 0x017A, 0x02DD, 0x017E, 0x017C, 0x0154,
    0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0139, 0x0106, 0x00C7, 0x010C,
    0x00C9, 0x0118, 0x00CB, 0x011A, 0x00CD, 0x00CE, 0x010E, 0x0110,
    0x0143, 0x0147, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x00D7, 0x0158,
    0x016E, 0x00DA, 0x0170, 0x00DC, 0x00DD, 0x0162, 0x00DF, 0x0155,
    0x00E1, 0x00E2, 0x0103, 0x00E4, 0x013A, 0x0107, 0x00E7, 0x010D,
    0x00E9, 0x0119, 0x00EB, 0x011B, 0x00ED, 0x00EE, 0x010F, 0x0111,
    0x0144, 0x0148, 0x00F3, 0x00F4, 0x0151, 0x00F6, 0x00F7, 0x0159,
    0x016F, 0x00FA, 0x0171, 0x00FC, 0x00FD, 0x0163, 0x02D9
};

//*****************************************************************************
//
// An array containing Unicode mappings for ISO8859-3 codes from 0xA1 and above.
//
//*****************************************************************************
const uint16_t g_pui16ISO8859_3_Unicode[] =
{
    0x0126, 0x02D8, 0x00A3, 0x00A4, 0x0000, 0x0124, 0x00A7, 0x00A8,
    0x0130, 0x015E, 0x011E, 0x0134, 0x00AD, 0x0000, 0x017B, 0x00B0,
    0x0127, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x0125, 0x00B7, 0x00B8,
    0x0131, 0x015F, 0x011F, 0x0135, 0x00BD, 0x0000, 0x017C, 0x00C0,
    0x00C1, 0x00C2, 0x0000, 0x00C4, 0x010A, 0x0108, 0x00C7, 0x00C8,
    0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, 0x0000,
    0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x0120, 0x00D6, 0x00D7, 0x011C,
    0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x016C, 0x015C, 0x00DF, 0x00E0,
    0x00E1, 0x00E2, 0x0000, 0x00E4, 0x010B, 0x0109, 0x00E7, 0x00E8,
    0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, 0x0000,
    0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x0121, 0x00F6, 0x00F7, 0x011D,
    0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x016D, 0x015D, 0x02D9
};

//*****************************************************************************
//
// An array containing Unicode mappings for ISO8859-4 codes from 0xA1 and above.
//
//*****************************************************************************
const uint16_t g_pui16ISO8859_4_Unicode[] =
{
    0x0104, 0x0138, 0x0156, 0x00A4, 0x0128, 0x013B, 0x00A7, 0x00A8,
    0x0160, 0x0112, 0x0122, 0x0166, 0x00AD, 0x017D, 0x00AF, 0x00B0,
    0x0105, 0x02DB, 0x0157, 0x00B4, 0x0129, 0x013C, 0x02C7, 0x00B8,
    0x0161, 0x0113, 0x0123, 0x0167, 0x014A, 0x017E, 0x014B, 0x0100,
    0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x012E, 0x010C,
    0x00C9, 0x0118, 0x00CB, 0x0116, 0x00CD, 0x00CE, 0x012A, 0x0110,
    0x0145, 0x014C, 0x0136, 0x00D4, 0x00D5, 0x00D6, 0x00D7, 0x00D8,
    0x0172, 0x00DA, 0x00DB, 0x00DC, 0x0168, 0x016A, 0x00DF, 0x0101,
    0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x012F, 0x010D,
    0x00E9, 0x0119, 0x00EB, 0x0117, 0x00ED, 0x00EE, 0x012B, 0x0111,
    0x0146, 0x014D, 0x0137, 0x00F4, 0x00F5, 0x00F6, 0x00F7, 0x00F8,
    0x0173, 0x00FA, 0x00FB, 0x00FC, 0x0169, 0x016B, 0x02D9
};

//*****************************************************************************
//
// An array containing Unicode mappings for ISO8859-7 codes from 0xA1 to 0xBD
//
//*****************************************************************************
const uint16_t g_pui16ISO8859_7_Unicode[] =
{
    0x2018, 0x2019, 0x00A3, 0x20AC, 0x20AF, 0x00A6, 0x00A7, 0x00A8,
    0x00A9, 0x037A, 0x00AB, 0x00AC, 0x00AD, 0x0000, 0x2015, 0x00B0,
    0x00B1, 0x00B2, 0x00B3, 0x0384, 0x0385, 0x0386, 0x00B7, 0x0388,
    0x0389, 0x038A, 0x00BB, 0x038C, 0x00BD
};

//*****************************************************************************
//
// An array containing Unicode mappings for ISO8859-10 codes from 0xA1 and
// above.
//
//*****************************************************************************
const uint16_t g_pui16ISO8859_10_Unicode[] =
{
    0x0104, 0x0112, 0x0122, 0x012A, 0x0128, 0x0136, 0x00A7, 0x013B,
    0x0110, 0x0160, 0x0166, 0x017D, 0x00AD, 0x016A, 0x014A, 0x00B0,
    0x0105, 0x0113, 0x0123, 0x012B, 0x0129, 0x0137, 0x00B7, 0x013C,
    0x0111, 0x0161, 0x0167, 0x017E, 0x2015, 0x016B, 0x014B, 0x0100,
    0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x012E, 0x010C,
    0x00C9, 0x0118, 0x00CB, 0x0116, 0x00CD, 0x00CE, 0x00CF, 0x00D0,
    0x0145, 0x014C, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x0168, 0x00D8,
    0x0172, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF, 0x0101,
    0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x012F, 0x010D,
    0x00E9, 0x0119, 0x00EB, 0x0117, 0x00ED, 0x00EE, 0x00EF, 0x00F0,
    0x0146, 0x014D, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x0169, 0x00F8,
    0x0173, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x0138
};

//*****************************************************************************
//
// An array containing Unicode mappings for ISO8859-13 codes from 0xA1 and
// above.
//
//*****************************************************************************
const uint16_t g_pui16ISO8859_13_Unicode[] =
{
    0x201D, 0x00A2, 0x00A3, 0x00A4, 0x201E, 0x00A6, 0x00A7, 0x00D8,
    0x00A9, 0x0156, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00C6, 0x00B0,
    0x00B1, 0x00B2, 0x00B3, 0x201C, 0x00B5, 0x00B6, 0x00B7, 0x00F8,
    0x00B9, 0x0157, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00E6, 0x0104,
    0x012E, 0x0100, 0x0106, 0x00C4, 0x00C5, 0x0118, 0x0112, 0x010C,
    0x00C9, 0x0179, 0x0116, 0x0122, 0x0136, 0x012A, 0x013B, 0x0160,
    0x0143, 0x0145, 0x00D3, 0x014C, 0x00D5, 0x00D6, 0x00D7, 0x0172,
    0x0141, 0x015A, 0x016A, 0x00DC, 0x017B, 0x017D, 0x00DF, 0x0105,
    0x012F, 0x0101, 0x0107, 0x00E4, 0x00E5, 0x0119, 0x0113, 0x010D,
    0x00E9, 0x017A, 0x0117, 0x0123, 0x0137, 0x012B, 0x013C, 0x0161,
    0x0144, 0x0146, 0x00F3, 0x014D, 0x00F5, 0x00F6, 0x00F7, 0x0173,
    0x0142, 0x015B, 0x016B, 0x00FC, 0x017C, 0x017E, 0x2019
};

//*****************************************************************************
//
// An array containing Unicode mappings for ISO8859-14 codes from 0xA1 to 0xBF.
//
//*****************************************************************************
const uint16_t g_pui16ISO8859_14_Unicode[] =
{
    0x1E02, 0x1E03, 0x00A3, 0x010A, 0x010B, 0x1E0A, 0x00A7, 0x1E80,
    0x00A9, 0x1E82, 0x1E0B, 0x1EF2, 0x00AD, 0x00AE, 0x0178, 0x1E1E,
    0x1E1F, 0x0120, 0x0121, 0x1E40, 0x1E41, 0x00B6, 0x1E56, 0x1E81,
    0x1E57, 0x1E83, 0x1E60, 0x1EF3, 0x1E84, 0x1E85, 0x1E61
};

//*****************************************************************************
//
// An array containing Unicode mappings for ISO8859-16 codes from 0xA1 and
// above.
//
//*****************************************************************************
const uint16_t g_pui16ISO8859_16_Unicode[] =
{
    0x0104, 0x0105, 0x0141, 0x20AC, 0x201E, 0x0160, 0x00A7, 0x0161,
    0x00A9, 0x0218, 0x00AB, 0x0179, 0x00AD, 0x017A, 0x017B, 0x00B0,
    0x00B1, 0x010C, 0x0142, 0x017D, 0x201D, 0x00B6, 0x00B7, 0x017E,
    0x010D, 0x0219, 0x00BB, 0x0152, 0x0153, 0x0178, 0x017C, 0x00C0,
    0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0106, 0x00C6, 0x00C7, 0x00C8,
    0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, 0x0110,
    0x0143, 0x00D2, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x015A, 0x0170,
    0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x0118, 0x021A, 0x00DF, 0x00E0,
    0x00E1, 0x00E2, 0x0103, 0x00E4, 0x0107, 0x00E6, 0x00E7, 0x00E8,
    0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, 0x0111,
    0x0144, 0x00F2, 0x00F3, 0x00F4, 0x0151, 0x00F6, 0x015B, 0x0171,
    0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x0119, 0x021B, 0x00FF
};

//*****************************************************************************
//
// An array containing Unicode mappings for Windows-1250 codes from 0x80 to
// 0xFF.
//
//*****************************************************************************
const uint16_t g_pui16WIN1250_Unicode[] =
{
    0x20AC,      0, 0x201A,      0, 0x201E, 0x2026, 0x2020, 0x2021,
         0, 0x2030, 0x0160, 0x2039, 0x015A, 0x0164, 0x017D, 0x0179,
         0, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
         0, 0x2122, 0x0161, 0x203A, 0x015B, 0x0165, 0x017E, 0x017A,
    0x00A0, 0x02C7, 0x02D8, 0x0141, 0x00A4, 0x0104, 0x00A6, 0x00A7,
    0x00A8, 0x00A9, 0x015E, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x017B,
    0x00B0, 0x00B1, 0x02DB, 0x0142, 0x00B4, 0x00B5, 0x00B6, 0x00B7,
    0x00B8, 0x0105, 0x015F, 0x00BB, 0x013D, 0x02DD, 0x013E, 0x017C,
    0x0154, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0139, 0x0106, 0x00C7,
    0x010C, 0x00C9, 0x0118, 0x00CB, 0x011A, 0x00CD, 0x00CE, 0x010E,
    0x0110, 0x0143, 0x0147, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x00D7,
    0x0158, 0x016E, 0x00DA, 0x0170, 0x00DC, 0x00DD, 0x0162, 0x00DF,
    0x0155, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x013A, 0x0107, 0x00E7,
    0x010D, 0x00E9, 0x0119, 0x00EB, 0x011B, 0x00ED, 0x00EE, 0x010F,
    0x0111, 0x0144, 0x0148, 0x00F3, 0x00F4, 0x0151, 0x00F6, 0x00F7,
    0x0159, 0x016F, 0x00FA, 0x0171, 0x00FC, 0x00FD, 0x0163, 0x02D9
};

//*****************************************************************************
//
// An array containing Unicode mappings for Windows-1251 codes from 0x80 to
// 0xBF.  Codes from 0xC0 to 0xFF calculate as code + 0x0350.
//
//*****************************************************************************
const uint16_t g_pui16WIN1251_Unicode[] =
{
    0x0402, 0x0403, 0x201A, 0x0453, 0x201E, 0x2026, 0x2020, 0x2021,
    0x20AC, 0x2030, 0x0409, 0x2039, 0x040A, 0x040C, 0x040B, 0x040F,
    0x0452, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
    0x0020, 0x2122, 0x0459, 0x203A, 0x045A, 0x045C, 0x045B, 0x045F,
    0x00A0, 0x040E, 0x045E, 0x0408, 0x00A4, 0x0490, 0x00A6, 0x00A7,
    0x0401, 0x00A9, 0x0404, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x0407,
    0x00B0, 0x00B1, 0x0406, 0x0456, 0x0491, 0x00B5, 0x00B6, 0x00B7,
    0x0451, 0x2116, 0x0454, 0x00BB, 0x0458, 0x0405, 0x0455, 0x0457
};

//*****************************************************************************
//
// An array containing Unicode mappings for Windows-1252 codes from 0x80 to
// 0x9F.  All codes outside this range map directly the same Unicode codepoint.
//
//*****************************************************************************
const uint16_t g_pui16WIN1252_Unicode[] =
{
    0x20AC,      0, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
    0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0,      0x017D, 0,
    0,      0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
    0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0,      0x017E, 0x0178,
};

//*****************************************************************************
//
// An array containing Unicode mappings for Windows-1253 codes from 0x80 to
// 0xBF.  All codes below 0x80 map map directly the same Unicode codepoint.
// Codes from 0xC0 to 0xFF calculate as code + 0x02D0.
//
//*****************************************************************************
const uint16_t g_pui16WIN1253_Unicode[] =
{
    0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397,
    0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F,
    0x03A0, 0x03A1,      0, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7,
    0x03A8, 0x03A9, 0x03AA, 0x03AB, 0x03AC, 0x03AD, 0x03AE, 0x03AF,
    0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7,
    0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,
    0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7,
    0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE,      0,
};

//*****************************************************************************
//
// An array containing Unicode mappings for Windows-1254 codes from 0x80 to
// 0x9F.  All codes outside this range are compatible with ISO8859-9.
//
//*****************************************************************************
const uint16_t g_pui16WIN1254_Unicode[] =
{
    0x20AC,      0, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
    0x02C6, 0x2030, 0x0160, 0x2039, 0x0152,      0,      0,      0,
         0, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
    0x02DC, 0x2122, 0x0161, 0x203A, 0x0153,      0,      0, 0x0178
};

//*****************************************************************************
//
//! Maps an ISO8859-1 encoded character to its Unicode equivalent.
//!
//! \param pcSrcChar is a pointer to a string containing ISO8859-1 encoded
//!        text.
//! \param ui32Count is the number of bytes in the buffer pointed to by
//!        pcSrcChar.
//! \param pui32Skip points to storage that will be written with the number of
//!        bytes to skip in pcSrcChar to get to the next character in the
//!        buffer.
//!
//! This function may be passed to GrCodepageMapTableSet() in a tCodePointMap
//! structure to map source text in ISO8859-1 format into 32 bit Unicode
//! typically used by wide character fonts.  This conversion is trivial since
//! the bottom 256 characters in Unicode are the ISO8859-1 characters and since
//! ISO8859-1 is not a variable length encoding (every character is exactly 1
//! byte).
//!
//! See http://unicode.org/Public/MAPPINGS/ISO8859/8859-1.TXT for more
//! information.
//!
//! \return Returns the Unicode character code for the first character in the
//! pcSrcChar string passed.
//
//*****************************************************************************
uint32_t
GrMapISO8859_1_Unicode(const char *pcSrcChar, uint32_t ui32Count,
                       uint32_t *pui32Skip)
{
    //
    // Parameter sanity check.
    //
    ASSERT(pui32Skip);
    ASSERT(pcSrcChar);

    //
    // There is a 1:1 mapping of characters in ISO8859-1 to Unicode.
    //
    *pui32Skip = 1;
    return((uint32_t)((uint8_t)*pcSrcChar));
}

//*****************************************************************************
//
//! Maps an ISO8859-2 encoded character to its Unicode equivalent.
//!
//! \param pcSrcChar is a pointer to a string containing ISO8859-2 encoded
//!        text.
//! \param ui32Count is the number of bytes in the buffer pointed to by
//!        pcSrcChar.
//! \param pui32Skip points to storage that will be written with the number of
//!        bytes to skip in pcSrcChar to get to the next character in the
//!        buffer.
//!
//! This function may be passed to GrCodepageMapTableSet() in a tCodePointMap
//! structure to map source text in ISO8859-2 format into 32 bit Unicode
//! typically used by wide character fonts.  This conversion is straightforward
//! since character codes 0xA0 and below map directly to the same code in
//! Unicode and those from 0xA1 to 0xFF are converted using a global data
//! table.
//!
//! See http://unicode.org/Public/MAPPINGS/ISO8859/8859-2.TXT for more
//! information.
//!
//! \return Returns the Unicode character code for the first character in the
//! pcSrcChar string passed.
//
//*****************************************************************************
uint32_t
GrMapISO8859_2_Unicode(const char *pcSrcChar, uint32_t ui32Count,
                       uint32_t *pui32Skip)
{
    //
    // Parameter sanity check.
    //
    ASSERT(pui32Skip);
    ASSERT(pcSrcChar);

    //
    // ISO8859 mappings are all 8 bits so we skip a single byte for each
    // character.
    //
    *pui32Skip = 1;

    //
    // Is this character one of those which maps directly to Unicode?
    //
    if((uint8_t)*pcSrcChar <= 0xA0)
    {
        return((uint32_t)(char)*pcSrcChar);
    }
    else
    {
        return((uint32_t)g_pui16ISO8859_2_Unicode[
                              (char)*pcSrcChar - 0xA1]);
    }
}

//*****************************************************************************
//
//! Maps an ISO8859-3 encoded character to its Unicode equivalent.
//!
//! \param pcSrcChar is a pointer to a string containing ISO8859-3 encoded
//!        text.
//! \param ui32Count is the number of bytes in the buffer pointed to by
//!        pcSrcChar.
//! \param pui32Skip points to storage that will be written with the number of
//!        bytes to skip in pcSrcChar to get to the next character in the
//!        buffer.
//!
//! This function may be passed to GrCodepageMapTableSet() in a tCodePointMap
//! structure to map source text in ISO8859-3 format into 32 bit Unicode
//! typically used by wide character fonts.  This conversion is straightforward
//! since character codes 0xA0 and below map directly to the same code in
//! Unicode and those from 0xA1 to 0xFF are converted using a global data table.
//!
//! See http://unicode.org/Public/MAPPINGS/ISO8859/8859-3.TXT for more
//! information.
//!
//! \return Returns the Unicode character code for the first character in the
//! pcSrcChar string passed.
//
//*****************************************************************************
uint32_t
GrMapISO8859_3_Unicode(const char *pcSrcChar, uint32_t ui32Count,
                       uint32_t *pui32Skip)
{
    //
    // Parameter sanity check.
    //
    ASSERT(pui32Skip);
    ASSERT(pcSrcChar);

    //
    // ISO8859 mappings are all 8 bits so we skip a single byte for each
    // character.
    //
    *pui32Skip = 1;

    //
    // Is this character one of those which maps directly to Unicode?
    //
    if((uint8_t)*pcSrcChar <= 0xA0)
    {
        return((uint32_t)(uint8_t)*pcSrcChar);
    }
    else
    {
        return((uint32_t)g_pui16ISO8859_3_Unicode[
               (uint8_t)*pcSrcChar - 0xA1]);
    }
}

//*****************************************************************************
//
//! Maps an ISO8859-4 encoded character to its Unicode equivalent.
//!
//! \param pcSrcChar is a pointer to a string containing ISO8859-4 encoded
//!        text.
//! \param ui32Count is the number of bytes in the buffer pointed to by
//!        pcSrcChar.
//! \param pui32Skip points to storage that will be written with the number of
//!        bytes to skip in pcSrcChar to get to the next character in the
//!        buffer.
//!
//! This function may be passed to GrCodepageMapTableSet() in a tCodePointMap
//! structure to map source text in ISO8859-4 format into 32 bit Unicode
//! typically used by wide character fonts.  This conversion is straightforward
//! since character codes 0xA0 and below map directly to the same code in
//! Unicode and those from 0xA1 to 0xFF are converted using a global data table.
//!
//! See http://unicode.org/Public/MAPPINGS/ISO8859/8859-4.TXT for more
//! information.
//!
//! \return Returns the Unicode character code for the first character in the
//! pcSrcChar string passed.
//
//*****************************************************************************
uint32_t
GrMapISO8859_4_Unicode(const char *pcSrcChar, uint32_t ui32Count,
                       uint32_t *pui32Skip)
{
    //
    // Parameter sanity check.
    //
    ASSERT(pui32Skip);
    ASSERT(pcSrcChar);

    //
    // ISO8859 mappings are all 8 bits so we skip a single byte for each
    // character.
    //
    *pui32Skip = 1;

    //
    // Is this character one of those which maps directly to Unicode?
    //
    if((uint8_t)*pcSrcChar <= 0xA0)
    {
        return((uint32_t)(uint8_t)*pcSrcChar);
    }
    else
    {
        return((uint32_t)g_pui16ISO8859_4_Unicode[
               (uint8_t)*pcSrcChar - 0xA1]);
    }
}

//*****************************************************************************
//
//! Maps an ISO8859-5 encoded character to its Unicode equivalent.
//!
//! \param pcSrcChar is a pointer to a string containing ISO8859-5 encoded
//!        text.
//! \param ui32Count is the number of bytes in the buffer pointed to by
//!        pcSrcChar.
//! \param pui32Skip points to storage that will be written with the number of
//!        bytes to skip in pcSrcChar to get to the next character in the
//!        buffer.
//!
//! This function may be passed to GrCodepageMapTableSet() in a tCodePointMap
//! structure to map source text in ISO8859-5 format into 32 bit Unicode
//! typically used by wide character fonts.  This conversion is straightforward
//! since character codes 0xA0 and below map directly to the same code in
//! Unicode and those from 0xA1 to 0xFF map to the Unicode by adding 0x360 to
//! the ISO8859-5 code.
//!
//! See http://unicode.org/Public/MAPPINGS/ISO8859/8859-5.TXT for more
//! information.
//!
//! \return Returns the Unicode character code for the first character in the
//! pcSrcChar string passed.
//
//*****************************************************************************
uint32_t
GrMapISO8859_5_Unicode(const char *pcSrcChar, uint32_t ui32Count,
                       uint32_t *pui32Skip)
{
    //
    // Parameter sanity check.
    //
    ASSERT(pui32Skip);
    ASSERT(pcSrcChar);

    //
    // ISO8859 mappings are all 8 bits so we skip a single byte for each
    // character.
    //
    *pui32Skip = 1;

    //
    // Is this character one of those which maps directly to Unicode?
    //
    if((uint8_t)*pcSrcChar <= 0xA0)
    {
        return((uint32_t)(uint8_t)*pcSrcChar);
    }
    else
    {
        return((uint32_t)((uint8_t)*pcSrcChar) + 0x360);
    }
}

//*****************************************************************************
//
//! Maps an ISO8859-6 encoded character to its Unicode equivalent.
//!
//! \param pcSrcChar is a pointer to a string containing ISO8859-6 encoded
//!        text.
//! \param ui32Count is the number of bytes in the buffer pointed to by
//!        pcSrcChar.
//! \param pui32Skip points to storage that will be written with the number of
//!        bytes to skip in pcSrcChar to get to the next character in the
//!        buffer.
//!
//! This function may be passed to GrCodepageMapTableSet() in a tCodePointMap
//! structure to map source text in ISO8859-6 format into 32 bit Unicode
//! typically used by wide character fonts.  This conversion is straightforward
//! since character codes 0xA4 and below map directly to the same code in
//! Unicode and those from 0xA5 to 0xFF map to the Unicode by adding 0x560 to
//! the ISO8859-5 code.  The only odd-man-out is character 0xAD which maps to
//! Unicode 0xAD even though it is above 0xA4.
//!
//! See http://unicode.org/Public/MAPPINGS/ISO8859/8859-6.TXT for more
//! information.
//!
//! \return Returns the Unicode character code for the first character in the
//! pcSrcChar string passed.
//
//*****************************************************************************
uint32_t
GrMapISO8859_6_Unicode(const char *pcSrcChar, uint32_t ui32Count,
                       uint32_t *pui32Skip)
{
    //
    // Parameter sanity check.
    //
    ASSERT(pui32Skip);
    ASSERT(pcSrcChar);

    //
    // ISO8859 mappings are all 8 bits so we skip a single byte for each
    // character.
    //
    *pui32Skip = 1;

    //
    // Is this character one of those which maps directly to Unicode?
    //
    if(((uint8_t)*pcSrcChar <= 0xA4) ||
       ((uint8_t)*pcSrcChar == 0xAD))
    {
        return((uint32_t)(uint8_t)*pcSrcChar);
    }
    else
    {
        return((uint32_t)((uint8_t)*pcSrcChar) + 0x560);
    }
}

//*****************************************************************************
//
//! Maps an ISO8859-7 encoded character to its Unicode equivalent.
//!
//! \param pcSrcChar is a pointer to a string containing ISO8859-7 encoded
//!        text.
//! \param ui32Count is the number of bytes in the buffer pointed to by
//!        pcSrcChar.
//! \param pui32Skip points to storage that will be written with the number of
//!        bytes to skip in pcSrcChar to get to the next character in the
//!        buffer.
//!
//! This function may be passed to GrCodepageMapTableSet() in a tCodePointMap
//! structure to map source text in ISO8859-7 format into 32 bit Unicode
//! typically used by wide character fonts.  This conversion is straightforward
//! since character codes 0xA0 and below map directly to the same code in
//! Unicode, those from 0xBE to 0xFE map to the Unicode by adding 0x2D0 to
//! the ISO8859-7 code and only a few "unusual" mappings exist between
//! codepoints 0xA1 and 0xBD.
//!
//! See http://unicode.org/Public/MAPPINGS/ISO8859/8859-7.TXT for more
//! information.
//!
//! \return Returns the Unicode character code for the first character in the
//! pcSrcChar string passed.
//
//*****************************************************************************
uint32_t
GrMapISO8859_7_Unicode(const char *pcSrcChar, uint32_t ui32Count,
                       uint32_t *pui32Skip)
{
    //
    // Parameter sanity check.
    //
    ASSERT(pui32Skip);
    ASSERT(pcSrcChar);

    //
    // ISO8859 mappings are all 8 bits so we skip a single byte for each
    // character.
    //
    *pui32Skip = 1;

    //
    // Is this character one of those which maps directly to Unicode?
    //
    if((uint8_t)*pcSrcChar <= 0xA0)
    {
        //
        // This character is in the basic ASCII range so return it without
        // remapping.
        //
        return((uint32_t)(uint8_t)*pcSrcChar);
    }
    else if((uint8_t)*pcSrcChar >= 0xBE)
    {
        //
        // This character can be mapped to Unicode by a simple addition.
        //
        return((uint32_t)((uint8_t)*pcSrcChar) + 0x2D0);
    }
    else
    {
        //
        // This is one of the characters in the range which we map using a
        // table.
        //
        return(g_pui16ISO8859_7_Unicode[(uint8_t)*pcSrcChar - 0xA1]);
    }
}

//*****************************************************************************
//
//! Maps an ISO8859-8 encoded character to its Unicode equivalent.
//!
//! \param pcSrcChar is a pointer to a string containing ISO8859-8 encoded
//!        text.
//! \param ui32Count is the number of bytes in the buffer pointed to by
//!        pcSrcChar.
//! \param pui32Skip points to storage that will be written with the number of
//!        bytes to skip in pcSrcChar to get to the next character in the
//!        buffer.
//!
//! This function may be passed to GrCodepageMapTableSet() in a tCodePointMap
//! structure to map source text in ISO8859-8 format into 32 bit Unicode
//! typically used by wide character fonts.  This conversion is straightforward
//! since character codes 0xDE and below map directly to the same code in
//! Unicode, those from 0xE0 to 0xFA map to the Unicode by adding 0x4F0 to
//! the ISO8859-7 code and only a few "unusual" mappings exist at codepoints
//! 0xDF, 0xFD and 0xFE.
//!
//! See http://unicode.org/Public/MAPPINGS/ISO8859/8859-8.TXT for more
//! information.
//!
//! \return Returns the Unicode character code for the first character in the
//! pcSrcChar string passed.
//
//*****************************************************************************
uint32_t
GrMapISO8859_8_Unicode(const char *pcSrcChar, uint32_t ui32Count,
                       uint32_t *pui32Skip)
{
    //
    // Parameter sanity check.
    //
    ASSERT(pui32Skip);
    ASSERT(pcSrcChar);

    //
    // ISO8859 mappings are all 8 bits so we skip a single byte for each
    // character.
    //
    *pui32Skip = 1;

    //
    // Is this character one of those which maps directly to Unicode?
    //
    if((uint8_t)*pcSrcChar <= 0xDE)
    {
        //
        // This character is in the basic ASCII range so return it without
        // remapping.
        //
        return((uint32_t)(uint8_t)*pcSrcChar);
    }
    else if((uint8_t)*pcSrcChar == 0xDF)
    {
        //
        // Return this special case.
        //
        return(0x2017);
    }
    else if((uint8_t)*pcSrcChar <= 0xFC)
    {
        //
        // Map this range using a simple addition.
        //
        return((uint8_t)*pcSrcChar + 0x4F0);
    }
    else
    {
        //
        // There are only 2 valid characters left at 0xFD and 0xFE.  Map these
        // to Unicode by adding 0x1F11 to map them to 0x200E and 0x200F.
        //
        return((uint8_t)*pcSrcChar + 0x1F11);
    }
}

//*****************************************************************************
//
//! Maps an ISO8859-9 encoded character to its Unicode equivalent.
//!
//! \param pcSrcChar is a pointer to a string containing ISO8859-9 encoded
//!        text.
//! \param ui32Count is the number of bytes in the buffer pointed to by
//!        pcSrcChar.
//! \param pui32Skip points to storage that will be written with the number of
//!        bytes to skip in pcSrcChar to get to the next character in the
//!        buffer.
//!
//! This function may be passed to GrCodepageMapTableSet() in a tCodePointMap
//! structure to map source text in ISO8859-9 format into 32 bit Unicode
//! typically used by wide character fonts.  This character set is almost
//! identical to ISO8859-1 but substitutes 6 characters to offer better
//! support for the Turkish language.
//!
//! See http://unicode.org/Public/MAPPINGS/ISO8859/8859-9.TXT for more
//! information.
//!
//! \return Returns the Unicode character code for the first character in the
//! pcSrcChar string passed.
//
//*****************************************************************************
uint32_t
GrMapISO8859_9_Unicode(const char *pcSrcChar, uint32_t ui32Count,
                       uint32_t *pui32Skip)
{
    //
    // Parameter sanity check.
    //
    ASSERT(pui32Skip);
    ASSERT(pcSrcChar);

    //
    // ISO8859 mappings are all 8 bits so we skip a single byte for each
    // character.
    //
    *pui32Skip = 1;

    //
    // Deal with the special cases in this switch.
    //
    switch((uint8_t)*pcSrcChar)
    {
        //
        // Character 0xD0 in ISO8859-9 maps to U+011E
        //
        case 0xD0:
        {
            return(0x11E);
        }

        //
        // Character 0xDD in ISO8859-9 maps to U+0130
        //
        case 0xDD:
        {
            return(0x130);
        }

        //
        // Character 0xDE in ISO8859-9 maps to U+015E
        //
        case 0xDE:
        {
            return(0x15E);
        }

        //
        // Character 0xF0 in ISO8859-9 maps to U+011F
        //
        case 0xF0:
        {
            return(0x11F);
        }

        //
        // Character 0xFD in ISO8859-9 maps to U+0131
        //
        case 0xFD:
        {
            return(0x131);
        }

        //
        // Character 0xFE in ISO8859-9 maps to U+015F
        //
        case 0xFE:
        {
            return(0x15F);
        }

        //
        // All other characters map directly to Unicode using the same
        // codepoints.
        //
        default:
        {
            return((uint32_t)(uint8_t)*pcSrcChar);
        }
    }
}

//*****************************************************************************
//
//! Maps an ISO8859-10 encoded character to its Unicode equivalent.
//!
//! \param pcSrcChar is a pointer to a string containing ISO8859-10 encoded
//!        text.
//! \param ui32Count is the number of bytes in the buffer pointed to by
//!        pcSrcChar.
//! \param pui32Skip points to storage that will be written with the number of
//!        bytes to skip in pcSrcChar to get to the next character in the
//!        buffer.
//!
//! This function may be passed to GrCodepageMapTableSet() in a tCodePointMap
//! structure to map source text in ISO8859-10 format into 32 bit Unicode
//! typically used by wide character fonts.  Character codes 0xA0 and below
//! map directly to the same code in Unicode and those from 0xA1 to 0xFF are
//! converted using a global data table.
//!
//! See http://unicode.org/Public/MAPPINGS/ISO8859/8859-10.TXT for more
//! information.
//!
//! \return Returns the Unicode character code for the first character in the
//! pcSrcChar string passed.
//
//*****************************************************************************
uint32_t
GrMapISO8859_10_Unicode(const char *pcSrcChar, uint32_t ui32Count,
                        uint32_t *pui32Skip)
{
    //
    // Parameter sanity check.
    //
    ASSERT(pui32Skip);
    ASSERT(pcSrcChar);

    //
    // ISO8859 mappings are all 8 bits so we skip a single byte for each
    // character.
    //
    *pui32Skip = 1;

    //
    // Is this character one of those which maps directly to Unicode?
    //
    if((uint8_t)*pcSrcChar <= 0xA0)
    {
        return((uint32_t)(uint8_t)*pcSrcChar);
    }
    else
    {
        return((uint32_t)g_pui16ISO8859_10_Unicode[
               (uint8_t)*pcSrcChar - 0xA1]);
    }
}

//*****************************************************************************
//
//! Maps an ISO8859-11 encoded character to its Unicode equivalent.
//!
//! \param pcSrcChar is a pointer to a string containing ISO8859-11 encoded
//!        text.
//! \param ui32Count is the number of bytes in the buffer pointed to by
//!        pcSrcChar.
//! \param pui32Skip points to storage that will be written with the number of
//!        bytes to skip in pcSrcChar to get to the next character in the
//!        buffer.
//!
//! This function may be passed to GrCodepageMapTableSet() in a tCodePointMap
//! structure to map source text in ISO8859-11 format into 32 bit Unicode
//! typically used by wide character fonts.  This conversion is straightforward
//! since character codes 0xA0 and below map directly to the same code in
//! Unicode and those from 0xA1 to 0xFF map to the Unicode by adding 0xD60 to
//! the ISO8859-11 code.
//!
//! See http://unicode.org/Public/MAPPINGS/ISO8859/8859-11.TXT for more
//! information.
//!
//! \return Returns the Unicode character code for the first character in the
//! pcSrcChar string passed.
//
//*****************************************************************************
uint32_t
GrMapISO8859_11_Unicode(const char *pcSrcChar, uint32_t ui32Count,
                        uint32_t *pui32Skip)
{
    //
    // Parameter sanity check.
    //
    ASSERT(pui32Skip);
    ASSERT(pcSrcChar);

    //
    // ISO8859 mappings are all 8 bits so we skip a single byte for each
    // character.
    //
    *pui32Skip = 1;

    //
    // Is this character one of those which maps directly to Unicode?
    //
    if((uint8_t)*pcSrcChar <= 0xA0)
    {
        return((uint32_t)(uint8_t)*pcSrcChar);
    }
    else
    {
        return((uint32_t)((uint8_t)*pcSrcChar) + 0xD60);
    }
}

//*****************************************************************************
//
//! Maps an ISO8859-13 encoded character to its Unicode equivalent.
//!
//! \param pcSrcChar is a pointer to a string containing ISO8859-13 encoded
//!        text.
//! \param ui32Count is the number of bytes in the buffer pointed to by
//!        pcSrcChar.
//! \param pui32Skip points to storage that will be written with the number of
//!        bytes to skip in pcSrcChar to get to the next character in the
//!        buffer.
//!
//! This function may be passed to GrCodepageMapTableSet() in a tCodePointMap
//! structure to map source text in ISO8859-13 format into 32 bit Unicode
//! typically used by wide character fonts.  Character codes 0xA0 and below
//! map directly to the same code in Unicode and those from 0xA1 to 0xFF are
//! converted using a global data table.
//!
//! See http://unicode.org/Public/MAPPINGS/ISO8859/8859-13.TXT for more
//! information.
//!
//! \return Returns the Unicode character code for the first character in the
//! pcSrcChar string passed.
//
//*****************************************************************************
uint32_t
GrMapISO8859_13_Unicode(const char *pcSrcChar, uint32_t ui32Count,
                        uint32_t *pui32Skip)
{
    //
    // Parameter sanity check.
    //
    ASSERT(pui32Skip);
    ASSERT(pcSrcChar);

    //
    // ISO8859 mappings are all 8 bits so we skip a single byte for each
    // character.
    //
    *pui32Skip = 1;

    //
    // Is this character one of those which maps directly to Unicode?
    //
    if((uint8_t)*pcSrcChar <= 0xA0)
    {
        return((uint32_t)(uint8_t)*pcSrcChar);
    }
    else
    {
        return((uint32_t)g_pui16ISO8859_13_Unicode[(uint8_t)*pcSrcChar - 0xA1]);
    }
}

//*****************************************************************************
//
//! Maps an ISO8859-14 encoded character to its Unicode equivalent.
//!
//! \param pcSrcChar is a pointer to a string containing ISO8859-14 encoded
//!        text.
//! \param ui32Count is the number of bytes in the buffer pointed to by
//!        pcSrcChar.
//! \param pui32Skip points to storage that will be written with the number of
//!        bytes to skip in pcSrcChar to get to the next character in the
//!        buffer.
//!
//! This function may be passed to GrCodepageMapTableSet() in a tCodePointMap
//! structure to map source text in ISO8859-9 format into 32 bit Unicode
//! typically used by wide character fonts.  This character set is similar to
//! ISO8859-1 but substitutes several characters to offer support for various
//! Celtic languages.
//!
//! See http://unicode.org/Public/MAPPINGS/ISO8859/8859-14.TXT for more
//! information.
//!
//! \return Returns the Unicode character code for the first character in the
//! pcSrcChar string passed.
//
//*****************************************************************************
uint32_t
GrMapISO8859_14_Unicode(const char *pcSrcChar, uint32_t ui32Count,
                        uint32_t *pui32Skip)
{
    //
    // Parameter sanity check.
    //
    ASSERT(pui32Skip);
    ASSERT(pcSrcChar);

    //
    // ISO8859 mappings are all 8 bits so we skip a single byte for each
    // character.
    //
    *pui32Skip = 1;

    //
    // Deal with the special cases in this switch.
    //
    switch((uint8_t)*pcSrcChar)
    {
        //
        // Character 0xD0 in ISO8859-14 maps to U+0174
        //
        case 0xD0:
        {
            return(0x174);
        }

        //
        // Character 0xD7 in ISO8859-14 maps to U+1E6A
        //
        case 0xD7:
        {
            return(0x1E6A);
        }

        //
        // Character 0xDE in ISO8859-14 maps to U+0176
        //
        case 0xDE:
        {
            return(0x176);
        }

        //
        // Character 0xF0 in ISO8859-14 maps to U+0175
        //
        case 0xF0:
        {
            return(0x175);
        }

        //
        // Character 0xF7 in ISO8859-14 maps to U+1E6B
        //
        case 0xF7:
        {
            return(0x1E6B);
        }

        //
        // Character 0xFD in ISO8859-14 maps to U+0177
        //
        case 0xFD:
        {
            return(0x131);
        }

        //
        // Other codepoints above 0xC0 map directly to their Unicode
        // equivalents.  Mappings for characters from 0xA1 to 0xBF are handled
        // using a global table.
        //
        default:
        {
            if((uint8_t)*pcSrcChar >= 0xC0)
            {
                return((uint32_t)(uint8_t)*pcSrcChar);
            }
            else
            {
                return((uint32_t)g_pui16ISO8859_14_Unicode[
                       (uint8_t)*pcSrcChar - 0xA1]);
            }
        }
    }
}

//*****************************************************************************
//
//! Maps an ISO8859-15 encoded character to its Unicode equivalent.
//!
//! \param pcSrcChar is a pointer to a string containing ISO8859-15 encoded
//!        text.
//! \param ui32Count is the number of bytes in the buffer pointed to by
//!        pcSrcChar.
//! \param pui32Skip points to storage that will be written with the number of
//!        bytes to skip in pcSrcChar to get to the next character in the
//!        buffer.
//!
//! This function may be passed to GrCodepageMapTableSet() in a tCodePointMap
//! structure to map source text in ISO8859-15 format into 32 bit Unicode
//! typically used by wide character fonts.  This character set is similar to
//! ISO8859-1 differing from that codepage in only 8 positions.
//!
//! See http://unicode.org/Public/MAPPINGS/ISO8859/8859-15.TXT for more
//! information.
//!
//! \return Returns the Unicode character code for the first character in the
//! pcSrcChar string passed.
//
//*****************************************************************************
uint32_t
GrMapISO8859_15_Unicode(const char *pcSrcChar, uint32_t ui32Count,
                        uint32_t *pui32Skip)
{
    //
    // Parameter sanity check.
    //
    ASSERT(pui32Skip);
    ASSERT(pcSrcChar);

    //
    // ISO8859 mappings are all 8 bits so we skip a single byte for each
    // character.
    //
    *pui32Skip = 1;

    //
    // Deal with the special cases in this switch.
    //
    switch((uint8_t)*pcSrcChar)
    {
        //
        // Character 0xA4 in ISO8859-15 maps to U+20AC
        //
        case 0xA4:
        {
            return(0x20AC);
        }

        //
        // Character 0xA6 in ISO8859-15 maps to U+0160
        //
        case 0xA6:
        {
            return(0x160);
        }

        //
        // Character 0xA8 in ISO8859-15 maps to U+0161
        //
        case 0xA8:
        {
            return(0x161);
        }

        //
        // Character 0xB4 in ISO8859-15 maps to U+017D
        //
        case 0xB4:
        {
            return(0x17D);
        }

        //
        // Character 0xB8 in ISO8859-15 maps to U+017E
        //
        case 0xB8:
        {
            return(0x17E);
        }

        //
        // Character 0xBC in ISO8859-15 maps to U+0152
        //
        case 0xBC:
        {
            return(0x152);
        }

        //
        // Character 0xBD in ISO8859-15 maps to U+0153
        //
        case 0xBD:
        {
            return(0x153);
        }

        //
        // Character 0xBE in ISO8859-15 maps to U+0178
        //
        case 0xBE:
        {
            return(0x178);
        }

        //
        // All other codepoints map directly to their Unicode equivalents.
        //
        default:
        {
            return((uint32_t)(uint8_t)*pcSrcChar);
        }
    }
}

//*****************************************************************************
//
//! Maps an ISO8859-16 encoded character to its Unicode equivalent.
//!
//! \param pcSrcChar is a pointer to a string containing ISO8859-16 encoded
//!        text.
//! \param ui32Count is the number of bytes in the buffer pointed to by
//!        pcSrcChar.
//! \param pui32Skip points to storage that will be written with the number of
//!        bytes to skip in pcSrcChar to get to the next character in the
//!        buffer.
//!
//! This function may be passed to GrCodepageMapTableSet() in a tCodePointMap
//! structure to map source text in ISO8859-16 format into 32 bit Unicode
//! typically used by wide character fonts.  Character codes 0xA0 and below
//! map directly to the same code in Unicode and those from 0xA1 to 0xFF are
//! converted using a global data table.
//!
//! See http://unicode.org/Public/MAPPINGS/ISO8859/8859-16.TXT for more
//! information.
//!
//! \return Returns the Unicode character code for the first character in the
//! pcSrcChar string passed.
//
//*****************************************************************************
uint32_t
GrMapISO8859_16_Unicode(const char *pcSrcChar, uint32_t ui32Count,
                        uint32_t *pui32Skip)
{
    //
    // Parameter sanity check.
    //
    ASSERT(pui32Skip);
    ASSERT(pcSrcChar);

    //
    // ISO8859 mappings are all 8 bits so we skip a single byte for each
    // character.
    //
    *pui32Skip = 1;

    //
    // Is this character one of those which maps directly to Unicode?
    //
    if((uint8_t)*pcSrcChar <= 0xA0)
    {
        return((uint32_t)(uint8_t)*pcSrcChar);
    }
    else
    {
        return((uint32_t)g_pui16ISO8859_16_Unicode[
               (uint8_t)*pcSrcChar - 0xA1]);
    }
}

//*****************************************************************************
//
//! Maps a UTF-8 encoded character to its Unicode equivalent.
//!
//! \param pcSrcChar is a pointer to a string containing UTF-8 encoded text.
//! \param ui32Count is the number of bytes in the buffer pointed to by
//!        pcSrcChar.
//! \param pui32Skip points to storage that will be written with the number of
//!        bytes to skip in pcSrcChar to get to the next character in the
//!        buffer.
//!
//! This function may be passed to GrCodepageMapTableSet() in a tCodePointMap
//! structure to map source text in UTF-8 format into 32 bit Unicode typically
//! used by wide character fonts.  This conversion will read bytes from the
//! buffer and decode the first full UTF-8 character found, returning the
//! Unicode code for that character and the number of bytes to advance
//! pcSrcChar by to point to the end of the decoded character.  If no valid
//! UTF-8 character is found, 0 is returned.
//!
//! See http://en.wikipedia.org/wiki/UTF-8 for more information.
//!
//! \return Returns the Unicode character code for the first character in the
//! pcSrcChar string passed.
//
//*****************************************************************************
uint32_t
GrMapUTF8_Unicode(const char *pcSrcChar, uint32_t ui32Count,
                  uint32_t *pui32Skip)
{
    uint32_t ui32Unicode, ui32ToRead, ui32Index;

    //
    // Parameter sanity check.
    //
    ASSERT(pui32Skip);
    ASSERT(pcSrcChar);

    //
    // Clear our our character code storage.
    //
    ui32Unicode = 0;
    ui32Index = 0;

    //
    // While we have bytes left to examine in the buffer and the current byte
    // is a continuation code...
    //
    while(ui32Count && ((uint8_t)pcSrcChar[ui32Index] & 0xC0) == 0x80)
    {
          //
           // Skip the byte.
           //
           ui32Index++;
           ui32Count--;
    }

    //
    // We are now either at the end of the string or the start of a new
    // character unit.  Did we get to the end of the string?
    //
    if(!ui32Count)
    {
        //
        // Yes - return 0.
        //
        return(0);
    }

    //
    // Is this a single byte encoded character of the form 0xxxxxxx?
    //
    if(!((uint8_t)(pcSrcChar[ui32Index]) & 0x80))
    {
        //
        // Yes - the Unicode equivalent is just the bottom 7 bits of the
        // UTF-8 byte.
        //
        ui32Unicode = (uint8_t)(pcSrcChar[ui32Index++]) & 0x7F;
        ui32ToRead = 0;
    }
    else
    {
        //
        // This is a multi-byte encoded character. Determine how many bytes
        // it uses.
        //
        ui32ToRead =
            NumLeadingZeros(~((uint32_t)pcSrcChar[ui32Index] << 24)) - 1;


        //
        // There can be a maximum of 5 more bytes to read.  If we found more
        // than this, then this is an illegal code.
        //
        if(ui32ToRead > 5)
        {
            ui32Unicode = 0;
            ui32ToRead = 0;
            ui32Index++;
        }
        else
        {
            //
            // Extract the first bits of the Unicode value from this byte.
            //
            ui32Unicode = (uint8_t)pcSrcChar[ui32Index++] &
                        ((1 << (6 - ui32ToRead)) - 1);

            //
            // Read the remaining bytes encoding this character.
            //
            while(ui32Count && ui32ToRead)
            {
                //
                // Is this a continuation byte with form 10xxxxxx?
                //
                if(((uint8_t)pcSrcChar[ui32Index] & 0xC0) != 0x80)
                {
                    //
                    // No - this is an invalid character to return 0 and tell
                    // the caller to skip past it.
                    //
                    *pui32Skip = ui32Index;
                    return(0);
                }
                else
                {
                    //
                    // Extract the bottom 6 bits from the continuation
                    // character and mask them into the Unicode code.
                    //
                    ui32Unicode = ((ui32Unicode << 6) |
                                 ((uint8_t)pcSrcChar[ui32Index++] & 0x3F));
                    ui32ToRead--;
                    ui32Count--;
                }
            }

            //
            // If we get here and we didn't read the expected number of bytes,
            // this is an invalid character.
            //
            if(ui32ToRead)
            {
                //
                // We ran out of data before reading all the required
                // continuation bytes so tell the caller to skip the data and
                // return 0 to indicate an error.
                //
                *pui32Skip = ui32Index;
                return(0);
            }
        }
    }

    //
    // Tell the caller how many bytes to skip to get to the next character in
    // the string.
    //
    *pui32Skip = ui32Index;

    //
    // Return the Unicode character code.
    //
    return(ui32Unicode);
}

//*****************************************************************************
//
// Maps a UTF-16LE or UTF-16BE encoded character to its Unicode equivalent.
//
// \param pcSrcChar is a pointer to a string containing UTF-16LE encoded text.
// \param ui32Count is the number of bytes in the buffer pointed to by
//        pcSrcChar.
// \param pui32Skip points to storage that will be written with the number of
//        bytes to skip in pcSrcChar to get to the next character in the
//        buffer.
// \param bLE is \b true if the \e pcSrcChar points to a UTF-16LE encoded
//        string or \b false if it points to a UTF-16BE string.
//
// This internal function is used to support GrMapUTF16LE_Unicode and
// GrMapUTF16BE_Unicode.
//
// \return Returns the Unicode character code for the first character in the
// \e pcSrcChar string passed.
//
//*****************************************************************************
static uint32_t
GrMapUTF16_Unicode(const char *pcSrcChar, uint32_t ui32Count,
                   uint32_t *pui32Skip, bool bLE)
{
    uint16_t ui16Char, ui16CharToo;
    uint32_t ui32Code;
    const char *pcChar;

    //
    // Parameter sanity check.
    //
    ASSERT(pui32Skip);
    ASSERT(pcSrcChar);

    //
    // Walk the string until we find something valid that we can decode.
    //
    ui32Code = 0;
    pcChar = pcSrcChar;

    while(ui32Count >= 2)
    {
        //
        // Get a word from the string.
        //
        ui16Char = bLE ? (pcChar[0] + 256 * pcChar[1]) :
                       (pcChar[1] + 256 * pcChar[0]);

        //
        // Move to the next word and update our count.
        //
        ui32Count -= 2;
        pcChar += 2;

        //
        // Is this a valid single-word encoding?
        //
        if((ui16Char <= 0xD7FF) || (ui16Char >= 0xE000))
        {
            //
            // Yes - return the value and tell the caller to skip the
            // appropriate number of bytes to get to the end of this character.
            //
            ui32Code = (uint32_t)ui16Char;
            break;
        }
        else
        {
            //
            // Is this a valid first word for a high surrogate (first word in a
            // 2 word encoding)?
            //
            if((ui16Char >= 0xD800) && (ui16Char < 0xDC00))
            {
                //
                // Yes - this is valid. Now look ahead and see if the next
                // word is valid as a low surrogate, assuming there are at
                // least 2 more bytes for us to look at.
                //
                if(ui32Count >= 2)
                {
                    //
                    // Get the next word in the string.
                    //
                    ui16CharToo = bLE ? (pcChar[0] + 256 * pcChar[1]) :
                                      (pcChar[1] + 256 * pcChar[0]);

                    //
                    // Is this a valid low surrogate?
                    //
                    if((ui16CharToo >= 0xDC00) && (ui16CharToo < 0xE000))
                    {
                        //
                        // Yes, it's valid. Update our skip count and parse
                        // the Unicode codepoint from the two words we've read.
                        //
                        pcChar += 2;
                        ui32Count -= 2;
                        ui32Code = 0x10000 +
                                 ((uint32_t)(ui16Char - 0xD800) << 10) +
                                 ((uint32_t)ui16CharToo - 0xDC00);
                        break;
                    }
                }
            }
        }
    }

    //
    // Set the number of bytes to skip in the string to get past the
    // character we just parsed and return the character codepoint if we
    // found one.
    //
    *pui32Skip = (uint32_t)(pcChar - pcSrcChar);
    return(ui32Code);
}

//*****************************************************************************
//
//! Maps a UTF-16LE encoded character to its Unicode equivalent.
//!
//! \param pcSrcChar is a pointer to a string containing UTF-16LE encoded text.
//! \param ui32Count is the number of bytes in the buffer pointed to by
//!        pcSrcChar.
//! \param pui32Skip points to storage that will be written with the number of
//!        bytes to skip in pcSrcChar to get to the next character in the
//!        buffer.
//!
//! This function may be passed to GrCodepageMapTableSet() in a tCodePointMap
//! structure to map source text in UTF-16LE format into 32 bit Unicode
//! typically used by wide character fonts.  This conversion will read bytes
//! from the buffer and decode the first full UTF-16LE character found,
//! returning the Unicode code for that character and the number of bytes to
//! advance \e pcSrcChar by to point to the end of the decoded character.  If
//! no valid UTF-16LE character is found, 0 is returned.
//!
//! See http://en.wikipedia.org/wiki/UTF-16 for more information.
//!
//! \return Returns the Unicode character code for the first character in the
//! \e pcSrcChar string passed.
//
//*****************************************************************************
uint32_t
GrMapUTF16LE_Unicode(const char *pcSrcChar, uint32_t ui32Count,
                     uint32_t *pui32Skip)
{
    //
    // Call the low level UTF parsing function and return the result.
    //
    return(GrMapUTF16_Unicode(pcSrcChar, ui32Count, pui32Skip, true));
}

//*****************************************************************************
//
//! Maps a UTF-16BE encoded character to its Unicode equivalent.
//!
//! \param pcSrcChar is a pointer to a string containing UTF-16BE encoded text.
//! \param ui32Count is the number of bytes in the buffer pointed to by
//!        pcSrcChar.
//! \param pui32Skip points to storage that will be written with the number of
//!        bytes to skip in pcSrcChar to get to the next character in the
//!        buffer.
//!
//! This function may be passed to GrCodepageMapTableSet() in a tCodePointMap
//! structure to map source text in UTF-16BE format into 32 bit Unicode
//! typically used by wide character fonts.  This conversion will read bytes
//! from the buffer and decode the first full UTF-16BE character found,
//! returning the Unicode code for that character and the number of bytes to
//! advance \e pcSrcChar by to point to the end of the decoded character.  If
//! no valid UTF-16BE character is found, 0 is returned.
//!
//! See http://en.wikipedia.org/wiki/UTF-16 for more information.
//!
//! \return Returns the Unicode character code for the first character in the
//! \e pcSrcChar string passed.
//
//*****************************************************************************
uint32_t
GrMapUTF16BE_Unicode(const char *pcSrcChar, uint32_t ui32Count,
                     uint32_t *pui32Skip)
{
    //
    // Call the low level UTF parsing function and return the result.
    //
    return(GrMapUTF16_Unicode(pcSrcChar, ui32Count, pui32Skip, false));
}

//*****************************************************************************
//
//! Maps an 32 bit Unicode encoded character to itself.
//!
//! \param pcSrcChar is a pointer to a string containing 32 bit Unicode text.
//! \param ui32Count is the number of bytes in the buffer pointed to by
//!        pcSrcChar.
//! \param pui32Skip points to storage that will be written with the number of
//!        bytes to skip in pcSrcChar to get to the next character in the
//!        buffer.
//!
//! This function may be passed to GrCodepageMapTableSet() in a tCodePointMap
//! structure to map source text in Unicode (UTF32) format into 32 bit
//! Unicode typically used by wide character fonts.  This identity conversion is
//! trivial - we merely read 4 bytes at a time and return the 32 bit value they
//! contain. It is assumed that the text is encoded in little endian format.
//!
//! \return Returns the Unicode character code for the first character in the
//! pcSrcChar string passed.
//
//*****************************************************************************
uint32_t
GrMapUnicode_Unicode(const char *pcSrcChar, uint32_t ui32Count,
                     uint32_t *pui32Skip)
{
    //
    // Parameter sanity check.
    //
    ASSERT(pui32Skip);
    ASSERT(pcSrcChar);

    //
    // Do we have enough bytes to pull out a single 32 bit character code?
    //
    if(ui32Count < 4)
    {
        //
        // Return 0 to indicate an error since we don't have enough data to
        // extract a single character code.
        //
        return(0);
    }
    else
    {
        //
        // We have at least 4 bytes so tell the caller to skip 4 bytes to get
        // the following character and return the Unicode codepoint represented
        // by the first 4 bytes in the buffer.
        //
        *pui32Skip = 4;
        return(pcSrcChar[0] | (pcSrcChar[1] << 8) | (pcSrcChar[2] << 16) |
               (pcSrcChar[3] << 24));
    }
}

//*****************************************************************************
//
//! Maps a WIN1250 encoded character to its Unicode equivalent.
//!
//! \param pcSrcChar is a pointer to a string containing WIN1250 encoded
//!        text.
//! \param ui32Count is the number of bytes in the buffer pointed to by
//!        pcSrcChar.
//! \param pui32Skip points to storage that will be written with the number of
//!        bytes to skip in pcSrcChar to get to the next character in the
//!        buffer.
//!
//! This function may be passed to GrCodepageMapTableSet() in a tCodePointMap
//! structure to map source text in WIN1250 format into 32 bit Unicode
//! typically used by wide character fonts.  Windows-1250 is a codepage commonly
//! used in processing eastern European text.  This conversion is
//! straightforward since character codes 0x7F and below map directly to the
//! same code in Unicode, and those from 0x80 to 0xFF are converted using a
//! global data table.
//!
//! See http://en.wikipedia.org/wiki/Windows-1250 for more information.
//!
//! \return Returns the Unicode character code for the first character in the
//! pcSrcChar string passed.
//
//*****************************************************************************
uint32_t
GrMapWIN1250_Unicode(const char *pcSrcChar, uint32_t ui32Count,
                     uint32_t *pui32Skip)
{
    //
    // Parameter sanity check.
    //
    ASSERT(pui32Skip);
    ASSERT(pcSrcChar);

    //
    // WIN1250 mappings are all 8 bits so we skip a single byte for each
    // character.
    //
    *pui32Skip = 1;

    //
    // Is this character one of those which maps directly to Unicode?
    //
    if((uint8_t)*pcSrcChar <= 0x7F)
    {
        return((uint32_t)(uint8_t)*pcSrcChar);
    }
    else
    {
        return((uint32_t)g_pui16WIN1250_Unicode[
                              (uint8_t)*pcSrcChar - 0x80]);
    }
}

//*****************************************************************************
//
//! Maps a WIN1251 encoded character to its Unicode equivalent.
//!
//! \param pcSrcChar is a pointer to a string containing WIN1251 encoded
//!        text.
//! \param ui32Count is the number of bytes in the buffer pointed to by
//!        pcSrcChar.
//! \param pui32Skip points to storage that will be written with the number of
//!        bytes to skip in pcSrcChar to get to the next character in the
//!        buffer.
//!
//! This function may be passed to GrCodepageMapTableSet() in a tCodePointMap
//! structure to map source text in WIN1251 format into 32 bit Unicode
//! typically used by wide character fonts.  Windows-1251 is a codepage commonly
//! used in processing Cyrillic text.  This conversion is straightforward
//! since character codes 0x7F and below map directly to the same code in
//! Unicode, those from 0x80 to 0xBF are converted using a global data table
//! and those from 0xC0 to 0xFF map to the Unicode by adding 0x350 to
//! the WIN1251 code.
//!
//! See http://en.wikipedia.org/wiki/Windows-1251 for more information.
//!
//! \return Returns the Unicode character code for the first character in the
//! pcSrcChar string passed.
//
//*****************************************************************************
uint32_t
GrMapWIN1251_Unicode(const char *pcSrcChar, uint32_t ui32Count,
                     uint32_t *pui32Skip)
{
    //
    // Parameter sanity check.
    //
    ASSERT(pui32Skip);
    ASSERT(pcSrcChar);

    //
    // WIN1251 mappings are all 8 bits so we skip a single byte for each
    // character.
    //
    *pui32Skip = 1;

    //
    // Is this character one of those which maps directly to Unicode?
    //
    if((uint8_t)*pcSrcChar <= 0x7F)
    {
        return((uint32_t)(uint8_t)*pcSrcChar);
    }
    else if(((uint8_t)*pcSrcChar >= 0x80) &&
            ((uint8_t)*pcSrcChar <= 0xBF))
    {
        return((uint32_t)g_pui16WIN1251_Unicode[
               (uint8_t)*pcSrcChar - 0x80]);
    }
    else
    {
         return((uint32_t)((uint8_t)*pcSrcChar) + 0x350);
    }
}

//*****************************************************************************
//
//! Maps a WIN1252 encoded character to its Unicode equivalent.
//!
//! \param pcSrcChar is a pointer to a string containing WIN1252 encoded
//!        text.
//! \param ui32Count is the number of bytes in the buffer pointed to by
//!        pcSrcChar.
//! \param pui32Skip points to storage that will be written with the number of
//!        bytes to skip in pcSrcChar to get to the next character in the
//!        buffer.
//!
//! This function may be passed to GrCodepageMapTableSet() in a tCodePointMap
//! structure to map source text in WIN1252 format into 32 bit Unicode
//! typically used by wide character fonts.  Windows-1252 is a codepage commonly
//! used in processing western European text.  This conversion is
//! straightforward since character codes 0x7F and below, and 0xA0 and above
//! map directly to the same code in Unicode, and those from 0x80 to 0x9F are
//! converted using a global data table.  This codepage can be thought of as a
//! superset of ISO8859-1 and text purported to be encoded in ISO8859-1 is
//! frequently processed using this codepage instead.
//!
//! See http://en.wikipedia.org/wiki/Windows-1252 for more information.
//!
//! \return Returns the Unicode character code for the first character in the
//! pcSrcChar string passed.
//
//*****************************************************************************
uint32_t
GrMapWIN1252_Unicode(const char *pcSrcChar, uint32_t ui32Count,
                     uint32_t *pui32Skip)
{
    //
    // Parameter sanity check.
    //
    ASSERT(pui32Skip);
    ASSERT(pcSrcChar);

    //
    // WIN1252 mappings are all 8 bits so we skip a single byte for each
    // character.
    //
    *pui32Skip = 1;

    //
    // Is this character one of those which maps directly to Unicode?
    //
    if(((uint8_t)*pcSrcChar <= 0x7F) ||
       ((uint8_t)*pcSrcChar >= 0xA0))
    {
        return((uint32_t)(uint8_t)*pcSrcChar);
    }
    else
    {
        return((uint32_t)g_pui16WIN1252_Unicode[
                              (uint8_t)*pcSrcChar - 0x80]);
    }
}

//*****************************************************************************
//
//! Maps a WIN1253 encoded character to its Unicode equivalent.
//!
//! \param pcSrcChar is a pointer to a string containing WIN1253 encoded
//!        text.
//! \param ui32Count is the number of bytes in the buffer pointed to by
//!        pcSrcChar.
//! \param pui32Skip points to storage that will be written with the number of
//!        bytes to skip in pcSrcChar to get to the next character in the
//!        buffer.
//!
//! This function may be passed to GrCodepageMapTableSet() in a tCodePointMap
//! structure to map source text in WIN1253 format into 32 bit Unicode
//! typically used by wide character fonts.  Windows-1253 is a codepage commonly
//! used in processing Greek text.  This conversion is straightforward
//! since character codes 0x7F and below map directly to the same code in
//! Unicode, those from 0x80 to 0xBF are converted using a global data table
//! and those from 0xC0 to 0xFF map to the Unicode by adding 0x2D0 to
//! the WIN1253 code.
//!
//! See http://en.wikipedia.org/wiki/Windows-1253 for more information.
//!
//! \return Returns the Unicode character code for the first character in the
//! pcSrcChar string passed.
//
//*****************************************************************************
uint32_t
GrMapWIN1253_Unicode(const char *pcSrcChar, uint32_t ui32Count,
                     uint32_t *pui32Skip)
{
    //
    // Parameter sanity check.
    //
    ASSERT(pui32Skip);
    ASSERT(pcSrcChar);

    //
    // WIN1253 mappings are all 8 bits so we skip a single byte for each
    // character.
    //
    *pui32Skip = 1;

    //
    // Is this character one of those which maps directly to Unicode?
    //
    if((uint8_t)*pcSrcChar <= 0x7F)
    {
        return((uint32_t)(uint8_t)*pcSrcChar);
    }
    else if(((uint8_t)*pcSrcChar >= 0x80) &&
            ((uint8_t)*pcSrcChar <= 0xBF))
    {
        //
        // This is a character we remap via the global table.
        //
        return((uint32_t)g_pui16WIN1253_Unicode[
               (uint8_t)*pcSrcChar - 0x80]);
    }
    else
    {
        //
        // This is a character we can calculate the Unicode character code for.
        //
        return((uint32_t)((uint8_t)*pcSrcChar) + 0x2D0);
    }
}

//*****************************************************************************
//
//! Maps a WIN1254 encoded character to its Unicode equivalent.
//!
//! \param pcSrcChar is a pointer to a string containing WIN1254 encoded
//!        text.
//! \param ui32Count is the number of bytes in the buffer pointed to by
//!        pcSrcChar.
//! \param pui32Skip points to storage that will be written with the number of
//!        bytes to skip in pcSrcChar to get to the next character in the
//!        buffer.
//!
//! This function may be passed to GrCodepageMapTableSet() in a tCodePointMap
//! structure to map source text in WIN1254 format into 32 bit Unicode
//! typically used by wide character fonts.  Windows-1254 is a codepage commonly
//! used in processing Turkish text.  It is compatible with ISO8859-9 but adds
//! several printable characters in the 0x80-0x9F range.
//!
//! See http://en.wikipedia.org/wiki/Windows-1254 for more information.
//!
//! \return Returns the Unicode character code for the first character in the
//! pcSrcChar string passed.
//
//*****************************************************************************
uint32_t
GrMapWIN1254_Unicode(const char *pcSrcChar, uint32_t ui32Count,
                     uint32_t *pui32Skip)
{
    //
    // Parameter sanity check.
    //
    ASSERT(pui32Skip);
    ASSERT(pcSrcChar);

    //
    // WIN1254 mappings are all 8 bits so we skip a single byte for each
    // character.
    //
    *pui32Skip = 1;

    //
    // Is this character one of those which maps directly to Unicode?
    //
    if(((uint8_t)*pcSrcChar <= 0x7F) ||
       ((uint8_t)*pcSrcChar >= 0xA0))
    {
        return(GrMapISO8859_9_Unicode(pcSrcChar, ui32Count, pui32Skip));
    }
    else
    {
        //
        // This is a character we remap via the global table.
        //
        return((uint32_t)g_pui16WIN1254_Unicode[
               (uint8_t)*pcSrcChar - 0x80]);
    }
}

//*****************************************************************************
//
// Close the Doxygen group.
//! @}
//
//*****************************************************************************
