Edit

kc3-lang/libxkbcommon/src/keysym-case-mappings.c

Branch :

  • Show log

    Commit

  • Author : Pierre Le Marre
    Date : 2025-02-07 16:31:37
    Hash : ce9bcbe0
    Message : scripts: Rename keysyms-related files Previous names were too generic. Fixed by using explicit names and add the `.py` file extension.

  • src/keysym-case-mappings.c
  • // NOTE: This file has been generated automatically by “update-case-mappings.py”.
    //       Do not edit manually!
    
    /*
     * Copyright © 2024 Pierre Le Marre
     * SPDX-License-Identifier: MIT
     */
    
    /* Case mappings for Unicode 16.0
     *
     * There are two kinds of keysyms to consider:
     * • Legacy keysyms: their case mappings is located at `data/keysyms.yaml`.
     * • Unicode keysyms: their case mappings come from the ICU library.
     *
     * These mappings would create huge lookup tables if done naively. Fortunately,
     * we can observe that if we compute only the *difference* between a keysym and
     * its corresponding case mapping, there are a lot of repetitions that can be
     * efficiently compressed.
     *
     * The idea for the compression is, for each kind of keysyms:
     * 1. Compute the deltas between the keysyms and their case mappings.
     * 2. Split the delta array in chunks of a given size.
     * 3. Rearrange the order of the chunks in order to optimize consecutive
     *    chunks overlap.
     * 4. Create a data table with the reordered chunks and an index table that
     *    maps the original chunk index to its offset in the data table.
     *
     * Trivial example (chunk size: 4, from step 2):
     *
     * [1, 2, 3, 4, 2, 3, 4, 5, 0, 1, 2, 3]          # source data
     * -> [[1, 2, 3, 4], [2, 3, 4, 5], [0, 1, 2, 3]] # make chunks
     * -> [[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5]] # rearrange to have best overlaps
     * -> {data: [0, 1, 2, 3, 4, 5], offsets: [1, 2, 0]} # overlap chunks & compute
     *                                                   # their offsets
     *
     * Then we can retrieve the data from the original array at index i with the
     * following formula:
     *
     *     mask = (1 << chunk_size) - 1;
     *     original[i] = data[offsets[i >> chunk_size] + (i & mask)];
     *
     * Since the index array is itself quite repetitive with the real data, we apply
     * the compression a second time to the offsets table.
     *
     * The complete algorithm optimizes the chunk sizes for both arrays in order to
     * get the lowest total data size.
     *
     * There are 6 resulting arrays, 3 for each kind of keysyms:
     * 1. The data array. Each item is either:
     *    • 0, if the keysym is not cased.
     *    • A delta to lower case.
     *    • A delta to upper case.
     *    • For some special cases, there are both a lower *and* an upper case
     *      mapping. The delta is identical in both cases.
     * 2. The 1st offsets array, that provides offsets into the data array.
     * 3. The 2nd offsets array, that provides offsets into the 1st index array.
     *
     * Finally, given the chunks sizes `cs_data` and `cs_offsets`:
     * 1. We compute the corresponding masks:
     *    • `mask_data = (1 << cs_data) - 1` and
     *    • `mask_offsets = (1 << cs_offsets) - 1`.
     * 2. We can retrieve the case mapping of a keysyms `ks` with the following
     *    formula:
     *
     *     data[
     *         offsets1[
     *             offsets2[ks >> (cs_data + cs_offsets)] +
     *             ((ks >> cs_data) & mask_offsets)
     *         ] +
     *         (ks & mask_data)
     *     ];
     */
    
    #include "config.h"
    
    #include <stdint.h>
    #include <stdbool.h>
    #include <string.h>
    #include "xkbcommon/xkbcommon.h"
    #include "utils.h"
    #include "keysym.h"
    
    struct CaseMappings{
        bool lower:1;
        bool upper:1;
        int32_t offset:30;
    };
    
    static const struct CaseMappings legacy_keysym_data[47] = {
        {0, 1, 0x0000000}, {1, 0, 0x0000010}, {0, 0, 0x0000000}, {0, 0, 0x0000000},
        {1, 0, 0x0000020}, {0, 1,-0x1001dbf}, {1, 0, 0x0000020}, {1, 0, 0x0000020},
        {0, 0, 0x0000000}, {0, 1,-0x0000717}, {0, 1, 0x0000020}, {0, 0, 0x0000000},
        {0, 1, 0x0000020}, {0, 1, 0x0000020}, {0, 1,-0x00012bf}, {0, 1, 0x0000000},
        {0, 0, 0x0000000}, {1, 0, 0x0000010}, {1, 0, 0x0000010}, {0, 1,-0x0fff89b},
        {0, 0, 0x0000000}, {0, 1, 0x0000010}, {0, 0, 0x0000000}, {0, 1,-0x0000010},
        {0, 1,-0x0000010}, {0, 1, 0x0000000}, {0, 1, 0x0000010}, {0, 1, 0x0000010},
        {1, 0, 0x0000002}, {0, 0, 0x0000000}, {1, 0,-0x0000010}, {1, 0,-0x0000010},
        {1, 0,-0x00012bf}, {1, 0,-0x0000020}, {1, 0,-0x0000020}, {0, 1,-0x0000020},
        {0, 1,-0x0000020}, {0, 0, 0x0000000}, {1, 0,-0x0000240}, {0, 0, 0x0000000},
        {0, 1, 0x0000002}, {0, 0, 0x0000000}, {0, 1, 0x0000270}, {0, 1, 0x0000020},
        {0, 1, 0x0000021}, {1, 0, 0x0000001}, {0, 1, 0x0000001}
    };
    
    static const uint8_t legacy_keysym_offsets1[540] = {
        0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
        0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
        0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
        0x0002, 0x0002, 0x0003, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006,
        0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0007, 0x0002, 0x0002, 0x000b, 0x000c,
        0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c,
        0x000c, 0x000a, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
        0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0010, 0x0011,
        0x0011, 0x0010, 0x0011, 0x0010, 0x0002, 0x0002, 0x0014, 0x001a, 0x001a, 0x0019,
        0x001a, 0x0019, 0x0002, 0x0002, 0x0003, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006,
        0x0006, 0x0006, 0x0006, 0x0007, 0x0006, 0x0006, 0x0006, 0x0002, 0x0002, 0x0002,
        0x000b, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x002b,
        0x000c, 0x000c, 0x000c, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
        0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
        0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
        0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
        0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
        0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
        0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0013, 0x0002, 0x0002,
        0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
        0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
        0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x002d, 0x0020,
        0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
        0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0000, 0x0010, 0x0001,
        0x0002, 0x0011, 0x0001, 0x0002, 0x0002, 0x0014, 0x0014, 0x0015, 0x0002, 0x001a,
        0x001b, 0x0027, 0x0007, 0x0002, 0x0002, 0x0003, 0x0002, 0x0002, 0x0007, 0x0003,
        0x0003, 0x0006, 0x0002, 0x0002, 0x0003, 0x0002, 0x0003, 0x0007, 0x000a, 0x0002,
        0x0002, 0x000b, 0x0002, 0x0002, 0x000a, 0x000b, 0x000b, 0x000c, 0x0002, 0x0002,
        0x000b, 0x0002, 0x000b, 0x000a, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
        0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
        0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x000f, 0x0002, 0x0002, 0x0002, 0x0002,
        0x0008, 0x0002, 0x0002, 0x000f, 0x0002, 0x0002, 0x0006, 0x0006, 0x0006, 0x0006,
        0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0007, 0x0006, 0x0006,
        0x0006, 0x0004, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c,
        0x000c, 0x000c, 0x000c, 0x000a, 0x000c, 0x000c, 0x000c, 0x000d, 0x0002, 0x0002,
        0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
        0x0002, 0x0002, 0x0002, 0x0002, 0x0010, 0x0002, 0x0002, 0x0001, 0x0025, 0x0010,
        0x0001, 0x0002, 0x0014, 0x0002, 0x0002, 0x0015, 0x0029, 0x0014, 0x0015, 0x0002,
        0x0002, 0x0002, 0x0003, 0x0007, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
        0x0003, 0x0002, 0x0007, 0x0002, 0x0003, 0x0007, 0x0002, 0x0002, 0x000b, 0x000a,
        0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x000b, 0x0002, 0x000a, 0x0002,
        0x000b, 0x000a, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
        0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0010, 0x0010,
        0x0010, 0x0001, 0x0010, 0x0011, 0x0001, 0x0011, 0x0014, 0x0014, 0x0014, 0x0015,
        0x0014, 0x001a, 0x0015, 0x001a, 0x0007, 0x0003, 0x0003, 0x0007, 0x0007, 0x0007,
        0x0007, 0x0003, 0x0006, 0x0007, 0x0003, 0x0002, 0x0006, 0x0003, 0x0002, 0x0007,
        0x000a, 0x000b, 0x000b, 0x000a, 0x000a, 0x000a, 0x000a, 0x000b, 0x000c, 0x000a,
        0x000b, 0x0002, 0x000c, 0x000b, 0x0002, 0x000a, 0x0002, 0x0002, 0x0002, 0x0002,
        0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
        0x0002, 0x0002, 0x0016, 0x0017, 0x0017, 0x0017, 0x0017, 0x0017, 0x0017, 0x0017,
        0x001d, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x0023, 0x0023,
        0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0023,
        0x0023, 0x0023, 0x0023, 0x0023, 0x0021, 0x0021, 0x0021, 0x0021, 0x0021, 0x0021,
        0x0021, 0x0021, 0x0021, 0x0021, 0x0021, 0x0021, 0x0021, 0x0021, 0x0021, 0x0021
    };
    
    static const uint16_t legacy_keysym_offsets2[40] = {
        0x0000, 0x011c, 0x007b, 0x019c, 0x007b, 0x015c, 0x007b, 0x00dc, 0x007b, 0x007b,
        0x007b, 0x007b, 0x007b, 0x01dc, 0x007b, 0x003e, 0x007b, 0x0080, 0x007b, 0x007b,
        0x007b, 0x007b, 0x007b, 0x007b, 0x007b, 0x007b, 0x007b, 0x007b, 0x007b, 0x007b,
        0x007b, 0x007b, 0x007b, 0x007b, 0x007b, 0x007b, 0x007b, 0x007b, 0x007b, 0x00bc
    };
    
    static inline const struct CaseMappings *
    get_legacy_keysym_entry(xkb_keysym_t ks)
    {
        return &legacy_keysym_data[legacy_keysym_offsets1[legacy_keysym_offsets2[ks >> 7] + ((ks >> 1) & 0x3f)] + (ks & 0x01)];
    }
    
    static const struct CaseMappings unicode_data[1004] = {
        {0, 1,-0x0080}, {0, 1,-0x0080}, {0, 1,-0x0070}, {0, 1,-0x0070},
        {0, 1,-0x007e}, {0, 1,-0x007e}, {0, 0, 0x0000}, {0, 0, 0x0000},
        {0, 1, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000},
        {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000},
        {0, 0, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000},
        {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1,-0xa515}, {0, 1,-0xa512},
        {0, 1, 0x0000}, {1, 0, 0x0002}, {1, 1, 0x0001}, {0, 1, 0x0002},
        {1, 0, 0x0001}, {0, 1, 0x0001}, {1, 0,-0x0061}, {1, 0,-0x0038},
        {1, 0, 0x0020}, {1, 0, 0x0020}, {0, 0, 0x0000}, {1, 0, 0x0020},
        {1, 0, 0x0020}, {1, 0, 0x0020}, {1, 0, 0x0020}, {1, 0, 0x0020},
        {1, 0, 0x0020}, {1, 0, 0x0020}, {1, 0, 0x0020}, {0, 1,-0x1dbf},
        {0, 1, 0x0001}, {1, 0, 0x00da}, {0, 1, 0x0000}, {0, 1, 0x0000},
        {1, 0, 0x0001}, {0, 1, 0x0001}, {1, 0, 0x00da}, {1, 0, 0x0001},
        {0, 1, 0x0001}, {1, 0, 0x0001}, {0, 1, 0x0001}, {1, 0,-0xa641},
        {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {1, 0,-0x0008},
        {0, 0, 0x0000}, {1, 0,-0x0008}, {0, 0, 0x0000}, {1, 0,-0x0008},
        {0, 0, 0x0000}, {1, 0,-0x0008}, {1, 0,-0x0008}, {1, 0,-0x004a},
        {1, 0,-0x004a}, {1, 0,-0x0009}, {0, 0, 0x0000}, {0, 1, 0x1c25},
        {0, 0, 0x0000}, {0, 1, 0x0020}, {0, 1, 0x0020}, {0, 1, 0x0020},
        {0, 1, 0x0020}, {0, 1, 0x0020}, {0, 1, 0x0020}, {0, 1, 0x0020},
        {0, 1, 0x0020}, {0, 1,-0x0079}, {0, 1,-0x2a1f}, {0, 1,-0x2a1c},
        {0, 1,-0x2a1e}, {0, 1, 0x00d2}, {0, 1, 0x00ce}, {0, 1, 0x0000},
        {0, 1, 0x00cd}, {0, 1, 0x00cd}, {0, 1,-0xa54b}, {0, 1, 0x0000},
        {0, 1, 0x00cf}, {0, 1,-0xa567}, {0, 1,-0xa528}, {0, 1,-0xa544},
        {0, 1, 0x0000}, {0, 1,-0x29fd}, {0, 1, 0x00d5}, {0, 1, 0x0000},
        {0, 1, 0x0000}, {0, 1, 0x00d6}, {0, 1, 0x0000}, {0, 1, 0x0000},
        {1, 0, 0x0020}, {1, 0, 0x0020}, {1, 0, 0x0020}, {1, 0, 0x0020},
        {1, 0, 0x0020}, {1, 0, 0x0020}, {1, 0, 0x0020}, {0, 0, 0x0000},
        {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000},
        {0, 1,-0x02e7}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 1, 0x0000},
        {0, 1, 0x0000}, {0, 1, 0x0000}, {1, 0, 0x0001}, {0, 1, 0x0001},
        {0, 0, 0x0000}, {1, 0, 0x0000}, {1, 0, 0x0000}, {1, 0, 0x0000},
        {1, 0, 0x0000}, {1, 0, 0x0000}, {0, 0, 0x0000}, {1, 0, 0x0000},
        {0, 0, 0x0000}, {1, 0,-0x20bf}, {1, 0,-0x2046}, {1, 0, 0x0000},
        {1, 0, 0x0000}, {0, 0, 0x0000}, {0, 1, 0x0000}, {0, 0, 0x0000},
        {0, 0, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {1, 0, 0x0000},
        {1, 0, 0x0000}, {1, 0, 0x0000}, {1, 0, 0x0000}, {1, 0, 0x0000},
        {0, 0, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000},
        {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000},
        {0, 1, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000},
        {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {1, 0, 0x001a},
        {1, 0, 0x001a}, {1, 0, 0x001a}, {1, 0, 0x001a}, {1, 0, 0x001a},
        {1, 0, 0x001a}, {1, 0, 0x001a}, {1, 0, 0x001a}, {0, 1,-0x89c2},
        {1, 0, 0x0001}, {0, 1, 0x0001}, {0, 0, 0x0000}, {0, 0, 0x0000},
        {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000},
        {1, 0, 0x0026}, {0, 0, 0x0000}, {1, 0,-0x0008}, {1, 0,-0x0008},
        {1, 0,-0x0064}, {1, 0,-0x0064}, {0, 0, 0x0000}, {0, 0, 0x0000},
        {0, 0, 0x0000}, {0, 0, 0x0000}, {1, 0, 0x0030}, {1, 0, 0x0030},
        {1, 0, 0x0030}, {1, 0, 0x0030}, {1, 0, 0x0030}, {1, 0, 0x0030},
        {1, 0, 0x0030}, {1, 0, 0x0030}, {0, 0, 0x0000}, {0, 1, 0x0001},
        {1, 0, 0x0001}, {0, 1, 0x0001}, {1, 0,-0xa567}, {1, 0, 0x0001},
        {0, 1, 0x0001}, {0, 0, 0x0000}, {0, 0, 0x0000}, {1, 0, 0x0000},
        {0, 0, 0x0000}, {0, 0, 0x0000}, {1, 0, 0x0000}, {1, 0, 0x0000},
        {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000},
        {0, 0, 0x0000}, {0, 0, 0x0000}, {1, 0, 0x0001}, {0, 1, 0x0001},
        {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000},
        {1, 0, 0x0002}, {1, 1, 0x0001}, {0, 1, 0x0002}, {1, 0, 0x0002},
        {1, 1, 0x0001}, {0, 1, 0x0002}, {1, 0, 0x0001}, {0, 1, 0x0001},
        {1, 0, 0x0001}, {0, 1, 0x0001}, {1, 0,-0x0030}, {1, 0,-0xa543},
        {1, 0,-0x8a38}, {1, 0, 0x0001}, {0, 1, 0x003e}, {0, 1, 0x0039},
        {1, 0, 0x0000}, {1, 0, 0x0000}, {1, 0, 0x0000}, {0, 1, 0x002f},
        {0, 1, 0x0036}, {0, 1, 0x0008}, {0, 1, 0x0008}, {0, 1, 0x0008},
        {0, 1, 0x0008}, {0, 1, 0x0008}, {0, 1, 0x0008}, {0, 0, 0x0000},
        {0, 0, 0x0000}, {0, 1, 0x0000}, {1, 0, 0x0000}, {1, 0, 0x0000},
        {1, 0, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000},
        {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {1, 0, 0x0000},
        {1, 0, 0x0000}, {1, 0, 0x0000}, {1, 0, 0x0000}, {1, 0, 0x0000},
        {1, 0, 0x0000}, {1, 0, 0x0000}, {1, 0, 0x0000}, {0, 0, 0x0000},
        {1, 0, 0x0000}, {1, 0, 0x0000}, {1, 0, 0x0000}, {1, 0, 0x0000},
        {0, 0, 0x0000}, {1, 0, 0x0000}, {1, 0, 0x0000}, {1, 0, 0x0000},
        {1, 0, 0x0000}, {1, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000},
        {1, 0, 0x0000}, {1, 0, 0x0000}, {1, 0, 0x0000}, {1, 0, 0x0000},
        {1, 0, 0x0000}, {1, 0, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000},
        {1, 0, 0x0000}, {0, 1, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000},
        {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 1, 0x0000}, {0, 1,-0x0082},
        {0, 1,-0x0082}, {0, 1,-0x0082}, {0, 0, 0x0000}, {1, 0, 0x0074},
        {1, 0,-0x00c7}, {0, 1, 0x00e8}, {1, 0, 0x0001}, {0, 1, 0x0001},
        {1, 0, 0x0001}, {0, 1, 0x0001}, {1, 0, 0x0001}, {0, 1, 0x0001},
        {1, 0, 0x00da}, {1, 0, 0x0001}, {1, 0, 0x000f}, {1, 0, 0x0001},
        {0, 1, 0x0001}, {1, 0, 0x0001}, {0, 1, 0x0001}, {1, 0, 0x0001},
        {0, 1, 0x0001}, {1, 0, 0x0001}, {0, 1, 0x0001}, {1, 0, 0x0001},
        {0, 1, 0x0001}, {1, 0,-0x2a1c}, {1, 0,-0x29fd}, {1, 0,-0x2a1f},
        {0, 1, 0x0001}, {0, 1, 0x0000}, {1, 0, 0x0001}, {0, 1, 0x0001},
        {1, 0, 0x0001}, {0, 1, 0x0001}, {1, 0, 0x0001}, {0, 1, 0x0001},
        {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000},
        {1, 0, 0x0000}, {0, 0, 0x0000}, {1, 0, 0x0000}, {1, 0, 0x0000},
        {1, 0, 0x001c}, {1, 0, 0x0000}, {0, 1, 0x0000}, {0, 0, 0x0000},
        {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 1, 0x0001}, {1, 0,-0x0007},
        {1, 0, 0x0001}, {0, 1, 0x0001}, {0, 1, 0x0000}, {1, 0,-0x0082},
        {1, 0,-0x0082}, {1, 0,-0x0082}, {0, 1, 0x0000}, {1, 0, 0x0001},
        {0, 1, 0x0001}, {1, 0, 0x0001}, {0, 1, 0x0001}, {1, 0, 0x0001},
        {0, 1, 0x0001}, {0, 0, 0x0000}, {0, 0, 0x0000}, {1, 0, 0x0001},
        {0, 1, 0x0001}, {1, 0, 0x0001}, {0, 1, 0x0001}, {1, 0, 0x0001},
        {0, 1, 0x0001}, {0, 1, 0x004f}, {1, 0, 0x0001}, {0, 1, 0x0001},
        {1, 0,-0xa544}, {1, 0,-0xa54f}, {1, 0,-0xa54b}, {1, 0,-0xa541},
        {1, 0,-0xa544}, {0, 1, 0x0000}, {0, 1, 0x0030}, {0, 1, 0x0030},
        {0, 1, 0x0030}, {0, 1, 0x0030}, {0, 1, 0x0030}, {0, 1, 0x0030},
        {0, 1, 0x0030}, {0, 1, 0x0030}, {0, 1, 0x0000}, {0, 1,-0x8a04},
        {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1,-0x0ee6},
        {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0020}, {0, 1, 0x0020},
        {0, 1, 0x0020}, {0, 1, 0x0020}, {0, 1, 0x0020}, {0, 1, 0x0020},
        {0, 1, 0x0020}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000},
        {0, 0, 0x0000}, {0, 0, 0x0000}, {1, 0, 0x1c60}, {0, 0, 0x0000},
        {0, 0, 0x0000}, {0, 1, 0x0000}, {0, 1,-0x0009}, {0, 1, 0x0000},
        {0, 0, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000},
        {0, 1, 0x003b}, {0, 1, 0x0000}, {0, 1, 0x0000}, {1, 0,-0x1dbf},
        {0, 1, 0x0000}, {0, 1,-0x0008}, {0, 1, 0x0000}, {0, 1,-0x0008},
        {0, 1, 0x0000}, {0, 1,-0x0008}, {0, 1, 0x0000}, {0, 1,-0x0008},
        {0, 1,-0x0008}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000},
        {0, 1,-0x0007}, {0, 1, 0x0000}, {0, 1, 0x0000}, {1, 0, 0x0001},
        {0, 1, 0x0001}, {1, 0, 0x0001}, {0, 1, 0x0001}, {1, 0, 0x0001},
        {0, 1, 0x0001}, {1, 0, 0x0001}, {0, 1, 0x0001}, {0, 1, 0x000f},
        {1, 0, 0x1c60}, {1, 0, 0x1c60}, {1, 0, 0x1c60}, {1, 0, 0x1c60},
        {1, 0, 0x1c60}, {1, 0, 0x1c60}, {1, 0, 0x1c60}, {1, 0, 0x1c60},
        {0, 0, 0x0000}, {1, 0, 0x1c60}, {0, 1,-0x0008}, {0, 1,-0x0008},
        {0, 1,-0x0008}, {0, 1,-0x0008}, {0, 1,-0x0008}, {0, 1,-0x0008},
        {0, 1,-0x0008}, {0, 1,-0x0008}, {0, 0, 0x0000}, {0, 0, 0x0000},
        {1, 0,-0x0008}, {1, 0,-0x0008}, {1, 0,-0x0008}, {1, 0,-0x0008},
        {1, 0,-0x0008}, {1, 0,-0x0008}, {1, 0,-0x0008}, {1, 0,-0x0008},
        {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 1, 0x1c60}, {0, 1, 0x1c60},
        {0, 1, 0x1c60}, {0, 1, 0x1c60}, {0, 1, 0x1c60}, {0, 1, 0x1c60},
        {0, 1, 0x1c60}, {0, 1, 0x1c60}, {0, 0, 0x0000}, {0, 1, 0x1c60},
        {1, 0, 0x0022}, {1, 0, 0x0022}, {1, 0, 0x0022}, {1, 0, 0x0022},
        {1, 0, 0x0022}, {1, 0, 0x0022}, {1, 0, 0x0022}, {1, 0, 0x0022},
        {0, 1, 0x0022}, {0, 1, 0x0022}, {0, 1, 0x0022}, {0, 1, 0x0022},
        {0, 1, 0x0022}, {0, 1, 0x0022}, {0, 1, 0x0022}, {0, 1, 0x0022},
        {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000},
        {1, 0, 0x0001}, {0, 1, 0x0001}, {1, 0, 0x0001}, {0, 1, 0x0001},
        {0, 0, 0x0000}, {0, 1, 0x0000}, {0, 0, 0x0000}, {0, 1, 0x0000},
        {1, 0, 0x0001}, {0, 1, 0x0001}, {1, 0, 0x0001}, {0, 1, 0x0001},
        {1, 0,-0x8a04}, {1, 0, 0x0001}, {0, 1, 0x0001}, {1, 0,-0x29f7},
        {1, 0,-0x0ee6}, {1, 0,-0x29e7}, {0, 1, 0x2a2b}, {0, 1, 0x2a28},
        {1, 0, 0x0001}, {0, 1, 0x001a}, {0, 1, 0x001a}, {0, 1, 0x001a},
        {0, 1, 0x001a}, {0, 1, 0x001a}, {0, 1, 0x001a}, {0, 1, 0x001a},
        {0, 1, 0x001a}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000},
        {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 1,-0x0054},
        {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 1,-0x0008}, {0, 1,-0x0008},
        {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000},
        {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 0, 0x0000},
        {0, 1, 0x0000}, {0, 0, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000},
        {0, 1, 0x0000}, {0, 1, 0x0000}, {1, 0, 0x0000}, {1, 0, 0x0000},
        {0, 0, 0x0000}, {1, 0, 0x0000}, {1, 0, 0x0000}, {1, 0, 0x0000},
        {0, 1, 0x0000}, {0, 0, 0x0000}, {1, 0, 0x0000}, {0, 0, 0x0000},
        {0, 0, 0x0000}, {1, 0, 0x0040}, {1, 0, 0x0040}, {1, 0, 0x0040},
        {1, 0, 0x0040}, {1, 0, 0x0040}, {1, 0, 0x0040}, {1, 0, 0x0040},
        {1, 0, 0x0040}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000},
        {0, 0, 0x0000}, {0, 0, 0x0000}, {1, 0, 0x0000}, {0, 1, 0x0000},
        {0, 1, 0x0000}, {1, 0, 0x2a2b}, {1, 0, 0x0001}, {0, 1, 0x0001},
        {1, 0,-0x00a3}, {1, 0, 0x2a28}, {0, 1,-0x2a3f}, {1, 0, 0x0001},
        {0, 1, 0x0001}, {1, 0,-0x00c3}, {1, 0, 0x0045}, {1, 0, 0x0047},
        {1, 0, 0x0001}, {0, 1, 0x0001}, {0, 1,-0x00a3}, {0, 1,-0xa641},
        {1, 0, 0x00d3}, {1, 0, 0x00d5}, {0, 1,-0x0082}, {1, 0, 0x00d6},
        {0, 1, 0x0040}, {0, 1, 0x0040}, {0, 1, 0x0040}, {0, 1, 0x0040},
        {0, 1, 0x0040}, {0, 1, 0x0040}, {0, 1, 0x0040}, {0, 1, 0x0040},
        {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000},
        {0, 0, 0x0000}, {0, 1, 0x1c60}, {0, 0, 0x0000}, {0, 0, 0x0000},
        {0, 1, 0x0020}, {0, 1, 0x0020}, {0, 1, 0x001f}, {0, 1, 0x0020},
        {0, 1, 0x0020}, {0, 1, 0x0020}, {0, 1, 0x0020}, {0, 1, 0x0020},
        {0, 1, 0x0040}, {0, 1, 0x003f}, {0, 1, 0x003f}, {1, 0, 0x0008},
        {1, 0, 0x0008}, {1, 0, 0x0008}, {1, 0, 0x0008}, {1, 0, 0x0008},
        {1, 0, 0x0008}, {0, 0, 0x0000}, {0, 0, 0x0000}, {1, 0, 0x0000},
        {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000},
        {1, 0, 0x0000}, {0, 0, 0x0000}, {1, 0,-0x1d5d}, {0, 0, 0x0000},
        {1, 0,-0xa512}, {1, 0,-0xa52a}, {1, 0,-0xa515}, {1, 0, 0x03a0},
        {1, 0, 0x0001}, {0, 1, 0x0001}, {1, 0, 0x0001}, {0, 1, 0x0001},
        {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000},
        {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 1, 0x001c}, {0, 0, 0x0000},
        {1, 0, 0x0028}, {1, 0, 0x0028}, {1, 0, 0x0028}, {1, 0, 0x0028},
        {1, 0, 0x0028}, {1, 0, 0x0028}, {1, 0, 0x0028}, {1, 0, 0x0028},
        {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000},
        {1, 0, 0x0001}, {0, 1, 0x0001}, {1, 0,-0xa528}, {0, 1, 0x0000},
        {0, 0, 0x0000}, {0, 1, 0x0028}, {0, 1, 0x0028}, {0, 1, 0x0028},
        {0, 1, 0x0028}, {0, 1, 0x0028}, {0, 1, 0x0028}, {0, 1, 0x0028},
        {0, 1, 0x0028}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000},
        {0, 0, 0x0000}, {1, 0, 0x0027}, {1, 0, 0x0027}, {1, 0, 0x0027},
        {0, 0, 0x0000}, {1, 0, 0x0027}, {1, 0, 0x0027}, {1, 0, 0x0027},
        {1, 0, 0x0027}, {1, 0, 0x0027}, {1, 0, 0x0027}, {1, 0, 0x0027},
        {1, 0, 0x0027}, {0, 0, 0x0000}, {1, 0, 0x0027}, {1, 0, 0x0027},
        {0, 0, 0x0000}, {0, 1, 0x0027}, {0, 1, 0x0027}, {0, 0, 0x0000},
        {0, 1, 0x0027}, {0, 1, 0x0027}, {0, 1, 0x0027}, {0, 1, 0x0027},
        {0, 1, 0x0027}, {0, 1, 0x0027}, {0, 1, 0x0027}, {0, 1, 0x0027},
        {0, 0, 0x0000}, {0, 1, 0x0027}, {0, 1, 0x0027}, {0, 0, 0x0000},
        {0, 0, 0x0000}, {0, 0, 0x0000}, {1, 0,-0x2a1e}, {0, 1, 0x0000},
        {1, 0, 0x0001}, {0, 1, 0x0001}, {0, 1, 0x0000}, {1, 0, 0x0001},
        {0, 1, 0x0001}, {0, 1, 0x0000}, {0, 0, 0x0000}, {1, 0, 0x0001},
        {0, 1, 0x0001}, {0, 1, 0x0000}, {0, 1,-0x0038}, {0, 1, 0x00da},
        {0, 1, 0x0045}, {0, 1, 0x00d9}, {0, 1, 0x00d9}, {0, 1, 0x0047},
        {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000},
        {0, 1, 0x0000}, {0, 1,-0x29e7}, {0, 1, 0x0000}, {0, 1, 0x0000},
        {0, 1, 0x00ca}, {0, 1, 0x0000}, {0, 1, 0x00cb}, {0, 1,-0xa54f},
        {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x03a0},
        {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000},
        {0, 1, 0x0000}, {0, 0, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000},
        {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000},
        {1, 0,-0x2a3f}, {1, 0,-0x2a3f}, {0, 1,-0x0008}, {0, 1,-0x0008},
        {0, 1, 0x0000}, {0, 1,-0x0009}, {0, 1, 0x0000}, {0, 0, 0x0000},
        {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x00db}, {0, 1, 0x0000},
        {0, 0, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000},
        {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1,-0x8a38},
        {0, 1, 0x0000}, {0, 1,-0x0bc0}, {0, 1,-0x0bc0}, {0, 1,-0x0bc0},
        {0, 1,-0x0bc0}, {0, 1,-0x0bc0}, {0, 1,-0x0bc0}, {0, 1,-0x0bc0},
        {0, 1,-0x0bc0}, {0, 0, 0x0000}, {0, 1, 0x0000}, {0, 1,-0x0bc0},
        {0, 1,-0x0bc0}, {0, 1,-0x0bc0}, {1, 0,-0x0bc0}, {1, 0,-0x0bc0},
        {1, 0,-0x0bc0}, {1, 0,-0x0bc0}, {1, 0,-0x0bc0}, {1, 0,-0x0bc0},
        {1, 0,-0x0bc0}, {1, 0,-0x0bc0}, {0, 0, 0x0000}, {0, 0, 0x0000},
        {1, 0,-0x0bc0}, {1, 0,-0x0bc0}, {1, 0,-0x0bc0}, {0, 1, 0x0056},
        {0, 1, 0x0050}, {0, 1,-0x0007}, {0, 1, 0x0074}, {1, 0,-0x003c},
        {0, 1, 0x0060}, {0, 0, 0x0000}, {1, 0, 0x0001}, {0, 1, 0x0001},
        {1, 0, 0x0001}, {0, 1, 0x0001}, {0, 1,-0x0030}, {0, 1, 0x0000},
        {1, 0, 0x0001}, {0, 1, 0x0001}, {1, 0, 0x0001}, {0, 1, 0x0001},
        {0, 1, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000},
        {1, 0,-0x0080}, {1, 0,-0x0080}, {1, 0,-0x007e}, {1, 0,-0x007e},
        {1, 0,-0x0009}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000},
        {1, 0,-0x0079}, {1, 0, 0x0001}, {0, 1, 0x0001}, {1, 0, 0x0001},
        {0, 1, 0x0001}, {1, 0, 0x0001}, {0, 1, 0x0001}, {0, 1, 0x012c},
        {1, 0,-0x0056}, {1, 0,-0x0056}, {1, 0,-0x0056}, {1, 0,-0x0056},
        {1, 0,-0x0009}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000},
        {1, 0,-0x0008}, {1, 0,-0x0008}, {1, 0,-0x0070}, {1, 0,-0x0070},
        {1, 0,-0x0007}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000},
        {0, 1,-0x00c3}, {1, 0, 0x00d2}, {1, 0, 0x0001}, {0, 1, 0x0001},
        {1, 0, 0x0001}, {0, 1, 0x0001}, {1, 0, 0x00ce}, {1, 0, 0x0001},
        {0, 1,-0x004a}, {0, 1,-0x004a}, {0, 1,-0x0056}, {0, 1,-0x0056},
        {0, 1,-0x0056}, {0, 1,-0x0056}, {0, 1,-0x0064}, {0, 1,-0x0064},
        {0, 1, 0x0001}, {1, 0, 0x00cd}, {1, 0, 0x00cd}, {1, 0, 0x0001},
        {0, 1, 0x0001}, {0, 1, 0x0000}, {1, 0, 0x004f}, {1, 0, 0x00ca},
        {0, 1, 0x0001}, {1, 0, 0x00d9}, {1, 0, 0x00d9}, {1, 0, 0x0001},
        {0, 1, 0x0001}, {1, 0, 0x0001}, {0, 1, 0x0001}, {1, 0, 0x00db},
        {0, 1, 0x0010}, {0, 1, 0x0010}, {0, 1, 0x0010}, {0, 1, 0x0010},
        {0, 1, 0x0010}, {0, 1, 0x0010}, {0, 1, 0x0010}, {0, 1, 0x0010},
        {0, 1, 0x0050}, {0, 1, 0x0050}, {0, 1, 0x0050}, {0, 1, 0x0050},
        {0, 1, 0x0050}, {0, 1, 0x0050}, {0, 1, 0x0050}, {0, 1, 0x0050},
        {0, 1, 0x00d1}, {0, 1, 0x00d3}, {0, 1,-0xa544}, {0, 1,-0x29f7},
        {0, 1,-0xa541}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x00d3},
        {0, 1, 0x00da}, {0, 1, 0x0000}, {0, 1,-0xa543}, {0, 1, 0x00da},
        {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1,-0xa52a},
        {0, 1, 0x186e}, {0, 1, 0x186d}, {0, 1, 0x1864}, {0, 1, 0x1862},
        {0, 1, 0x1862}, {0, 1, 0x1863}, {0, 1, 0x185c}, {0, 1, 0x1825},
        {0, 1, 0x97d0}, {0, 1, 0x97d0}, {0, 1, 0x97d0}, {0, 1, 0x97d0},
        {0, 1, 0x97d0}, {0, 1, 0x97d0}, {0, 1, 0x97d0}, {0, 1, 0x97d0},
        {1, 0, 0x0010}, {1, 0, 0x0010}, {1, 0, 0x0010}, {1, 0, 0x0010},
        {1, 0, 0x0010}, {1, 0, 0x0010}, {1, 0, 0x0010}, {1, 0, 0x0010},
        {1, 0, 0x0020}, {1, 0, 0x0020}, {1, 0, 0x0020}, {1, 0, 0x0020},
        {0, 1, 0x0026}, {0, 1, 0x0025}, {0, 1, 0x0025}, {0, 1, 0x0025},
        {1, 0, 0x0025}, {1, 0, 0x0025}, {1, 0, 0x0025}, {0, 0, 0x0000},
        {1, 0, 0x0040}, {0, 0, 0x0000}, {1, 0, 0x003f}, {1, 0, 0x003f},
        {1, 0, 0x0050}, {1, 0, 0x0050}, {1, 0, 0x0050}, {1, 0, 0x0050},
        {1, 0, 0x0050}, {1, 0, 0x0050}, {1, 0, 0x0050}, {1, 0, 0x0050},
        {1, 0, 0x00cb}, {1, 0, 0x0001}, {0, 1, 0x0001}, {1, 0, 0x00cd},
        {1, 0, 0x00cf}, {0, 1,-0x0061}, {1, 0, 0x00d3}, {1, 0, 0x00d1},
        {1, 0, 0x97d0}, {1, 0, 0x97d0}, {1, 0, 0x97d0}, {1, 0, 0x97d0},
        {1, 0, 0x97d0}, {1, 0, 0x97d0}, {1, 0, 0x97d0}, {1, 0, 0x97d0}
    };
    
    static const uint16_t unicode_offsets1[907] = {
        0x0096, 0x0009, 0x000e, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
        0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
        0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
        0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x009d, 0x00a3, 0x00a3, 0x00a3, 0x0211,
        0x0211, 0x0211, 0x0217, 0x0009, 0x0009, 0x01de, 0x01de, 0x01de, 0x01de, 0x01e0,
        0x0268, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
        0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
        0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x01c0, 0x01c0, 0x01c0,
        0x01c0, 0x01c2, 0x0195, 0x031d, 0x031d, 0x031d, 0x031d, 0x031d, 0x0322, 0x0107,
        0x0107, 0x0107, 0x00ff, 0x0095, 0x0095, 0x0103, 0x0107, 0x0107, 0x011c, 0x02fc,
        0x0095, 0x0095, 0x0107, 0x0107, 0x0107, 0x00ff, 0x0095, 0x0095, 0x0150, 0x00cd,
        0x010f, 0x011c, 0x0229, 0x02fd, 0x0095, 0x0107, 0x0107, 0x0107, 0x00ff, 0x0095,
        0x0095, 0x0095, 0x0095, 0x0095, 0x0095, 0x0095, 0x0095, 0x0095, 0x0095, 0x0095,
        0x0095, 0x0095, 0x0095, 0x0095, 0x0186, 0x0095, 0x0315, 0x0095, 0x0095, 0x0095,
        0x0095, 0x0095, 0x0095, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
        0x0009, 0x0022, 0x0023, 0x0023, 0x006c, 0x0048, 0x0049, 0x0049, 0x0192, 0x0009,
        0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
        0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x03e4,
        0x03e4, 0x03e4, 0x03e4, 0x03e4, 0x03e4, 0x03e4, 0x03e4, 0x03e4, 0x03e4, 0x027b,
        0x00f5, 0x01e8, 0x01e8, 0x01e8, 0x01e8, 0x01ee, 0x01f0, 0x01f0, 0x01f0, 0x01f4,
        0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
        0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
        0x0009, 0x0009, 0x0009, 0x0023, 0x0023, 0x0023, 0x0023, 0x0049, 0x0049, 0x0049,
        0x0049, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
        0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0225, 0x0095, 0x0095,
        0x0095, 0x0095, 0x0095, 0x0300, 0x009a, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
        0x0009, 0x0009, 0x0009, 0x0022, 0x0023, 0x0023, 0x006c, 0x0048, 0x0049, 0x0049,
        0x0192, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0006, 0x006f, 0x0006, 0x0023,
        0x0023, 0x0068, 0x0024, 0x0049, 0x0049, 0x018e, 0x004a, 0x0095, 0x02ff, 0x0095,
        0x0096, 0x000c, 0x009a, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
        0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
        0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x03ac,
        0x00ab, 0x032a, 0x032a, 0x032a, 0x032a, 0x032a, 0x032f, 0x0009, 0x0009, 0x0009,
        0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x01b7, 0x01b7, 0x01b7, 0x01b7, 0x01b7,
        0x0167, 0x0009, 0x0009, 0x01b7, 0x01b7, 0x01b7, 0x0290, 0x0009, 0x0009, 0x0009,
        0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x021a,
        0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0169, 0x0128, 0x00ae, 0x03cc, 0x0067,
        0x0023, 0x0020, 0x03c4, 0x018d, 0x0049, 0x0270, 0x0274, 0x00ee, 0x01b7, 0x01b7,
        0x01b7, 0x0337, 0x015e, 0x0095, 0x0095, 0x02fc, 0x0103, 0x0107, 0x0107, 0x008f,
        0x0095, 0x0095, 0x0096, 0x0101, 0x0107, 0x0107, 0x0108, 0x0095, 0x0095, 0x0095,
        0x0300, 0x0107, 0x0107, 0x0107, 0x0093, 0x0095, 0x0095, 0x02fe, 0x0122, 0x0009,
        0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0095, 0x0095, 0x0095, 0x0095, 0x0095,
        0x0095, 0x0095, 0x0097, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
        0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
        0x0009, 0x023d, 0x023d, 0x023d, 0x023d, 0x023d, 0x023d, 0x0242, 0x0009, 0x0260,
        0x0260, 0x0260, 0x0260, 0x0260, 0x0260, 0x0265, 0x0009, 0x03d4, 0x03d4, 0x0023,
        0x0023, 0x0023, 0x0023, 0x0049, 0x0049, 0x0049, 0x0049, 0x0394, 0x0394, 0x01b7,
        0x01b7, 0x01b7, 0x01b7, 0x00ac, 0x016d, 0x01b7, 0x01b7, 0x01b7, 0x01b7, 0x01b7,
        0x01b7, 0x013a, 0x01b8, 0x01b7, 0x01b7, 0x01b7, 0x01b7, 0x01b7, 0x01b7, 0x00bd,
        0x00be, 0x00be, 0x00be, 0x00bf, 0x0009, 0x017d, 0x017e, 0x017e, 0x017e, 0x017f,
        0x0008, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
        0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0007, 0x000a, 0x0009, 0x0009, 0x0095,
        0x0098, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
        0x0009, 0x0009, 0x0009, 0x0023, 0x0023, 0x0069, 0x0009, 0x0049, 0x0049, 0x018f,
        0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
        0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0095, 0x0095, 0x0095, 0x0095, 0x02f8,
        0x02fe, 0x0095, 0x009b, 0x03b4, 0x03b4, 0x03b4, 0x03b4, 0x03b4, 0x03b4, 0x03b4,
        0x03b4, 0x03b4, 0x03b4, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
        0x0009, 0x0107, 0x0107, 0x0107, 0x00d2, 0x0107, 0x0107, 0x0107, 0x00d2, 0x0107,
        0x0107, 0x0107, 0x008f, 0x0281, 0x00fb, 0x0235, 0x0114, 0x0284, 0x0083, 0x0156,
        0x0089, 0x0245, 0x0294, 0x0009, 0x0009, 0x03bc, 0x03bc, 0x038c, 0x038c, 0x00d7,
        0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
        0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x02bd, 0x02b9, 0x02bd, 0x02b9, 0x02c2,
        0x02cc, 0x02c9, 0x02cc, 0x02c9, 0x02d2, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
        0x0009, 0x0009, 0x0009, 0x016d, 0x01b7, 0x01b5, 0x01b7, 0x01b7, 0x01b7, 0x01b7,
        0x01b7, 0x01b7, 0x01b7, 0x0095, 0x0203, 0x01b7, 0x02a5, 0x033e, 0x01b7, 0x01b7,
        0x0176, 0x028c, 0x01b7, 0x00e6, 0x00c7, 0x01fe, 0x0033, 0x0009, 0x0009, 0x0075,
        0x009a, 0x022e, 0x0117, 0x010a, 0x008f, 0x0095, 0x0095, 0x0095, 0x010d, 0x007d,
        0x011a, 0x0093, 0x0095, 0x0095, 0x0103, 0x0107, 0x0107, 0x011c, 0x0095, 0x0095,
        0x0095, 0x0107, 0x0107, 0x0107, 0x00ff, 0x0095, 0x0095, 0x0103, 0x0107, 0x0107,
        0x011c, 0x0095, 0x0095, 0x0095, 0x0107, 0x0107, 0x0107, 0x00ff, 0x0095, 0x0095,
        0x0097, 0x0107, 0x0107, 0x0107, 0x0093, 0x0095, 0x0095, 0x02fe, 0x0105, 0x0107,
        0x0107, 0x0091, 0x01b7, 0x01b7, 0x01b7, 0x01b7, 0x01b7, 0x01b7, 0x01b7, 0x01b7,
        0x01b7, 0x01b7, 0x01b7, 0x01b7, 0x01b7, 0x01b7, 0x01b7, 0x01b7, 0x01b7, 0x01b7,
        0x014a, 0x01a1, 0x01b7, 0x01b7, 0x01b7, 0x01b7, 0x01b7, 0x01b7, 0x01b7, 0x01b7,
        0x01b7, 0x01b7, 0x01b7, 0x01b7, 0x0130, 0x01b6, 0x013c, 0x0148, 0x01b7, 0x01b7,
        0x01b7, 0x01b7, 0x01b7, 0x0354, 0x036c, 0x037c, 0x03dc, 0x0258, 0x0132, 0x002c,
        0x0384, 0x02df, 0x00dc, 0x00e1, 0x013c, 0x0170, 0x01b7, 0x01b7, 0x0018, 0x01b7,
        0x01b7, 0x01b7, 0x01b7, 0x0165, 0x01b7, 0x014c, 0x024b, 0x0252, 0x01b7, 0x0052,
        0x02f3, 0x0059, 0x039c, 0x0060, 0x02ec, 0x03a4, 0x02e7, 0x0310, 0x0011, 0x0095,
        0x0095, 0x0095, 0x0008, 0x009b, 0x0009, 0x0009, 0x0009, 0x0098, 0x0009, 0x0009,
        0x0009, 0x00be, 0x00be, 0x00be, 0x00be, 0x00be, 0x00be, 0x017e, 0x017e, 0x017e,
        0x017e, 0x017e, 0x017e, 0x0209, 0x0140, 0x02da, 0x0302, 0x01b7, 0x01b7, 0x01b7,
        0x01b7, 0x01b7, 0x01b7, 0x01b7, 0x01b7, 0x01b7, 0x01b7, 0x01b7, 0x01b7, 0x0344,
        0x01f9, 0x00d8, 0x0009, 0x01ca, 0x01d4, 0x01cc, 0x01d6, 0x01ca, 0x01d4, 0x01ca,
        0x01d4, 0x01cc, 0x01d6, 0x01a8, 0x003a, 0x01ca, 0x01d4, 0x0374, 0x0000, 0x01ca,
        0x01d4, 0x01ca, 0x01d4, 0x01ca, 0x01d4, 0x030a, 0x0041, 0x019b, 0x035c, 0x0222,
        0x00b6, 0x01af, 0x0364, 0x019b, 0x034c, 0x029c, 0x029c, 0x029c, 0x029c, 0x029c,
        0x02ad, 0x02ad, 0x02ad, 0x02ad, 0x02ad, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
        0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x029c, 0x029c, 0x029c,
        0x029c, 0x02a0, 0x02ad, 0x02ad, 0x02ad, 0x02ad, 0x02b1
    };
    
    static const uint16_t unicode_offsets2[498] = {
        0x00ff, 0x02ec, 0x030b, 0x015f, 0x01c9, 0x01e3, 0x0003, 0x0003, 0x0003, 0x0003,
        0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0039, 0x0003, 0x0003, 0x009f,
        0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x012f, 0x0077,
        0x02d2, 0x034b, 0x01f5, 0x0251, 0x0003, 0x0003, 0x000d, 0x0003, 0x0003, 0x0003,
        0x0003, 0x0003, 0x0003, 0x0003, 0x032b, 0x002d, 0x0003, 0x0003, 0x0003, 0x0003,
        0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003,
        0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003,
        0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003,
        0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003,
        0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003,
        0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003,
        0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003,
        0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003,
        0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003,
        0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003,
        0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003,
        0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0147, 0x027f, 0x0003, 0x0003,
        0x0003, 0x0225, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003,
        0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003,
        0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003,
        0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003,
        0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003,
        0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003,
        0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003,
        0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003,
        0x0003, 0x0000, 0x0003, 0x0003, 0x0003, 0x0093, 0x0003, 0x0003, 0x0003, 0x0003,
        0x036b, 0x0263, 0x0003, 0x00e7, 0x0003, 0x0003, 0x0003, 0x0003, 0x01a9, 0x020b,
        0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003,
        0x00cb, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003,
        0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003,
        0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003,
        0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003,
        0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003,
        0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003,
        0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003,
        0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003,
        0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x00d7, 0x0003, 0x0003, 0x0003,
        0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003,
        0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003,
        0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003,
        0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003,
        0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003,
        0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003,
        0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003,
        0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003,
        0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003,
        0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0059, 0x029f,
        0x02b2, 0x017f, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x011f,
        0x0199, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x00bf,
        0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x023f
    };
    
    static inline const struct CaseMappings *
    get_unicode_entry(xkb_keysym_t ks)
    {
        return &unicode_data[unicode_offsets1[unicode_offsets2[ks >> 8] + ((ks >> 3) & 0x1f)] + (ks & 0x07)];
    }
    
    xkb_keysym_t
    xkb_keysym_to_lower(xkb_keysym_t ks)
    {
        if (ks <= 0x13be) {
            const struct CaseMappings *m = get_legacy_keysym_entry(ks);
            return (m->lower) ? ks + m->offset : ks;
        } else if (XKB_KEYSYM_UNICODE_MIN <= ks && ks <= 0x0101f189) {
            const struct CaseMappings *m = get_unicode_entry(ks - XKB_KEYSYM_UNICODE_OFFSET);
            if (m->lower) {
                ks = ks + m->offset;
                return (ks < XKB_KEYSYM_UNICODE_MIN) ? ks - XKB_KEYSYM_UNICODE_OFFSET : ks;
            } else {
                return ks;
            }
        } else {
            return ks;
        }
    }
    
    xkb_keysym_t
    xkb_keysym_to_upper(xkb_keysym_t ks)
    {
        if (ks <= 0x13be) {
            const struct CaseMappings *m = get_legacy_keysym_entry(ks);
            return (m->upper) ? ks - m->offset : ks;
        } else if (XKB_KEYSYM_UNICODE_MIN <= ks && ks <= 0x0101f189) {
            const struct CaseMappings *m = get_unicode_entry(ks - XKB_KEYSYM_UNICODE_OFFSET);
            if (m->upper) {
                ks = ks - m->offset;
                return (ks < XKB_KEYSYM_UNICODE_MIN) ? ks - XKB_KEYSYM_UNICODE_OFFSET : ks;
            } else {
                return ks;
            }
        } else {
            return ks;
        }
    }
    
    bool
    xkb_keysym_is_lower(xkb_keysym_t ks)
    {
        /* This predicate matches keysyms with their corresponding Unicode code point
         * having the Unicode property “Lowercase”.
         *
         * Here: a keysym is lower case if it has an upper case and no lower case.
         * Note: title case letters may have both. Example for U+01F2:
         * • U+01F1 DZ: upper case
         * • U+01F2 Dz: title case
         * • U+01F3 dz: lower case
         */
        if (ks <= 0x13be) {
            const struct CaseMappings *m = get_legacy_keysym_entry(ks);
            return m->upper && !m->lower;
        } else if (XKB_KEYSYM_UNICODE_MIN <= ks && ks <= 0x0101f189) {
            const struct CaseMappings *m = get_unicode_entry(ks - XKB_KEYSYM_UNICODE_OFFSET);
            return m->upper && !m->lower;
        } else {
            return false;
        }
    }
    
    bool
    xkb_keysym_is_upper_or_title(xkb_keysym_t ks)
    {
        /* This predicate matches keysyms with their corresponding Unicode code point
         * having the Unicode properties “Uppercase” or General Category “Lt”.
         *
         * Here: a keysym is upper case or title case if it has a lower case. */
        if (ks <= 0x13be) {
            return get_legacy_keysym_entry(ks)->lower;
        } else if (XKB_KEYSYM_UNICODE_MIN <= ks && ks <= 0x0101f189) {
            return get_unicode_entry(ks - XKB_KEYSYM_UNICODE_OFFSET)->lower;
        } else {
            return false;
        }
    }