Resguardo inicial

This commit is contained in:
lastdragon
2026-09-06 12:53:21 -06:00
parent 662efe3c2a
commit ad2088d178
94853 changed files with 43200404 additions and 0 deletions
+7
View File
@@ -0,0 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
/conmakehash
/consolemap_deftbl.c
/defkeymap.c
/ucs_fallback_table.h
/ucs_recompose_table.h
/ucs_width_table.h
+65
View File
@@ -0,0 +1,65 @@
# SPDX-License-Identifier: GPL-2.0
#
# This file contains the font map for the default (hardware) font
#
FONTMAPFILE = cp437.uni
obj-$(CONFIG_VT) += vt_ioctl.o vc_screen.o \
selection.o keyboard.o \
vt.o defkeymap.o
obj-$(CONFIG_CONSOLE_TRANSLATIONS) += consolemap.o consolemap_deftbl.o \
ucs.o
# Files generated that shall be removed upon make clean
clean-files := consolemap_deftbl.c defkeymap.c \
ucs_width_table.h ucs_recompose_table.h ucs_fallback_table.h
hostprogs += conmakehash
quiet_cmd_conmk = CONMK $@
cmd_conmk = $(obj)/conmakehash $< > $@
$(obj)/consolemap_deftbl.c: $(src)/$(FONTMAPFILE) $(obj)/conmakehash
$(call cmd,conmk)
$(obj)/defkeymap.o: $(obj)/defkeymap.c
# Uncomment if you're changing the keymap and have an appropriate
# loadkeys version for the map. By default, we'll use the shipped
# versions.
# GENERATE_KEYMAP := 1
ifdef GENERATE_KEYMAP
$(obj)/defkeymap.c: $(obj)/%.c: $(src)/%.map
loadkeys --mktable --unicode $< > $@
endif
$(obj)/ucs.o: $(src)/ucs.c $(obj)/ucs_width_table.h \
$(obj)/ucs_recompose_table.h $(obj)/ucs_fallback_table.h
# You may uncomment one of those to have the UCS tables be regenerated
# during the build process. By default the _shipped versions are used.
#
#GENERATE_UCS_TABLES := 1
#GENERATE_UCS_TABLES := 2 # invokes gen_ucs_recompose_table.py with --full
ifdef GENERATE_UCS_TABLES
$(obj)/ucs_width_table.h: $(src)/gen_ucs_width_table.py
$(PYTHON3) $< -o $@
ifeq ($(GENERATE_UCS_TABLES),2)
gen_recomp_arg := --full
else
gen_recomp_arg :=
endif
$(obj)/ucs_recompose_table.h: $(src)/gen_ucs_recompose_table.py
$(PYTHON3) $< -o $@ $(gen_recomp_arg)
$(obj)/ucs_fallback_table.h: $(src)/gen_ucs_fallback_table.py
$(PYTHON3) $< -o $@
endif
+287
View File
@@ -0,0 +1,287 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* conmakehash.c
*
* Create arrays for initializing the kernel folded tables (using a hash
* table turned out to be to limiting...) Unfortunately we can't simply
* preinitialize the tables at compile time since kfree() cannot accept
* memory not allocated by kmalloc(), and doing our own memory management
* just for this seems like massive overkill.
*
* Copyright (C) 1995-1997 H. Peter Anvin
*/
#include <stdio.h>
#include <stdlib.h>
#include <sysexits.h>
#include <string.h>
#include <ctype.h>
#define MAX_FONTLEN 256
typedef unsigned short unicode;
static void usage(char *argv0)
{
fprintf(stderr, "Usage: \n"
" %s chartable [hashsize] [hashstep] [maxhashlevel]\n", argv0);
exit(EX_USAGE);
}
static int getunicode(char **p0)
{
char *p = *p0;
while (*p == ' ' || *p == '\t')
p++;
if (*p != 'U' || p[1] != '+' ||
!isxdigit(p[2]) || !isxdigit(p[3]) || !isxdigit(p[4]) ||
!isxdigit(p[5]) || isxdigit(p[6]))
return -1;
*p0 = p+6;
return strtol(p+2,0,16);
}
unicode unitable[MAX_FONTLEN][255];
/* Massive overkill, but who cares? */
int unicount[MAX_FONTLEN];
static void addpair(int fp, int un)
{
int i;
if ( un <= 0xfffe )
{
/* Check it isn't a duplicate */
for ( i = 0 ; i < unicount[fp] ; i++ )
if ( unitable[fp][i] == un )
return;
/* Add to list */
if ( unicount[fp] > 254 )
{
fprintf(stderr, "ERROR: Only 255 unicodes/glyph permitted!\n");
exit(EX_DATAERR);
}
unitable[fp][unicount[fp]] = un;
unicount[fp]++;
}
/* otherwise: ignore */
}
int main(int argc, char *argv[])
{
FILE *ctbl;
const char *tblname;
char buffer[65536];
int fontlen;
int i, nuni, nent;
int fp0, fp1, un0, un1;
char *p, *p1;
if ( argc < 2 || argc > 5 )
usage(argv[0]);
if ( !strcmp(argv[1],"-") )
{
ctbl = stdin;
tblname = "stdin";
}
else
{
ctbl = fopen(tblname = argv[1], "r");
if ( !ctbl )
{
perror(tblname);
exit(EX_NOINPUT);
}
}
/* For now we assume the default font is always 256 characters. */
fontlen = 256;
/* Initialize table */
for ( i = 0 ; i < fontlen ; i++ )
unicount[i] = 0;
/* Now we come to the tricky part. Parse the input table. */
while ( fgets(buffer, sizeof(buffer), ctbl) != NULL )
{
if ( (p = strchr(buffer, '\n')) != NULL )
*p = '\0';
else
fprintf(stderr, "%s: Warning: line too long\n", tblname);
p = buffer;
/*
* Syntax accepted:
* <fontpos> <unicode> <unicode> ...
* <range> idem
* <range> <unicode range>
*
* where <range> ::= <fontpos>-<fontpos>
* and <unicode> ::= U+<h><h><h><h>
* and <h> ::= <hexadecimal digit>
*/
while (*p == ' ' || *p == '\t')
p++;
if (!*p || *p == '#')
continue; /* skip comment or blank line */
fp0 = strtol(p, &p1, 0);
if (p1 == p)
{
fprintf(stderr, "Bad input line: %s\n", buffer);
exit(EX_DATAERR);
}
p = p1;
while (*p == ' ' || *p == '\t')
p++;
if (*p == '-')
{
p++;
fp1 = strtol(p, &p1, 0);
if (p1 == p)
{
fprintf(stderr, "Bad input line: %s\n", buffer);
exit(EX_DATAERR);
}
p = p1;
}
else
fp1 = 0;
if ( fp0 < 0 || fp0 >= fontlen )
{
fprintf(stderr,
"%s: Glyph number (0x%x) larger than font length\n",
tblname, fp0);
exit(EX_DATAERR);
}
if ( fp1 && (fp1 < fp0 || fp1 >= fontlen) )
{
fprintf(stderr,
"%s: Bad end of range (0x%x)\n",
tblname, fp1);
exit(EX_DATAERR);
}
if (fp1)
{
/* we have a range; expect the word "idem" or a Unicode range of the
same length */
while (*p == ' ' || *p == '\t')
p++;
if (!strncmp(p, "idem", 4))
{
for (i=fp0; i<=fp1; i++)
addpair(i,i);
p += 4;
}
else
{
un0 = getunicode(&p);
while (*p == ' ' || *p == '\t')
p++;
if (*p != '-')
{
fprintf(stderr,
"%s: Corresponding to a range of font positions, there should be a Unicode range\n",
tblname);
exit(EX_DATAERR);
}
p++;
un1 = getunicode(&p);
if (un0 < 0 || un1 < 0)
{
fprintf(stderr,
"%s: Bad Unicode range corresponding to font position range 0x%x-0x%x\n",
tblname, fp0, fp1);
exit(EX_DATAERR);
}
if (un1 - un0 != fp1 - fp0)
{
fprintf(stderr,
"%s: Unicode range U+%x-U+%x not of the same length as font position range 0x%x-0x%x\n",
tblname, un0, un1, fp0, fp1);
exit(EX_DATAERR);
}
for(i=fp0; i<=fp1; i++)
addpair(i,un0-fp0+i);
}
}
else
{
/* no range; expect a list of unicode values for a single font position */
while ( (un0 = getunicode(&p)) >= 0 )
addpair(fp0, un0);
}
while (*p == ' ' || *p == '\t')
p++;
if (*p && *p != '#')
fprintf(stderr, "%s: trailing junk (%s) ignored\n", tblname, p);
}
/* Okay, we hit EOF, now output hash table */
fclose(ctbl);
/* Compute total size of Unicode list */
nuni = 0;
for ( i = 0 ; i < fontlen ; i++ )
nuni += unicount[i];
printf("\
/*\n\
* Automatically generated file; Do not edit.\n\
*/\n\
\n\
#include <linux/types.h>\n\
\n\
u8 dfont_unicount[%d] = \n\
{\n\t", fontlen);
for ( i = 0 ; i < fontlen ; i++ )
{
printf("%3d", unicount[i]);
if ( i == fontlen-1 )
printf("\n};\n");
else if ( i % 8 == 7 )
printf(",\n\t");
else
printf(", ");
}
printf("\nu16 dfont_unitable[%d] = \n{\n\t", nuni);
fp0 = 0;
nent = 0;
for ( i = 0 ; i < nuni ; i++ )
{
while ( nent >= unicount[fp0] )
{
fp0++;
nent = 0;
}
printf("0x%04x", unitable[fp0][nent++]);
if ( i == nuni-1 )
printf("\n};\n");
else if ( i % 8 == 7 )
printf(",\n\t");
else
printf(", ");
}
exit(EX_OK);
}
+900
View File
@@ -0,0 +1,900 @@
// SPDX-License-Identifier: GPL-2.0
/*
* consolemap.c
*
* Mapping from internal code (such as Latin-1 or Unicode or IBM PC code)
* to font positions.
*
* aeb, 950210
*
* Support for multiple unimaps by Jakub Jelinek <jj@ultra.linux.cz>, July 1998
*
* Fix bug in inverse translation. Stanislav Voronyi <stas@cnti.uanet.kharkov.ua>, Dec 1998
*
* In order to prevent the following circular lock dependency:
* &mm->mmap_lock --> cpu_hotplug.lock --> console_lock --> &mm->mmap_lock
*
* We cannot allow page fault to happen while holding the console_lock.
* Therefore, all the userspace copy operations have to be done outside
* the console_lock critical sections.
*
* As all the affected functions are all called directly from vt_ioctl(), we
* can allocate some small buffers directly on stack without worrying about
* stack overflow.
*/
#include <linux/bitfield.h>
#include <linux/bits.h>
#include <linux/module.h>
#include <linux/kd.h>
#include <linux/errno.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/tty.h>
#include <linux/uaccess.h>
#include <linux/console.h>
#include <linux/consolemap.h>
#include <linux/vt_kern.h>
#include <linux/string.h>
static unsigned short translations[][E_TABSZ] = {
/* 8-bit Latin-1 mapped to Unicode -- trivial mapping */
[LAT1_MAP] = {
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7,
0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7,
0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7,
0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7,
0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff
},
/* VT100 graphics mapped to Unicode */
[GRAF_MAP] = {
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
0x0028, 0x0029, 0x002a, 0x2192, 0x2190, 0x2191, 0x2193, 0x002f,
0x2588, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x00a0,
0x25c6, 0x2592, 0x2409, 0x240c, 0x240d, 0x240a, 0x00b0, 0x00b1,
0x2591, 0x240b, 0x2518, 0x2510, 0x250c, 0x2514, 0x253c, 0x23ba,
0x23bb, 0x2500, 0x23bc, 0x23bd, 0x251c, 0x2524, 0x2534, 0x252c,
0x2502, 0x2264, 0x2265, 0x03c0, 0x2260, 0x00a3, 0x00b7, 0x007f,
0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7,
0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7,
0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7,
0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7,
0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff
},
/* IBM Codepage 437 mapped to Unicode */
[IBMPC_MAP] = {
0x0000, 0x263a, 0x263b, 0x2665, 0x2666, 0x2663, 0x2660, 0x2022,
0x25d8, 0x25cb, 0x25d9, 0x2642, 0x2640, 0x266a, 0x266b, 0x263c,
0x25b6, 0x25c0, 0x2195, 0x203c, 0x00b6, 0x00a7, 0x25ac, 0x21a8,
0x2191, 0x2193, 0x2192, 0x2190, 0x221f, 0x2194, 0x25b2, 0x25bc,
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x2302,
0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7,
0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5,
0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9,
0x00ff, 0x00d6, 0x00dc, 0x00a2, 0x00a3, 0x00a5, 0x20a7, 0x0192,
0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00ba,
0x00bf, 0x2310, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510,
0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f,
0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567,
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256b,
0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258c, 0x2590, 0x2580,
0x03b1, 0x00df, 0x0393, 0x03c0, 0x03a3, 0x03c3, 0x00b5, 0x03c4,
0x03a6, 0x0398, 0x03a9, 0x03b4, 0x221e, 0x03c6, 0x03b5, 0x2229,
0x2261, 0x00b1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00f7, 0x2248,
0x00b0, 0x2219, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x25a0, 0x00a0
},
/* User mapping -- default to codes for direct font mapping */
[USER_MAP] = {
0xf000, 0xf001, 0xf002, 0xf003, 0xf004, 0xf005, 0xf006, 0xf007,
0xf008, 0xf009, 0xf00a, 0xf00b, 0xf00c, 0xf00d, 0xf00e, 0xf00f,
0xf010, 0xf011, 0xf012, 0xf013, 0xf014, 0xf015, 0xf016, 0xf017,
0xf018, 0xf019, 0xf01a, 0xf01b, 0xf01c, 0xf01d, 0xf01e, 0xf01f,
0xf020, 0xf021, 0xf022, 0xf023, 0xf024, 0xf025, 0xf026, 0xf027,
0xf028, 0xf029, 0xf02a, 0xf02b, 0xf02c, 0xf02d, 0xf02e, 0xf02f,
0xf030, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036, 0xf037,
0xf038, 0xf039, 0xf03a, 0xf03b, 0xf03c, 0xf03d, 0xf03e, 0xf03f,
0xf040, 0xf041, 0xf042, 0xf043, 0xf044, 0xf045, 0xf046, 0xf047,
0xf048, 0xf049, 0xf04a, 0xf04b, 0xf04c, 0xf04d, 0xf04e, 0xf04f,
0xf050, 0xf051, 0xf052, 0xf053, 0xf054, 0xf055, 0xf056, 0xf057,
0xf058, 0xf059, 0xf05a, 0xf05b, 0xf05c, 0xf05d, 0xf05e, 0xf05f,
0xf060, 0xf061, 0xf062, 0xf063, 0xf064, 0xf065, 0xf066, 0xf067,
0xf068, 0xf069, 0xf06a, 0xf06b, 0xf06c, 0xf06d, 0xf06e, 0xf06f,
0xf070, 0xf071, 0xf072, 0xf073, 0xf074, 0xf075, 0xf076, 0xf077,
0xf078, 0xf079, 0xf07a, 0xf07b, 0xf07c, 0xf07d, 0xf07e, 0xf07f,
0xf080, 0xf081, 0xf082, 0xf083, 0xf084, 0xf085, 0xf086, 0xf087,
0xf088, 0xf089, 0xf08a, 0xf08b, 0xf08c, 0xf08d, 0xf08e, 0xf08f,
0xf090, 0xf091, 0xf092, 0xf093, 0xf094, 0xf095, 0xf096, 0xf097,
0xf098, 0xf099, 0xf09a, 0xf09b, 0xf09c, 0xf09d, 0xf09e, 0xf09f,
0xf0a0, 0xf0a1, 0xf0a2, 0xf0a3, 0xf0a4, 0xf0a5, 0xf0a6, 0xf0a7,
0xf0a8, 0xf0a9, 0xf0aa, 0xf0ab, 0xf0ac, 0xf0ad, 0xf0ae, 0xf0af,
0xf0b0, 0xf0b1, 0xf0b2, 0xf0b3, 0xf0b4, 0xf0b5, 0xf0b6, 0xf0b7,
0xf0b8, 0xf0b9, 0xf0ba, 0xf0bb, 0xf0bc, 0xf0bd, 0xf0be, 0xf0bf,
0xf0c0, 0xf0c1, 0xf0c2, 0xf0c3, 0xf0c4, 0xf0c5, 0xf0c6, 0xf0c7,
0xf0c8, 0xf0c9, 0xf0ca, 0xf0cb, 0xf0cc, 0xf0cd, 0xf0ce, 0xf0cf,
0xf0d0, 0xf0d1, 0xf0d2, 0xf0d3, 0xf0d4, 0xf0d5, 0xf0d6, 0xf0d7,
0xf0d8, 0xf0d9, 0xf0da, 0xf0db, 0xf0dc, 0xf0dd, 0xf0de, 0xf0df,
0xf0e0, 0xf0e1, 0xf0e2, 0xf0e3, 0xf0e4, 0xf0e5, 0xf0e6, 0xf0e7,
0xf0e8, 0xf0e9, 0xf0ea, 0xf0eb, 0xf0ec, 0xf0ed, 0xf0ee, 0xf0ef,
0xf0f0, 0xf0f1, 0xf0f2, 0xf0f3, 0xf0f4, 0xf0f5, 0xf0f6, 0xf0f7,
0xf0f8, 0xf0f9, 0xf0fa, 0xf0fb, 0xf0fc, 0xf0fd, 0xf0fe, 0xf0ff
}
};
/* The standard kernel character-to-font mappings are not invertible
-- this is just a best effort. */
#define MAX_GLYPH 512 /* Max possible glyph value */
static enum translation_map inv_translate[MAX_NR_CONSOLES];
#define UNI_DIRS 32U
#define UNI_DIR_ROWS 32U
#define UNI_ROW_GLYPHS 64U
#define UNI_DIR_BITS GENMASK(15, 11)
#define UNI_ROW_BITS GENMASK(10, 6)
#define UNI_GLYPH_BITS GENMASK( 5, 0)
#define UNI_DIR(uni) FIELD_GET(UNI_DIR_BITS, (uni))
#define UNI_ROW(uni) FIELD_GET(UNI_ROW_BITS, (uni))
#define UNI_GLYPH(uni) FIELD_GET(UNI_GLYPH_BITS, (uni))
#define UNI(dir, row, glyph) (FIELD_PREP(UNI_DIR_BITS, (dir)) | \
FIELD_PREP(UNI_ROW_BITS, (row)) | \
FIELD_PREP(UNI_GLYPH_BITS, (glyph)))
/**
* struct uni_pagedict - unicode directory
*
* @uni_pgdir: 32*32*64 table with glyphs
* @refcount: reference count of this structure
* @sum: checksum
* @inverse_translations: best-effort inverse mapping
* @inverse_trans_unicode: best-effort inverse mapping to unicode
*/
struct uni_pagedict {
u16 **uni_pgdir[UNI_DIRS];
unsigned long refcount;
unsigned long sum;
unsigned char *inverse_translations[LAST_MAP + 1];
u16 *inverse_trans_unicode;
};
static struct uni_pagedict *dflt;
static void set_inverse_transl(struct vc_data *conp, struct uni_pagedict *dict,
enum translation_map m)
{
unsigned short *t = translations[m];
unsigned char *inv;
if (!dict)
return;
inv = dict->inverse_translations[m];
if (!inv) {
inv = dict->inverse_translations[m] = kmalloc(MAX_GLYPH,
GFP_KERNEL);
if (!inv)
return;
}
memset(inv, 0, MAX_GLYPH);
for (unsigned int ch = 0; ch < ARRAY_SIZE(translations[m]); ch++) {
int glyph = conv_uni_to_pc(conp, t[ch]);
if (glyph >= 0 && glyph < MAX_GLYPH && inv[glyph] < 32) {
/* prefer '-' above SHY etc. */
inv[glyph] = ch;
}
}
}
static void set_inverse_trans_unicode(struct uni_pagedict *dict)
{
unsigned int d, r, g;
u16 *inv;
if (!dict)
return;
inv = dict->inverse_trans_unicode;
if (!inv) {
inv = dict->inverse_trans_unicode = kmalloc_array(MAX_GLYPH,
sizeof(*inv), GFP_KERNEL);
if (!inv)
return;
}
memset(inv, 0, MAX_GLYPH * sizeof(*inv));
for (d = 0; d < UNI_DIRS; d++) {
u16 **dir = dict->uni_pgdir[d];
if (!dir)
continue;
for (r = 0; r < UNI_DIR_ROWS; r++) {
u16 *row = dir[r];
if (!row)
continue;
for (g = 0; g < UNI_ROW_GLYPHS; g++) {
u16 glyph = row[g];
if (glyph < MAX_GLYPH && inv[glyph] < 32)
inv[glyph] = UNI(d, r, g);
}
}
}
}
unsigned short *set_translate(enum translation_map m, struct vc_data *vc)
{
inv_translate[vc->vc_num] = m;
return translations[m];
}
/*
* Inverse translation is impossible for several reasons:
* 1. The font<->character maps are not 1-1.
* 2. The text may have been written while a different translation map
* was active.
* Still, it is now possible to a certain extent to cut and paste non-ASCII.
*/
u16 inverse_translate(const struct vc_data *conp, u16 glyph, bool use_unicode)
{
struct uni_pagedict *p;
enum translation_map m;
if (glyph >= MAX_GLYPH)
return 0;
p = *conp->uni_pagedict_loc;
if (!p)
return glyph;
if (use_unicode) {
if (!p->inverse_trans_unicode)
return glyph;
return p->inverse_trans_unicode[glyph];
}
m = inv_translate[conp->vc_num];
if (!p->inverse_translations[m])
return glyph;
return p->inverse_translations[m][glyph];
}
EXPORT_SYMBOL_GPL(inverse_translate);
static void update_user_maps(void)
{
int i;
struct uni_pagedict *p, *q = NULL;
for (i = 0; i < MAX_NR_CONSOLES; i++) {
if (!vc_cons_allocated(i))
continue;
p = *vc_cons[i].d->uni_pagedict_loc;
if (p && p != q) {
set_inverse_transl(vc_cons[i].d, p, USER_MAP);
set_inverse_trans_unicode(p);
q = p;
}
}
}
/*
* Load customizable translation table
* arg points to a 256 byte translation table.
*
* The "old" variants are for translation directly to font (using the
* 0xf000-0xf0ff "transparent" Unicodes) whereas the "new" variants set
* Unicodes explicitly.
*/
int con_set_trans_old(unsigned char __user * arg)
{
unsigned short inbuf[E_TABSZ];
unsigned int i;
unsigned char ch;
for (i = 0; i < ARRAY_SIZE(inbuf); i++) {
if (get_user(ch, &arg[i]))
return -EFAULT;
inbuf[i] = UNI_DIRECT_BASE | ch;
}
guard(console_lock)();
memcpy(translations[USER_MAP], inbuf, sizeof(inbuf));
update_user_maps();
return 0;
}
int con_get_trans_old(unsigned char __user * arg)
{
int i, ch;
unsigned short *p = translations[USER_MAP];
unsigned char outbuf[E_TABSZ];
scoped_guard(console_lock)
for (i = 0; i < ARRAY_SIZE(outbuf); i++) {
ch = conv_uni_to_pc(vc_cons[fg_console].d, p[i]);
outbuf[i] = (ch & ~0xff) ? 0 : ch;
}
return copy_to_user(arg, outbuf, sizeof(outbuf)) ? -EFAULT : 0;
}
int con_set_trans_new(ushort __user * arg)
{
unsigned short inbuf[E_TABSZ];
if (copy_from_user(inbuf, arg, sizeof(inbuf)))
return -EFAULT;
guard(console_lock)();
memcpy(translations[USER_MAP], inbuf, sizeof(inbuf));
update_user_maps();
return 0;
}
int con_get_trans_new(ushort __user * arg)
{
unsigned short outbuf[E_TABSZ];
scoped_guard(console_lock)
memcpy(outbuf, translations[USER_MAP], sizeof(outbuf));
return copy_to_user(arg, outbuf, sizeof(outbuf)) ? -EFAULT : 0;
}
/*
* Unicode -> current font conversion
*
* A font has at most 512 chars, usually 256.
* But one font position may represent several Unicode chars.
* A hashtable is somewhat of a pain to deal with, so use a
* "paged table" instead. Simulation has shown the memory cost of
* this 3-level paged table scheme to be comparable to a hash table.
*/
extern u8 dfont_unicount[]; /* Defined in console_defmap.c */
extern u16 dfont_unitable[];
static void con_release_unimap(struct uni_pagedict *dict)
{
unsigned int d, r;
if (dict == dflt)
dflt = NULL;
for (d = 0; d < UNI_DIRS; d++) {
u16 **dir = dict->uni_pgdir[d];
if (dir != NULL) {
for (r = 0; r < UNI_DIR_ROWS; r++)
kfree(dir[r]);
kfree(dir);
}
dict->uni_pgdir[d] = NULL;
}
for (r = 0; r < ARRAY_SIZE(dict->inverse_translations); r++) {
kfree(dict->inverse_translations[r]);
dict->inverse_translations[r] = NULL;
}
kfree(dict->inverse_trans_unicode);
dict->inverse_trans_unicode = NULL;
}
/* Caller must hold the console lock */
void con_free_unimap(struct vc_data *vc)
{
struct uni_pagedict *p;
p = *vc->uni_pagedict_loc;
if (!p)
return;
*vc->uni_pagedict_loc = NULL;
if (--p->refcount)
return;
con_release_unimap(p);
kfree(p);
}
static int con_unify_unimap(struct vc_data *conp, struct uni_pagedict *dict1)
{
struct uni_pagedict *dict2;
unsigned int cons, d, r;
for (cons = 0; cons < MAX_NR_CONSOLES; cons++) {
if (!vc_cons_allocated(cons))
continue;
dict2 = *vc_cons[cons].d->uni_pagedict_loc;
if (!dict2 || dict2 == dict1 || dict2->sum != dict1->sum)
continue;
for (d = 0; d < UNI_DIRS; d++) {
u16 **dir1 = dict1->uni_pgdir[d];
u16 **dir2 = dict2->uni_pgdir[d];
if (!dir1 && !dir2)
continue;
if (!dir1 || !dir2)
break;
for (r = 0; r < UNI_DIR_ROWS; r++) {
if (!dir1[r] && !dir2[r])
continue;
if (!dir1[r] || !dir2[r])
break;
if (memcmp(dir1[r], dir2[r], UNI_ROW_GLYPHS *
sizeof(*dir1[r])))
break;
}
if (r < UNI_DIR_ROWS)
break;
}
if (d == UNI_DIRS) {
dict2->refcount++;
*conp->uni_pagedict_loc = dict2;
con_release_unimap(dict1);
kfree(dict1);
return 1;
}
}
return 0;
}
static int
con_insert_unipair(struct uni_pagedict *p, u_short unicode, u_short fontpos)
{
u16 **dir, *row;
unsigned int n;
n = UNI_DIR(unicode);
dir = p->uni_pgdir[n];
if (!dir) {
dir = p->uni_pgdir[n] = kcalloc(UNI_DIR_ROWS, sizeof(*dir),
GFP_KERNEL);
if (!dir)
return -ENOMEM;
}
n = UNI_ROW(unicode);
row = dir[n];
if (!row) {
row = dir[n] = kmalloc_array(UNI_ROW_GLYPHS, sizeof(*row),
GFP_KERNEL);
if (!row)
return -ENOMEM;
/* No glyphs for the characters (yet) */
memset(row, 0xff, UNI_ROW_GLYPHS * sizeof(*row));
}
row[UNI_GLYPH(unicode)] = fontpos;
p->sum += (fontpos << 20U) + unicode;
return 0;
}
static int con_allocate_new(struct vc_data *vc)
{
struct uni_pagedict *new, *old = *vc->uni_pagedict_loc;
new = kzalloc_obj(*new);
if (!new)
return -ENOMEM;
new->refcount = 1;
*vc->uni_pagedict_loc = new;
if (old)
old->refcount--;
return 0;
}
/* Caller must hold the lock */
static int con_do_clear_unimap(struct vc_data *vc)
{
struct uni_pagedict *old = *vc->uni_pagedict_loc;
if (!old || old->refcount > 1)
return con_allocate_new(vc);
old->sum = 0;
con_release_unimap(old);
return 0;
}
int con_clear_unimap(struct vc_data *vc)
{
guard(console_lock)();
return con_do_clear_unimap(vc);
}
static struct uni_pagedict *con_unshare_unimap(struct vc_data *vc,
struct uni_pagedict *old)
{
struct uni_pagedict *new;
unsigned int d, r, g;
int ret;
u16 uni = 0;
ret = con_allocate_new(vc);
if (ret)
return ERR_PTR(ret);
new = *vc->uni_pagedict_loc;
/*
* uni_pgdir is a 32*32*64 table with rows allocated when its first
* entry is added. The unicode value must still be incremented for
* empty rows. We are copying entries from "old" to "new".
*/
for (d = 0; d < UNI_DIRS; d++) {
u16 **dir = old->uni_pgdir[d];
if (!dir) {
/* Account for empty table */
uni += UNI_DIR_ROWS * UNI_ROW_GLYPHS;
continue;
}
for (r = 0; r < UNI_DIR_ROWS; r++) {
u16 *row = dir[r];
if (!row) {
/* Account for row of 64 empty entries */
uni += UNI_ROW_GLYPHS;
continue;
}
for (g = 0; g < UNI_ROW_GLYPHS; g++, uni++) {
if (row[g] == 0xffff)
continue;
/*
* Found one, copy entry for unicode uni with
* fontpos value row[g].
*/
ret = con_insert_unipair(new, uni, row[g]);
if (ret) {
old->refcount++;
*vc->uni_pagedict_loc = old;
con_release_unimap(new);
kfree(new);
return ERR_PTR(ret);
}
}
}
}
return new;
}
int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
{
struct uni_pagedict *dict;
struct unipair *plist;
int err = 0;
if (!ct)
return 0;
struct unipair *unilist __free(kvfree) = vmemdup_array_user(list, ct, sizeof(*unilist));
if (IS_ERR(unilist))
return PTR_ERR(unilist);
guard(console_lock)();
/* Save original vc_unipagdir_loc in case we allocate a new one */
dict = *vc->uni_pagedict_loc;
if (!dict)
return -EINVAL;
if (dict->refcount > 1) {
dict = con_unshare_unimap(vc, dict);
if (IS_ERR(dict))
return PTR_ERR(dict);
} else if (dict == dflt) {
dflt = NULL;
}
/*
* Insert user specified unicode pairs into new table.
*/
for (plist = unilist; ct; ct--, plist++) {
int err1 = con_insert_unipair(dict, plist->unicode, plist->fontpos);
if (err1)
err = err1;
}
/*
* Merge with fontmaps of any other virtual consoles.
*/
if (con_unify_unimap(vc, dict))
return err;
for (enum translation_map m = FIRST_MAP; m <= LAST_MAP; m++)
set_inverse_transl(vc, dict, m);
set_inverse_trans_unicode(dict);
return err;
}
/**
* con_set_default_unimap - set default unicode map
* @vc: the console we are updating
*
* Loads the unimap for the hardware font, as defined in uni_hash.tbl.
* The representation used was the most compact I could come up
* with. This routine is executed at video setup, and when the
* PIO_FONTRESET ioctl is called.
*
* The caller must hold the console lock
*/
int con_set_default_unimap(struct vc_data *vc)
{
struct uni_pagedict *dict;
unsigned int fontpos, count;
int err = 0, err1;
u16 *dfont;
if (dflt) {
dict = *vc->uni_pagedict_loc;
if (dict == dflt)
return 0;
dflt->refcount++;
*vc->uni_pagedict_loc = dflt;
if (dict && !--dict->refcount) {
con_release_unimap(dict);
kfree(dict);
}
return 0;
}
/* The default font is always 256 characters */
err = con_do_clear_unimap(vc);
if (err)
return err;
dict = *vc->uni_pagedict_loc;
dfont = dfont_unitable;
for (fontpos = 0; fontpos < 256U; fontpos++)
for (count = dfont_unicount[fontpos]; count; count--) {
err1 = con_insert_unipair(dict, *(dfont++), fontpos);
if (err1)
err = err1;
}
if (con_unify_unimap(vc, dict)) {
dflt = *vc->uni_pagedict_loc;
return err;
}
for (enum translation_map m = FIRST_MAP; m <= LAST_MAP; m++)
set_inverse_transl(vc, dict, m);
set_inverse_trans_unicode(dict);
dflt = dict;
return err;
}
EXPORT_SYMBOL(con_set_default_unimap);
/**
* con_copy_unimap - copy unimap between two vts
* @dst_vc: target
* @src_vc: source
*
* The caller must hold the console lock when invoking this method
*/
int con_copy_unimap(struct vc_data *dst_vc, struct vc_data *src_vc)
{
struct uni_pagedict *src;
if (!*src_vc->uni_pagedict_loc)
return -EINVAL;
if (*dst_vc->uni_pagedict_loc == *src_vc->uni_pagedict_loc)
return 0;
con_free_unimap(dst_vc);
src = *src_vc->uni_pagedict_loc;
src->refcount++;
*dst_vc->uni_pagedict_loc = src;
return 0;
}
EXPORT_SYMBOL(con_copy_unimap);
/*
* con_get_unimap - get the unicode map
*
* Read the console unicode data for this console. Called from the ioctl
* handlers.
*/
int con_get_unimap(struct vc_data *vc, ushort ct, ushort __user *uct,
struct unipair __user *list)
{
ushort ect;
struct uni_pagedict *dict;
unsigned int d, r, g;
struct unipair *unilist __free(kvfree) = kvmalloc_array(ct, sizeof(*unilist), GFP_KERNEL);
if (!unilist)
return -ENOMEM;
scoped_guard(console_lock) {
ect = 0;
dict = *vc->uni_pagedict_loc;
if (!dict)
break;
for (d = 0; d < UNI_DIRS; d++) {
u16 **dir = dict->uni_pgdir[d];
if (!dir)
continue;
for (r = 0; r < UNI_DIR_ROWS; r++) {
u16 *row = dir[r];
if (!row)
continue;
for (g = 0; g < UNI_ROW_GLYPHS; g++, row++) {
if (*row >= MAX_GLYPH)
continue;
if (ect < ct) {
unilist[ect].unicode = UNI(d, r, g);
unilist[ect].fontpos = *row;
}
ect++;
}
}
}
}
if (copy_to_user(list, unilist, min(ect, ct) * sizeof(*unilist)))
return -EFAULT;
if (put_user(ect, uct))
return -EFAULT;
if (ect > ct)
return -ENOMEM;
return 0;
}
/*
* Always use USER_MAP. These functions are used by the keyboard,
* which shouldn't be affected by G0/G1 switching, etc.
* If the user map still contains default values, i.e. the
* direct-to-font mapping, then assume user is using Latin1.
*
* FIXME: at some point we need to decide if we want to lock the table
* update element itself via the keyboard_event_lock for consistency with the
* keyboard driver as well as the consoles
*/
/* may be called during an interrupt */
u32 conv_8bit_to_uni(unsigned char c)
{
unsigned short uni = translations[USER_MAP][c];
return uni == (0xf000 | c) ? c : uni;
}
int conv_uni_to_8bit(u32 uni)
{
int c;
for (c = 0; c < ARRAY_SIZE(translations[USER_MAP]); c++)
if (translations[USER_MAP][c] == uni ||
(translations[USER_MAP][c] == (c | 0xf000) && uni == c))
return c;
return -1;
}
int conv_uni_to_pc(struct vc_data *conp, long ucs)
{
struct uni_pagedict *dict;
u16 **dir, *row, glyph;
/* Only 16-bit codes supported at this time */
if (ucs > 0xffff)
return -4; /* Not found */
else if (ucs < 0x20)
return -1; /* Not a printable character */
/*
* UNI_DIRECT_BASE indicates the start of the region in the User Zone
* which always has a 1:1 mapping to the currently loaded font. The
* UNI_DIRECT_MASK indicates the bit span of the region.
*/
else if ((ucs & ~UNI_DIRECT_MASK) == UNI_DIRECT_BASE)
return ucs & UNI_DIRECT_MASK;
dict = *conp->uni_pagedict_loc;
if (!dict)
return -3;
dir = dict->uni_pgdir[UNI_DIR(ucs)];
if (!dir)
return -4;
row = dir[UNI_ROW(ucs)];
if (!row)
return -4;
glyph = row[UNI_GLYPH(ucs)];
if (glyph >= MAX_GLYPH)
return -4;
return glyph;
}
/*
* This is called at sys_setup time, after memory and the console are
* initialized. It must be possible to call kmalloc(..., GFP_KERNEL)
* from this function, hence the call from sys_setup.
*/
void __init
console_map_init(void)
{
int i;
for (i = 0; i < MAX_NR_CONSOLES; i++)
if (vc_cons_allocated(i) && !*vc_cons[i].d->uni_pagedict_loc)
con_set_default_unimap(vc_cons[i].d);
}
+292
View File
@@ -0,0 +1,292 @@
# SPDX-License-Identifier: GPL-2.0
#
# Unicode table for IBM Codepage 437. Note that there are many more
# substitutions that could be conceived (for example, thick-line
# graphs probably should be replaced with double-line ones, accented
# Latin characters should replaced with their nonaccented versions,
# and some upper case Greek characters could be replaced by Latin), however,
# I have limited myself to the Unicodes used by the kernel ISO 8859-1,
# DEC VT, and IBM CP 437 tables.
#
# --------------------------------
#
# Basic IBM dingbats, some of which will never have a purpose clear
# to mankind
#
0x00 U+0000
0x01 U+263a
0x02 U+263b
0x03 U+2665
0x04 U+2666 U+25c6
0x05 U+2663
0x06 U+2660
0x07 U+2022
0x08 U+25d8
0x09 U+25cb
0x0a U+25d9
0x0b U+2642
0x0c U+2640
0x0d U+266a
0x0e U+266b
0x0f U+263c U+00a4
0x10 U+25b6 U+25ba
0x11 U+25c0 U+25c4
0x12 U+2195
0x13 U+203c
0x14 U+00b6
0x15 U+00a7
0x16 U+25ac
0x17 U+21a8
0x18 U+2191
0x19 U+2193
0x1a U+2192
0x1b U+2190
0x1c U+221f
0x1d U+2194
0x1e U+25b2
0x1f U+25bc
#
# The ASCII range is identity-mapped, but some of the characters also
# have to act as substitutes, especially the upper-case characters.
#
0x20 U+0020
0x21 U+0021
0x22 U+0022 U+00a8
0x23 U+0023
0x24 U+0024
0x25 U+0025
0x26 U+0026
0x27 U+0027 U+00b4
0x28 U+0028
0x29 U+0029
0x2a U+002a
0x2b U+002b
0x2c U+002c U+00b8
0x2d U+002d U+00ad
0x2e U+002e
0x2f U+002f
0x30 U+0030
0x31 U+0031
0x32 U+0032
0x33 U+0033
0x34 U+0034
0x35 U+0035
0x36 U+0036
0x37 U+0037
0x38 U+0038
0x39 U+0039
0x3a U+003a
0x3b U+003b
0x3c U+003c
0x3d U+003d
0x3e U+003e
0x3f U+003f
0x40 U+0040
0x41 U+0041 U+00c0 U+00c1 U+00c2 U+00c3
0x42 U+0042
0x43 U+0043 U+00a9
0x44 U+0044 U+00d0
0x45 U+0045 U+00c8 U+00ca U+00cb
0x46 U+0046
0x47 U+0047
0x48 U+0048
0x49 U+0049 U+00cc U+00cd U+00ce U+00cf
0x4a U+004a
0x4b U+004b U+212a
0x4c U+004c
0x4d U+004d
0x4e U+004e
0x4f U+004f U+00d2 U+00d3 U+00d4 U+00d5
0x50 U+0050
0x51 U+0051
0x52 U+0052 U+00ae
0x53 U+0053
0x54 U+0054
0x55 U+0055 U+00d9 U+00da U+00db
0x56 U+0056
0x57 U+0057
0x58 U+0058
0x59 U+0059 U+00dd
0x5a U+005a
0x5b U+005b
0x5c U+005c
0x5d U+005d
0x5e U+005e
0x5f U+005f U+23bd U+f804
0x60 U+0060
0x61 U+0061 U+00e3
0x62 U+0062
0x63 U+0063
0x64 U+0064
0x65 U+0065
0x66 U+0066
0x67 U+0067
0x68 U+0068
0x69 U+0069
0x6a U+006a
0x6b U+006b
0x6c U+006c
0x6d U+006d
0x6e U+006e
0x6f U+006f U+00f5
0x70 U+0070
0x71 U+0071
0x72 U+0072
0x73 U+0073
0x74 U+0074
0x75 U+0075
0x76 U+0076
0x77 U+0077
0x78 U+0078 U+00d7
0x79 U+0079 U+00fd
0x7a U+007a
0x7b U+007b
0x7c U+007c U+00a6
0x7d U+007d
0x7e U+007e
#
# Okay, what on Earth is this one supposed to be used for?
#
0x7f U+2302
#
# Non-English characters, mostly lower case letters...
#
0x80 U+00c7
0x81 U+00fc
0x82 U+00e9
0x83 U+00e2
0x84 U+00e4
0x85 U+00e0
0x86 U+00e5
0x87 U+00e7
0x88 U+00ea
0x89 U+00eb
0x8a U+00e8
0x8b U+00ef
0x8c U+00ee
0x8d U+00ec
0x8e U+00c4
0x8f U+00c5 U+212b
0x90 U+00c9
0x91 U+00e6
0x92 U+00c6
0x93 U+00f4
0x94 U+00f6
0x95 U+00f2
0x96 U+00fb
0x97 U+00f9
0x98 U+00ff
0x99 U+00d6
0x9a U+00dc
0x9b U+00a2
0x9c U+00a3
0x9d U+00a5
0x9e U+20a7
0x9f U+0192
0xa0 U+00e1
0xa1 U+00ed
0xa2 U+00f3
0xa3 U+00fa
0xa4 U+00f1
0xa5 U+00d1
0xa6 U+00aa
0xa7 U+00ba
0xa8 U+00bf
0xa9 U+2310
0xaa U+00ac
0xab U+00bd
0xac U+00bc
0xad U+00a1
0xae U+00ab
0xaf U+00bb
#
# Block graphics
#
0xb0 U+2591
0xb1 U+2592
0xb2 U+2593
0xb3 U+2502
0xb4 U+2524
0xb5 U+2561
0xb6 U+2562
0xb7 U+2556
0xb8 U+2555
0xb9 U+2563
0xba U+2551
0xbb U+2557
0xbc U+255d
0xbd U+255c
0xbe U+255b
0xbf U+2510
0xc0 U+2514
0xc1 U+2534
0xc2 U+252c
0xc3 U+251c
0xc4 U+2500
0xc5 U+253c
0xc6 U+255e
0xc7 U+255f
0xc8 U+255a
0xc9 U+2554
0xca U+2569
0xcb U+2566
0xcc U+2560
0xcd U+2550
0xce U+256c
0xcf U+2567
0xd0 U+2568
0xd1 U+2564
0xd2 U+2565
0xd3 U+2559
0xd4 U+2558
0xd5 U+2552
0xd6 U+2553
0xd7 U+256b
0xd8 U+256a
0xd9 U+2518
0xda U+250c
0xdb U+2588
0xdc U+2584
0xdd U+258c
0xde U+2590
0xdf U+2580
#
# Greek letters and mathematical symbols
#
0xe0 U+03b1
0xe1 U+03b2 U+00df
0xe2 U+0393
0xe3 U+03c0
0xe4 U+03a3
0xe5 U+03c3
0xe6 U+00b5 U+03bc
0xe7 U+03c4
0xe8 U+03a6 U+00d8
0xe9 U+0398
0xea U+03a9 U+2126
0xeb U+03b4 U+00f0
0xec U+221e
0xed U+03c6 U+00f8
0xee U+03b5 U+2208
0xef U+2229
0xf0 U+2261
0xf1 U+00b1
0xf2 U+2265
0xf3 U+2264
0xf4 U+2320
0xf5 U+2321
0xf6 U+00f7
0xf7 U+2248
0xf8 U+00b0
0xf9 U+2219
0xfa U+00b7
0xfb U+221a
0xfc U+207f
0xfd U+00b2
#
# Square bullet, non-spacing blank
# Mapping U+fffd to the square bullet means it is the substitution
# character
#
0xfe U+25a0 U+fffd
0xff U+00a0
@@ -0,0 +1,375 @@
// SPDX-License-Identifier: GPL-2.0
/* Do not edit this file! It was automatically generated by */
/* loadkeys --mktable --unicode defkeymap.map > defkeymap.c */
#include <linux/types.h>
#include <linux/keyboard.h>
#include <linux/kd.h>
unsigned short plain_map[NR_KEYS] = {
0xf200, 0xf01b, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036,
0xf037, 0xf038, 0xf039, 0xf030, 0xf02d, 0xf03d, 0xf07f, 0xf009,
0xfb71, 0xfb77, 0xfb65, 0xfb72, 0xfb74, 0xfb79, 0xfb75, 0xfb69,
0xfb6f, 0xfb70, 0xf05b, 0xf05d, 0xf201, 0xf702, 0xfb61, 0xfb73,
0xfb64, 0xfb66, 0xfb67, 0xfb68, 0xfb6a, 0xfb6b, 0xfb6c, 0xf03b,
0xf027, 0xf060, 0xf700, 0xf05c, 0xfb7a, 0xfb78, 0xfb63, 0xfb76,
0xfb62, 0xfb6e, 0xfb6d, 0xf02c, 0xf02e, 0xf02f, 0xf700, 0xf30c,
0xf703, 0xf020, 0xf207, 0xf100, 0xf101, 0xf102, 0xf103, 0xf104,
0xf105, 0xf106, 0xf107, 0xf108, 0xf109, 0xf208, 0xf209, 0xf307,
0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301,
0xf302, 0xf303, 0xf300, 0xf310, 0xf206, 0xf200, 0xf03c, 0xf10a,
0xf10b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf30e, 0xf702, 0xf30d, 0xf01c, 0xf701, 0xf205, 0xf114, 0xf603,
0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116,
0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
};
static unsigned short shift_map[NR_KEYS] = {
0xf200, 0xf01b, 0xf021, 0xf040, 0xf023, 0xf024, 0xf025, 0xf05e,
0xf026, 0xf02a, 0xf028, 0xf029, 0xf05f, 0xf02b, 0xf07f, 0xf009,
0xfb51, 0xfb57, 0xfb45, 0xfb52, 0xfb54, 0xfb59, 0xfb55, 0xfb49,
0xfb4f, 0xfb50, 0xf07b, 0xf07d, 0xf201, 0xf702, 0xfb41, 0xfb53,
0xfb44, 0xfb46, 0xfb47, 0xfb48, 0xfb4a, 0xfb4b, 0xfb4c, 0xf03a,
0xf022, 0xf07e, 0xf700, 0xf07c, 0xfb5a, 0xfb58, 0xfb43, 0xfb56,
0xfb42, 0xfb4e, 0xfb4d, 0xf03c, 0xf03e, 0xf03f, 0xf700, 0xf30c,
0xf703, 0xf020, 0xf207, 0xf10a, 0xf10b, 0xf10c, 0xf10d, 0xf10e,
0xf10f, 0xf110, 0xf111, 0xf112, 0xf113, 0xf213, 0xf203, 0xf307,
0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301,
0xf302, 0xf303, 0xf300, 0xf310, 0xf206, 0xf200, 0xf03e, 0xf10a,
0xf10b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf30e, 0xf702, 0xf30d, 0xf200, 0xf701, 0xf205, 0xf114, 0xf603,
0xf20b, 0xf601, 0xf602, 0xf117, 0xf600, 0xf20a, 0xf115, 0xf116,
0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
};
static unsigned short altgr_map[NR_KEYS] = {
0xf200, 0xf200, 0xf200, 0xf040, 0xf200, 0xf024, 0xf200, 0xf200,
0xf07b, 0xf05b, 0xf05d, 0xf07d, 0xf05c, 0xf200, 0xf200, 0xf200,
0xfb71, 0xfb77, 0xf918, 0xfb72, 0xfb74, 0xfb79, 0xfb75, 0xfb69,
0xfb6f, 0xfb70, 0xf200, 0xf07e, 0xf201, 0xf702, 0xf914, 0xfb73,
0xf917, 0xf919, 0xfb67, 0xfb68, 0xfb6a, 0xfb6b, 0xfb6c, 0xf200,
0xf200, 0xf200, 0xf700, 0xf200, 0xfb7a, 0xfb78, 0xf916, 0xfb76,
0xf915, 0xfb6e, 0xfb6d, 0xf200, 0xf200, 0xf200, 0xf700, 0xf30c,
0xf703, 0xf200, 0xf207, 0xf50c, 0xf50d, 0xf50e, 0xf50f, 0xf510,
0xf511, 0xf512, 0xf513, 0xf514, 0xf515, 0xf208, 0xf202, 0xf911,
0xf912, 0xf913, 0xf30b, 0xf90e, 0xf90f, 0xf910, 0xf30a, 0xf90b,
0xf90c, 0xf90d, 0xf90a, 0xf310, 0xf206, 0xf200, 0xf07c, 0xf516,
0xf517, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf30e, 0xf702, 0xf30d, 0xf200, 0xf701, 0xf205, 0xf114, 0xf603,
0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116,
0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
};
static unsigned short ctrl_map[NR_KEYS] = {
0xf200, 0xf200, 0xf200, 0xf000, 0xf01b, 0xf01c, 0xf01d, 0xf01e,
0xf01f, 0xf07f, 0xf200, 0xf200, 0xf01f, 0xf200, 0xf008, 0xf200,
0xf011, 0xf017, 0xf005, 0xf012, 0xf014, 0xf019, 0xf015, 0xf009,
0xf00f, 0xf010, 0xf01b, 0xf01d, 0xf201, 0xf702, 0xf001, 0xf013,
0xf004, 0xf006, 0xf007, 0xf008, 0xf00a, 0xf00b, 0xf00c, 0xf200,
0xf007, 0xf000, 0xf700, 0xf01c, 0xf01a, 0xf018, 0xf003, 0xf016,
0xf002, 0xf00e, 0xf00d, 0xf200, 0xf20e, 0xf07f, 0xf700, 0xf30c,
0xf703, 0xf000, 0xf207, 0xf100, 0xf101, 0xf102, 0xf103, 0xf104,
0xf105, 0xf106, 0xf107, 0xf108, 0xf109, 0xf208, 0xf204, 0xf307,
0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301,
0xf302, 0xf303, 0xf300, 0xf310, 0xf206, 0xf200, 0xf200, 0xf10a,
0xf10b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf30e, 0xf702, 0xf30d, 0xf01c, 0xf701, 0xf205, 0xf114, 0xf603,
0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116,
0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
};
static unsigned short shift_ctrl_map[NR_KEYS] = {
0xf200, 0xf200, 0xf200, 0xf000, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf01f, 0xf200, 0xf200, 0xf200,
0xf011, 0xf017, 0xf005, 0xf012, 0xf014, 0xf019, 0xf015, 0xf009,
0xf00f, 0xf010, 0xf200, 0xf200, 0xf201, 0xf702, 0xf001, 0xf013,
0xf004, 0xf006, 0xf007, 0xf008, 0xf00a, 0xf00b, 0xf00c, 0xf200,
0xf200, 0xf200, 0xf700, 0xf200, 0xf01a, 0xf018, 0xf003, 0xf016,
0xf002, 0xf00e, 0xf00d, 0xf200, 0xf200, 0xf200, 0xf700, 0xf30c,
0xf703, 0xf200, 0xf207, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf208, 0xf200, 0xf307,
0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301,
0xf302, 0xf303, 0xf300, 0xf310, 0xf206, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf30e, 0xf702, 0xf30d, 0xf200, 0xf701, 0xf205, 0xf114, 0xf603,
0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116,
0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
};
static unsigned short alt_map[NR_KEYS] = {
0xf200, 0xf81b, 0xf831, 0xf832, 0xf833, 0xf834, 0xf835, 0xf836,
0xf837, 0xf838, 0xf839, 0xf830, 0xf82d, 0xf83d, 0xf87f, 0xf809,
0xf871, 0xf877, 0xf865, 0xf872, 0xf874, 0xf879, 0xf875, 0xf869,
0xf86f, 0xf870, 0xf85b, 0xf85d, 0xf80d, 0xf702, 0xf861, 0xf873,
0xf864, 0xf866, 0xf867, 0xf868, 0xf86a, 0xf86b, 0xf86c, 0xf83b,
0xf827, 0xf860, 0xf700, 0xf85c, 0xf87a, 0xf878, 0xf863, 0xf876,
0xf862, 0xf86e, 0xf86d, 0xf82c, 0xf82e, 0xf82f, 0xf700, 0xf30c,
0xf703, 0xf820, 0xf207, 0xf500, 0xf501, 0xf502, 0xf503, 0xf504,
0xf505, 0xf506, 0xf507, 0xf508, 0xf509, 0xf208, 0xf209, 0xf907,
0xf908, 0xf909, 0xf30b, 0xf904, 0xf905, 0xf906, 0xf30a, 0xf901,
0xf902, 0xf903, 0xf900, 0xf310, 0xf206, 0xf200, 0xf83c, 0xf50a,
0xf50b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf30e, 0xf702, 0xf30d, 0xf01c, 0xf701, 0xf205, 0xf114, 0xf603,
0xf118, 0xf210, 0xf211, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116,
0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
};
static unsigned short ctrl_alt_map[NR_KEYS] = {
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf811, 0xf817, 0xf805, 0xf812, 0xf814, 0xf819, 0xf815, 0xf809,
0xf80f, 0xf810, 0xf200, 0xf200, 0xf201, 0xf702, 0xf801, 0xf813,
0xf804, 0xf806, 0xf807, 0xf808, 0xf80a, 0xf80b, 0xf80c, 0xf200,
0xf200, 0xf200, 0xf700, 0xf200, 0xf81a, 0xf818, 0xf803, 0xf816,
0xf802, 0xf80e, 0xf80d, 0xf200, 0xf200, 0xf200, 0xf700, 0xf30c,
0xf703, 0xf200, 0xf207, 0xf500, 0xf501, 0xf502, 0xf503, 0xf504,
0xf505, 0xf506, 0xf507, 0xf508, 0xf509, 0xf208, 0xf200, 0xf307,
0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301,
0xf302, 0xf303, 0xf300, 0xf20c, 0xf206, 0xf200, 0xf200, 0xf50a,
0xf50b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf30e, 0xf702, 0xf30d, 0xf200, 0xf701, 0xf205, 0xf114, 0xf603,
0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf20c,
0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
};
unsigned short *key_maps[MAX_NR_KEYMAPS] = {
plain_map, shift_map, altgr_map, NULL,
ctrl_map, shift_ctrl_map, NULL, NULL,
alt_map, NULL, NULL, NULL,
ctrl_alt_map, NULL
};
unsigned int keymap_count = 7;
/*
* Philosophy: most people do not define more strings, but they who do
* often want quite a lot of string space. So, we statically allocate
* the default and allocate dynamically in chunks of 512 bytes.
*/
char func_buf[] = {
'\033', '[', '[', 'A', 0,
'\033', '[', '[', 'B', 0,
'\033', '[', '[', 'C', 0,
'\033', '[', '[', 'D', 0,
'\033', '[', '[', 'E', 0,
'\033', '[', '1', '7', '~', 0,
'\033', '[', '1', '8', '~', 0,
'\033', '[', '1', '9', '~', 0,
'\033', '[', '2', '0', '~', 0,
'\033', '[', '2', '1', '~', 0,
'\033', '[', '2', '3', '~', 0,
'\033', '[', '2', '4', '~', 0,
'\033', '[', '2', '5', '~', 0,
'\033', '[', '2', '6', '~', 0,
'\033', '[', '2', '8', '~', 0,
'\033', '[', '2', '9', '~', 0,
'\033', '[', '3', '1', '~', 0,
'\033', '[', '3', '2', '~', 0,
'\033', '[', '3', '3', '~', 0,
'\033', '[', '3', '4', '~', 0,
'\033', '[', '1', '~', 0,
'\033', '[', '2', '~', 0,
'\033', '[', '3', '~', 0,
'\033', '[', '4', '~', 0,
'\033', '[', '5', '~', 0,
'\033', '[', '6', '~', 0,
'\033', '[', 'M', 0,
'\033', '[', 'P', 0,
};
char *funcbufptr = func_buf;
int funcbufsize = sizeof(func_buf);
int funcbufleft = 0; /* space left */
char *func_table[MAX_NR_FUNC] = {
func_buf + 0,
func_buf + 5,
func_buf + 10,
func_buf + 15,
func_buf + 20,
func_buf + 25,
func_buf + 31,
func_buf + 37,
func_buf + 43,
func_buf + 49,
func_buf + 55,
func_buf + 61,
func_buf + 67,
func_buf + 73,
func_buf + 79,
func_buf + 85,
func_buf + 91,
func_buf + 97,
func_buf + 103,
func_buf + 109,
func_buf + 115,
func_buf + 120,
func_buf + 125,
func_buf + 130,
func_buf + 135,
func_buf + 140,
func_buf + 145,
NULL,
NULL,
func_buf + 149,
NULL,
};
struct kbdiacruc accent_table[MAX_DIACR] = {
{'`', 'A', 0x00c0}, {'`', 'a', 0x00e0},
{'\'', 'A', 0x00c1}, {'\'', 'a', 0x00e1},
{'^', 'A', 0x00c2}, {'^', 'a', 0x00e2},
{'~', 'A', 0x00c3}, {'~', 'a', 0x00e3},
{'"', 'A', 0x00c4}, {'"', 'a', 0x00e4},
{'O', 'A', 0x00c5}, {'o', 'a', 0x00e5},
{'0', 'A', 0x00c5}, {'0', 'a', 0x00e5},
{'A', 'A', 0x00c5}, {'a', 'a', 0x00e5},
{'A', 'E', 0x00c6}, {'a', 'e', 0x00e6},
{',', 'C', 0x00c7}, {',', 'c', 0x00e7},
{'`', 'E', 0x00c8}, {'`', 'e', 0x00e8},
{'\'', 'E', 0x00c9}, {'\'', 'e', 0x00e9},
{'^', 'E', 0x00ca}, {'^', 'e', 0x00ea},
{'"', 'E', 0x00cb}, {'"', 'e', 0x00eb},
{'`', 'I', 0x00cc}, {'`', 'i', 0x00ec},
{'\'', 'I', 0x00cd}, {'\'', 'i', 0x00ed},
{'^', 'I', 0x00ce}, {'^', 'i', 0x00ee},
{'"', 'I', 0x00cf}, {'"', 'i', 0x00ef},
{'-', 'D', 0x00d0}, {'-', 'd', 0x00f0},
{'~', 'N', 0x00d1}, {'~', 'n', 0x00f1},
{'`', 'O', 0x00d2}, {'`', 'o', 0x00f2},
{'\'', 'O', 0x00d3}, {'\'', 'o', 0x00f3},
{'^', 'O', 0x00d4}, {'^', 'o', 0x00f4},
{'~', 'O', 0x00d5}, {'~', 'o', 0x00f5},
{'"', 'O', 0x00d6}, {'"', 'o', 0x00f6},
{'/', 'O', 0x00d8}, {'/', 'o', 0x00f8},
{'`', 'U', 0x00d9}, {'`', 'u', 0x00f9},
{'\'', 'U', 0x00da}, {'\'', 'u', 0x00fa},
{'^', 'U', 0x00db}, {'^', 'u', 0x00fb},
{'"', 'U', 0x00dc}, {'"', 'u', 0x00fc},
{'\'', 'Y', 0x00dd}, {'\'', 'y', 0x00fd},
{'T', 'H', 0x00de}, {'t', 'h', 0x00fe},
{'s', 's', 0x00df}, {'"', 'y', 0x00ff},
{'s', 'z', 0x00df}, {'i', 'j', 0x00ff},
};
unsigned int accent_table_size = 68;
+358
View File
@@ -0,0 +1,358 @@
# SPDX-License-Identifier: GPL-2.0
# Default kernel keymap. This uses 7 modifier combinations.
keymaps 0-2,4-5,8,12
# Change the above line into
# keymaps 0-2,4-6,8,12
# in case you want the entries
# altgr control keycode 83 = Boot
# altgr control keycode 111 = Boot
# below.
#
# In fact AltGr is used very little, and one more keymap can
# be saved by mapping AltGr to Alt (and adapting a few entries):
# keycode 100 = Alt
#
keycode 1 = Escape Escape
alt keycode 1 = Meta_Escape
keycode 2 = one exclam
alt keycode 2 = Meta_one
keycode 3 = two at at
control keycode 3 = nul
shift control keycode 3 = nul
alt keycode 3 = Meta_two
keycode 4 = three numbersign
control keycode 4 = Escape
alt keycode 4 = Meta_three
keycode 5 = four dollar dollar
control keycode 5 = Control_backslash
alt keycode 5 = Meta_four
keycode 6 = five percent
control keycode 6 = Control_bracketright
alt keycode 6 = Meta_five
keycode 7 = six asciicircum
control keycode 7 = Control_asciicircum
alt keycode 7 = Meta_six
keycode 8 = seven ampersand braceleft
control keycode 8 = Control_underscore
alt keycode 8 = Meta_seven
keycode 9 = eight asterisk bracketleft
control keycode 9 = Delete
alt keycode 9 = Meta_eight
keycode 10 = nine parenleft bracketright
alt keycode 10 = Meta_nine
keycode 11 = zero parenright braceright
alt keycode 11 = Meta_zero
keycode 12 = minus underscore backslash
control keycode 12 = Control_underscore
shift control keycode 12 = Control_underscore
alt keycode 12 = Meta_minus
keycode 13 = equal plus
alt keycode 13 = Meta_equal
keycode 14 = Delete Delete
control keycode 14 = BackSpace
alt keycode 14 = Meta_Delete
keycode 15 = Tab Tab
alt keycode 15 = Meta_Tab
keycode 16 = q
keycode 17 = w
keycode 18 = e
altgr keycode 18 = Hex_E
keycode 19 = r
keycode 20 = t
keycode 21 = y
keycode 22 = u
keycode 23 = i
keycode 24 = o
keycode 25 = p
keycode 26 = bracketleft braceleft
control keycode 26 = Escape
alt keycode 26 = Meta_bracketleft
keycode 27 = bracketright braceright asciitilde
control keycode 27 = Control_bracketright
alt keycode 27 = Meta_bracketright
keycode 28 = Return
alt keycode 28 = Meta_Control_m
keycode 29 = Control
keycode 30 = a
altgr keycode 30 = Hex_A
keycode 31 = s
keycode 32 = d
altgr keycode 32 = Hex_D
keycode 33 = f
altgr keycode 33 = Hex_F
keycode 34 = g
keycode 35 = h
keycode 36 = j
keycode 37 = k
keycode 38 = l
keycode 39 = semicolon colon
alt keycode 39 = Meta_semicolon
keycode 40 = apostrophe quotedbl
control keycode 40 = Control_g
alt keycode 40 = Meta_apostrophe
keycode 41 = grave asciitilde
control keycode 41 = nul
alt keycode 41 = Meta_grave
keycode 42 = Shift
keycode 43 = backslash bar
control keycode 43 = Control_backslash
alt keycode 43 = Meta_backslash
keycode 44 = z
keycode 45 = x
keycode 46 = c
altgr keycode 46 = Hex_C
keycode 47 = v
keycode 48 = b
altgr keycode 48 = Hex_B
keycode 49 = n
keycode 50 = m
keycode 51 = comma less
alt keycode 51 = Meta_comma
keycode 52 = period greater
control keycode 52 = Compose
alt keycode 52 = Meta_period
keycode 53 = slash question
control keycode 53 = Delete
alt keycode 53 = Meta_slash
keycode 54 = Shift
keycode 55 = KP_Multiply
keycode 56 = Alt
keycode 57 = space space
control keycode 57 = nul
alt keycode 57 = Meta_space
keycode 58 = Caps_Lock
keycode 59 = F1 F11 Console_13
control keycode 59 = F1
alt keycode 59 = Console_1
control alt keycode 59 = Console_1
keycode 60 = F2 F12 Console_14
control keycode 60 = F2
alt keycode 60 = Console_2
control alt keycode 60 = Console_2
keycode 61 = F3 F13 Console_15
control keycode 61 = F3
alt keycode 61 = Console_3
control alt keycode 61 = Console_3
keycode 62 = F4 F14 Console_16
control keycode 62 = F4
alt keycode 62 = Console_4
control alt keycode 62 = Console_4
keycode 63 = F5 F15 Console_17
control keycode 63 = F5
alt keycode 63 = Console_5
control alt keycode 63 = Console_5
keycode 64 = F6 F16 Console_18
control keycode 64 = F6
alt keycode 64 = Console_6
control alt keycode 64 = Console_6
keycode 65 = F7 F17 Console_19
control keycode 65 = F7
alt keycode 65 = Console_7
control alt keycode 65 = Console_7
keycode 66 = F8 F18 Console_20
control keycode 66 = F8
alt keycode 66 = Console_8
control alt keycode 66 = Console_8
keycode 67 = F9 F19 Console_21
control keycode 67 = F9
alt keycode 67 = Console_9
control alt keycode 67 = Console_9
keycode 68 = F10 F20 Console_22
control keycode 68 = F10
alt keycode 68 = Console_10
control alt keycode 68 = Console_10
keycode 69 = Num_Lock
shift keycode 69 = Bare_Num_Lock
keycode 70 = Scroll_Lock Show_Memory Show_Registers
control keycode 70 = Show_State
alt keycode 70 = Scroll_Lock
keycode 71 = KP_7
alt keycode 71 = Ascii_7
altgr keycode 71 = Hex_7
keycode 72 = KP_8
alt keycode 72 = Ascii_8
altgr keycode 72 = Hex_8
keycode 73 = KP_9
alt keycode 73 = Ascii_9
altgr keycode 73 = Hex_9
keycode 74 = KP_Subtract
keycode 75 = KP_4
alt keycode 75 = Ascii_4
altgr keycode 75 = Hex_4
keycode 76 = KP_5
alt keycode 76 = Ascii_5
altgr keycode 76 = Hex_5
keycode 77 = KP_6
alt keycode 77 = Ascii_6
altgr keycode 77 = Hex_6
keycode 78 = KP_Add
keycode 79 = KP_1
alt keycode 79 = Ascii_1
altgr keycode 79 = Hex_1
keycode 80 = KP_2
alt keycode 80 = Ascii_2
altgr keycode 80 = Hex_2
keycode 81 = KP_3
alt keycode 81 = Ascii_3
altgr keycode 81 = Hex_3
keycode 82 = KP_0
alt keycode 82 = Ascii_0
altgr keycode 82 = Hex_0
keycode 83 = KP_Period
# altgr control keycode 83 = Boot
control alt keycode 83 = Boot
keycode 84 = Last_Console
keycode 85 =
keycode 86 = less greater bar
alt keycode 86 = Meta_less
keycode 87 = F11 F11 Console_23
control keycode 87 = F11
alt keycode 87 = Console_11
control alt keycode 87 = Console_11
keycode 88 = F12 F12 Console_24
control keycode 88 = F12
alt keycode 88 = Console_12
control alt keycode 88 = Console_12
keycode 89 =
keycode 90 =
keycode 91 =
keycode 92 =
keycode 93 =
keycode 94 =
keycode 95 =
keycode 96 = KP_Enter
keycode 97 = Control
keycode 98 = KP_Divide
keycode 99 = Control_backslash
control keycode 99 = Control_backslash
alt keycode 99 = Control_backslash
keycode 100 = AltGr
keycode 101 = Break
keycode 102 = Find
keycode 103 = Up
keycode 104 = Prior
shift keycode 104 = Scroll_Backward
keycode 105 = Left
alt keycode 105 = Decr_Console
keycode 106 = Right
alt keycode 106 = Incr_Console
keycode 107 = Select
keycode 108 = Down
keycode 109 = Next
shift keycode 109 = Scroll_Forward
keycode 110 = Insert
keycode 111 = Remove
# altgr control keycode 111 = Boot
control alt keycode 111 = Boot
keycode 112 = Macro
keycode 113 = F13
keycode 114 = F14
keycode 115 = Help
keycode 116 = Do
keycode 117 = F17
keycode 118 = KP_MinPlus
keycode 119 = Pause
keycode 120 =
keycode 121 =
keycode 122 =
keycode 123 =
keycode 124 =
keycode 125 =
keycode 126 =
keycode 127 =
string F1 = "\033[[A"
string F2 = "\033[[B"
string F3 = "\033[[C"
string F4 = "\033[[D"
string F5 = "\033[[E"
string F6 = "\033[17~"
string F7 = "\033[18~"
string F8 = "\033[19~"
string F9 = "\033[20~"
string F10 = "\033[21~"
string F11 = "\033[23~"
string F12 = "\033[24~"
string F13 = "\033[25~"
string F14 = "\033[26~"
string F15 = "\033[28~"
string F16 = "\033[29~"
string F17 = "\033[31~"
string F18 = "\033[32~"
string F19 = "\033[33~"
string F20 = "\033[34~"
string Find = "\033[1~"
string Insert = "\033[2~"
string Remove = "\033[3~"
string Select = "\033[4~"
string Prior = "\033[5~"
string Next = "\033[6~"
string Macro = "\033[M"
string Pause = "\033[P"
compose '`' 'A' to 'À'
compose '`' 'a' to 'à'
compose '\'' 'A' to 'Á'
compose '\'' 'a' to 'á'
compose '^' 'A' to 'Â'
compose '^' 'a' to 'â'
compose '~' 'A' to 'Ã'
compose '~' 'a' to 'ã'
compose '"' 'A' to 'Ä'
compose '"' 'a' to 'ä'
compose 'O' 'A' to 'Å'
compose 'o' 'a' to 'å'
compose '0' 'A' to 'Å'
compose '0' 'a' to 'å'
compose 'A' 'A' to 'Å'
compose 'a' 'a' to 'å'
compose 'A' 'E' to 'Æ'
compose 'a' 'e' to 'æ'
compose ',' 'C' to 'Ç'
compose ',' 'c' to 'ç'
compose '`' 'E' to 'È'
compose '`' 'e' to 'è'
compose '\'' 'E' to 'É'
compose '\'' 'e' to 'é'
compose '^' 'E' to 'Ê'
compose '^' 'e' to 'ê'
compose '"' 'E' to 'Ë'
compose '"' 'e' to 'ë'
compose '`' 'I' to 'Ì'
compose '`' 'i' to 'ì'
compose '\'' 'I' to 'Í'
compose '\'' 'i' to 'í'
compose '^' 'I' to 'Î'
compose '^' 'i' to 'î'
compose '"' 'I' to 'Ï'
compose '"' 'i' to 'ï'
compose '-' 'D' to 'Ð'
compose '-' 'd' to 'ð'
compose '~' 'N' to 'Ñ'
compose '~' 'n' to 'ñ'
compose '`' 'O' to 'Ò'
compose '`' 'o' to 'ò'
compose '\'' 'O' to 'Ó'
compose '\'' 'o' to 'ó'
compose '^' 'O' to 'Ô'
compose '^' 'o' to 'ô'
compose '~' 'O' to 'Õ'
compose '~' 'o' to 'õ'
compose '"' 'O' to 'Ö'
compose '"' 'o' to 'ö'
compose '/' 'O' to 'Ø'
compose '/' 'o' to 'ø'
compose '`' 'U' to 'Ù'
compose '`' 'u' to 'ù'
compose '\'' 'U' to 'Ú'
compose '\'' 'u' to 'ú'
compose '^' 'U' to 'Û'
compose '^' 'u' to 'û'
compose '"' 'U' to 'Ü'
compose '"' 'u' to 'ü'
compose '\'' 'Y' to 'Ý'
compose '\'' 'y' to 'ý'
compose 'T' 'H' to 'Þ'
compose 't' 'h' to 'þ'
compose 's' 's' to 'ß'
compose '"' 'y' to 'ÿ'
compose 's' 'z' to 'ß'
compose 'i' 'j' to 'ÿ'
+360
View File
@@ -0,0 +1,360 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-2.0
#
# Leverage Python's unidecode module to generate ucs_fallback_table.h
#
# The generated table maps complex characters to their simpler fallback forms
# for a terminal display when corresponding glyphs are unavailable.
#
# Usage:
# python3 gen_ucs_fallback_table.py # Generate fallback tables
# python3 gen_ucs_fallback_table.py -o FILE # Specify output file
import unicodedata
from unidecode import unidecode
import sys
import argparse
from collections import defaultdict
# Try to get unidecode version
try:
from importlib.metadata import version
unidecode_version = version('unidecode')
except:
unidecode_version = 'unknown'
# This script's file name
from pathlib import Path
this_file = Path(__file__).name
# Default output file name
DEFAULT_OUT_FILE = "ucs_fallback_table.h"
# Define the range marker value
RANGE_MARKER = 0x00
def generate_fallback_map():
"""Generate a fallback map using unidecode for all relevant Unicode points."""
fallback_map = {}
# Process BMP characters (0x0000 - 0xFFFF) to keep table size manageable
for cp in range(0x0080, 0x10000): # Skip ASCII range (0x00-0x7F)
char = chr(cp)
# Skip unassigned/control characters
try:
if not unicodedata.name(char, ''):
continue
except ValueError:
continue
# Get the unidecode transliteration
ascii_version = unidecode(char)
# Only store if it results in a single character mapping
if len(ascii_version) == 1:
fallback_map[cp] = ord(ascii_version)
# Apply manual overrides for special cases
fallback_map.update(get_special_overrides())
return fallback_map
def get_special_overrides():
"""Get special case overrides that need different handling than unidecode
provides... or doesn't provide at all."""
overrides = {}
# Multi-character unidecode output
# These map to single chars instead of unidecode's multiple-char mappings
# In a terminal fallback context, we need a single character rather than multiple
overrides[0x00C6] = ord('E') # Æ LATIN CAPITAL LETTER AE -> E (unidecode: "AE")
overrides[0x00E6] = ord('e') # æ LATIN SMALL LETTER AE -> e (unidecode: "ae")
overrides[0x0152] = ord('E') # Œ LATIN CAPITAL LIGATURE OE -> E (unidecode: "OE")
overrides[0x0153] = ord('e') # œ LATIN SMALL LETTER LIGATURE OE -> e (unidecode: "oe")
overrides[0x00DF] = ord('s') # ß LATIN SMALL LETTER SHARP S -> s (unidecode: "ss")
# Comparison operators that unidecode renders as multiple characters
overrides[0x2264] = ord('<') # ≤ LESS-THAN OR EQUAL TO -> < (unidecode: "<=")
overrides[0x2265] = ord('>') # ≥ GREATER-THAN OR EQUAL TO -> > (unidecode: ">=")
# Unidecode returns an empty string for these
overrides[0x2260] = ord('#') # ≠ NOT EQUAL TO -> # (unidecode: empty string)
# Quadrant block characters that unidecode doesn't map
for cp in range(0x2596, 0x259F+1):
overrides[cp] = ord('#') # ▖ ▗ ▘ ▙ etc. - map to # (unidecode: empty string)
# Directional arrows
# These provide better semantic meaning than unidecode's mappings
overrides[0x2192] = ord('>') # → RIGHTWARDS ARROW -> > (unidecode: "-")
overrides[0x2190] = ord('<') # ← LEFTWARDS ARROW -> < (unidecode: "-")
overrides[0x2191] = ord('^') # ↑ UPWARDS ARROW -> ^ (unidecode: "|")
overrides[0x2193] = ord('v') # ↓ DOWNWARDS ARROW -> v (unidecode: "|")
# Double arrows with their directional semantic mappings
overrides[0x21D0] = ord('<') # ⇐ LEFTWARDS DOUBLE ARROW -> <
overrides[0x21D1] = ord('^') # ⇑ UPWARDS DOUBLE ARROW -> ^
overrides[0x21D2] = ord('>') # ⇒ RIGHTWARDS DOUBLE ARROW -> >
overrides[0x21D3] = ord('v') # ⇓ DOWNWARDS DOUBLE ARROW -> v
# Halfwidth arrows
# These need the same treatment as their normal-width counterparts
overrides[0xFFE9] = ord('<') # ← HALFWIDTH LEFTWARDS ARROW -> < (unidecode: "-")
overrides[0xFFEA] = ord('^') # ↑ HALFWIDTH UPWARDS ARROW -> ^ (unidecode: "|")
overrides[0xFFEB] = ord('>') # → HALFWIDTH RIGHTWARDS ARROW -> > (unidecode: "-")
overrides[0xFFEC] = ord('v') # ↓ HALFWIDTH DOWNWARDS ARROW -> v (unidecode: "|")
# Currency symbols - each mapped to a representative letter
overrides[0x00A2] = ord('c') # ¢ CENT SIGN -> c
overrides[0x00A3] = ord('L') # £ POUND SIGN -> L
overrides[0x00A5] = ord('Y') # ¥ YEN SIGN -> Y
overrides[0x20AC] = ord('E') # € EURO SIGN -> E
# Symbols mapped to letters
overrides[0x00A7] = ord('S') # § SECTION SIGN -> S
overrides[0x00A9] = ord('C') # © COPYRIGHT SIGN -> C
overrides[0x00AE] = ord('R') # ® REGISTERED SIGN -> R
overrides[0x2122] = ord('T') # ™ TRADE MARK SIGN -> T
# Degree-related symbols
overrides[0x00B0] = ord('o') # ° DEGREE SIGN -> o
overrides[0x2103] = ord('C') # ℃ DEGREE CELSIUS -> C
overrides[0x2109] = ord('F') # ℉ DEGREE FAHRENHEIT -> F
# Angle quotation marks
overrides[0x00AB] = ord('<') # « LEFT-POINTING DOUBLE ANGLE QUOTATION MARK -> <
overrides[0x00BB] = ord('>') # » RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK -> >
# Operators with circular shape
overrides[0x2218] = ord('o') # ∘ RING OPERATOR -> o
overrides[0x2219] = ord('.') # ∙ BULLET OPERATOR -> .
# Negated mathematical symbols (preserving the negation semantics)
# Negated symbols mapped to exclamation mark (semantically "not")
for cp in (0x2204, 0x2209, 0x220C, 0x2224, 0x2226, 0x226E, 0x226F, 0x2280, 0x2281, 0x2284, 0x2285):
overrides[cp] = ord('!') # Negated math symbols -> ! (not)
# Negated symbols mapped to hash sign (semantically "not equal")
for cp in (0x2241, 0x2244, 0x2249, 0x2262, 0x2268, 0x2269, 0x226D, 0x228A, 0x228B):
overrides[cp] = ord('#') # Negated equality symbols -> # (not equal)
# Negated arrows - all mapped to exclamation mark
for cp in (0x219A, 0x219B, 0x21AE, 0x21CD, 0x21CE, 0x21CF):
overrides[cp] = ord('!') # Negated arrows -> ! (not)
# Dashes and hyphens
for cp in (0x2010, 0x2011, 0x2012, 0x2013, 0x2014, 0x2015, 0x2043, 0x2052):
overrides[cp] = ord('-') # Dashes and hyphens -> -
# Question mark punctuation
for cp in (0x203D, 0x2047, 0x2048):
overrides[cp] = ord('?') # Question marks -> ?
# Exclamation mark punctuation
for cp in (0x203C, 0x2049):
overrides[cp] = ord('!') # Exclamation marks -> !
# Asterisk-like symbols
for cp in (0x2042, 0x2051, 0x2055):
overrides[cp] = ord('*')
# Other specific punctuation with unique mappings
overrides[0x201E] = ord('"') # „ DOUBLE LOW-9 QUOTATION MARK
overrides[0x2023] = ord('>') # ‣ TRIANGULAR BULLET
overrides[0x2026] = ord('.') # … HORIZONTAL ELLIPSIS
overrides[0x2033] = ord('"') # ″ DOUBLE PRIME
overrides[0x204B] = ord('P') # ⁋ REVERSED PILCROW SIGN
overrides[0x204C] = ord('<') # ⁌ BLACK LEFTWARDS BULLET
overrides[0x204D] = ord('>') # ⁍ BLACK RIGHTWARDS BULLET
overrides[0x204F] = ord(';') # ⁏ REVERSED SEMICOLON
overrides[0x205B] = ord(':') # ⁛ FOUR DOT MARK
# Check marks
overrides[0x2713] = ord('v') # ✓ CHECK MARK
overrides[0x2714] = ord('V') # ✔ HEAVY CHECK MARK
# X marks - lowercase for regular, uppercase for heavy
for cp in (0x2715, 0x2717):
overrides[cp] = ord('x') # Regular X marks -> x
for cp in (0x2716, 0x2718):
overrides[cp] = ord('X') # Heavy X marks -> X
# Stars and asterisk-like symbols mapped to '*'
for cp in (0x2605, 0x2606, 0x262A, 0x269D, 0x2698):
overrides[cp] = ord('*') # All star and asterisk symbols -> *
for cp in range(0x2721, 0x2746+1):
overrides[cp] = ord('*') # All star and asterisk symbols -> *
for cp in range(0x2749, 0x274B+1):
overrides[cp] = ord('*') # Last set of asterisk symbols -> *
for cp in (0x229B, 0x22C6, 0x235F, 0x2363):
overrides[cp] = ord('*') # Star operators -> *
# Special exclusions with fallback value of 0
# These will be filtered out in organize_by_pages()
# Exclude U+2028 (LINE SEPARATOR)
overrides[0x2028] = 0 # LINE SEPARATOR (unidecode: '\n')
# Full-width to ASCII mapping (covering all printable ASCII 33-126)
# 0xFF01 (!) to 0xFF5E (~) -> ASCII 33 (!) to 126 (~)
# Those are excluded here to reduce the table size.
# It is more efficient to process them programmatically in
# ucs.c:ucs_get_fallback().
for cp in range(0xFF01, 0xFF5E + 1):
overrides[cp] = 0 # Double-width ASCII characters
return overrides
def organize_by_pages(fallback_map):
"""Organize the fallback mappings by their high byte (page)."""
# Group by high byte (page)
page_groups = defaultdict(list)
for code, fallback in fallback_map.items():
# Skip characters with fallback value of 0 (excluded characters)
if fallback == 0:
continue
page = code >> 8 # Get the high byte (page)
offset = code & 0xFF # Get the low byte (offset within page)
page_groups[page].append((offset, fallback))
# Sort each page's entries by offset
for page in page_groups:
page_groups[page].sort()
return page_groups
def compress_ranges(page_groups):
"""Compress consecutive entries with the same fallback character into ranges.
A range is only compressed if it contains 3 or more consecutive entries."""
compressed_pages = {}
for page, entries in page_groups.items():
compressed_entries = []
i = 0
while i < len(entries):
start_offset, fallback = entries[i]
# Look ahead to find consecutive entries with the same fallback
j = i + 1
while (j < len(entries) and
entries[j][0] == entries[j-1][0] + 1 and # consecutive offsets
entries[j][1] == fallback): # same fallback
j += 1
# Calculate the range end
end_offset = entries[j-1][0]
# If we found a range with 3 or more entries (worth compressing)
if j - i >= 3:
# Add a range entry
compressed_entries.append((start_offset, RANGE_MARKER))
compressed_entries.append((end_offset, fallback))
else:
# Add the individual entries as is
for k in range(i, j):
compressed_entries.append(entries[k])
i = j
compressed_pages[page] = compressed_entries
return compressed_pages
def cp_name(cp):
"""Get the Unicode character name for a code point."""
try:
return unicodedata.name(chr(cp))
except:
return f"U+{cp:04X}"
def generate_fallback_tables(out_file=DEFAULT_OUT_FILE):
"""Generate the fallback character tables."""
# Generate fallback map using unidecode
fallback_map = generate_fallback_map()
print(f"Generated {len(fallback_map)} total fallback mappings")
# Organize by pages
page_groups = organize_by_pages(fallback_map)
print(f"Organized into {len(page_groups)} pages")
# Compress ranges
compressed_pages = compress_ranges(page_groups)
total_compressed_entries = sum(len(entries) for entries in compressed_pages.values())
print(f"Total compressed entries: {total_compressed_entries}")
# Create output file
with open(out_file, 'w') as f:
f.write(f"""\
/* SPDX-License-Identifier: GPL-2.0 */
/*
* {out_file} - Unicode character fallback table
*
* Auto-generated by {this_file}
*
* Unicode Version: {unicodedata.unidata_version}
* Unidecode Version: {unidecode_version}
*
* This file contains optimized tables that map complex Unicode characters
* to simpler fallback characters for terminal display when corresponding
* glyphs are unavailable.
*/
static const struct ucs_page_desc ucs_fallback_pages[] = {{
""")
# Convert compressed_pages to a sorted list of (page, entries) tuples
sorted_pages = sorted(compressed_pages.items())
# Track the start index for each page
start_index = 0
# Write page descriptors
for page, entries in sorted_pages:
count = len(entries)
f.write(f"\t{{ 0x{page:02X}, {count}, {start_index} }},\n")
start_index += count
# Write entries array
f.write("""\
};
/* Page entries array (referenced by page descriptors) */
static const struct ucs_page_entry ucs_fallback_entries[] = {
""")
# Write all entries
for page, entries in sorted_pages:
page_hex = f"0x{page:02X}"
f.write(f"\t/* Entries for page {page_hex} */\n")
for i, (offset, fallback) in enumerate(entries):
# Convert to hex for better readability
offset_hex = f"0x{offset:02X}"
fallback_hex = f"0x{fallback:02X}"
# Handle comments
codepoint = (page << 8) | offset
if fallback == RANGE_MARKER:
comment = f"{cp_name(codepoint)} -> ..."
else:
comment = f"{cp_name(codepoint)} -> '{chr(fallback)}'"
f.write(f"\t{{ 0x{offset:02X}, 0x{fallback:02X} }}, /* {comment} */\n")
f.write(f"""\
}};
#define UCS_PAGE_ENTRY_RANGE_MARKER {RANGE_MARKER}
""")
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Generate Unicode fallback character tables")
parser.add_argument("-o", "--output", dest="output_file", default=DEFAULT_OUT_FILE,
help=f"Output file name (default: {DEFAULT_OUT_FILE})")
args = parser.parse_args()
generate_fallback_tables(out_file=args.output_file)
+257
View File
@@ -0,0 +1,257 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-2.0
#
# Leverage Python's unicodedata module to generate ucs_recompose_table.h
#
# The generated table maps base character + combining mark pairs to their
# precomposed equivalents.
#
# Usage:
# python3 gen_ucs_recompose_table.py # Generate with common recomposition pairs
# python3 gen_ucs_recompose_table.py --full # Generate with all recomposition pairs
import unicodedata
import sys
import argparse
import textwrap
# This script's file name
from pathlib import Path
this_file = Path(__file__).name
# Default output file name
DEFAULT_OUT_FILE = "ucs_recompose_table.h"
common_recompose_description = "most commonly used Latin, Greek, and Cyrillic recomposition pairs only"
COMMON_RECOMPOSITION_PAIRS = [
# Latin letters with accents - uppercase
(0x0041, 0x0300, 0x00C0), # A + COMBINING GRAVE ACCENT = LATIN CAPITAL LETTER A WITH GRAVE
(0x0041, 0x0301, 0x00C1), # A + COMBINING ACUTE ACCENT = LATIN CAPITAL LETTER A WITH ACUTE
(0x0041, 0x0302, 0x00C2), # A + COMBINING CIRCUMFLEX ACCENT = LATIN CAPITAL LETTER A WITH CIRCUMFLEX
(0x0041, 0x0303, 0x00C3), # A + COMBINING TILDE = LATIN CAPITAL LETTER A WITH TILDE
(0x0041, 0x0308, 0x00C4), # A + COMBINING DIAERESIS = LATIN CAPITAL LETTER A WITH DIAERESIS
(0x0041, 0x030A, 0x00C5), # A + COMBINING RING ABOVE = LATIN CAPITAL LETTER A WITH RING ABOVE
(0x0043, 0x0327, 0x00C7), # C + COMBINING CEDILLA = LATIN CAPITAL LETTER C WITH CEDILLA
(0x0045, 0x0300, 0x00C8), # E + COMBINING GRAVE ACCENT = LATIN CAPITAL LETTER E WITH GRAVE
(0x0045, 0x0301, 0x00C9), # E + COMBINING ACUTE ACCENT = LATIN CAPITAL LETTER E WITH ACUTE
(0x0045, 0x0302, 0x00CA), # E + COMBINING CIRCUMFLEX ACCENT = LATIN CAPITAL LETTER E WITH CIRCUMFLEX
(0x0045, 0x0308, 0x00CB), # E + COMBINING DIAERESIS = LATIN CAPITAL LETTER E WITH DIAERESIS
(0x0049, 0x0300, 0x00CC), # I + COMBINING GRAVE ACCENT = LATIN CAPITAL LETTER I WITH GRAVE
(0x0049, 0x0301, 0x00CD), # I + COMBINING ACUTE ACCENT = LATIN CAPITAL LETTER I WITH ACUTE
(0x0049, 0x0302, 0x00CE), # I + COMBINING CIRCUMFLEX ACCENT = LATIN CAPITAL LETTER I WITH CIRCUMFLEX
(0x0049, 0x0308, 0x00CF), # I + COMBINING DIAERESIS = LATIN CAPITAL LETTER I WITH DIAERESIS
(0x004E, 0x0303, 0x00D1), # N + COMBINING TILDE = LATIN CAPITAL LETTER N WITH TILDE
(0x004F, 0x0300, 0x00D2), # O + COMBINING GRAVE ACCENT = LATIN CAPITAL LETTER O WITH GRAVE
(0x004F, 0x0301, 0x00D3), # O + COMBINING ACUTE ACCENT = LATIN CAPITAL LETTER O WITH ACUTE
(0x004F, 0x0302, 0x00D4), # O + COMBINING CIRCUMFLEX ACCENT = LATIN CAPITAL LETTER O WITH CIRCUMFLEX
(0x004F, 0x0303, 0x00D5), # O + COMBINING TILDE = LATIN CAPITAL LETTER O WITH TILDE
(0x004F, 0x0308, 0x00D6), # O + COMBINING DIAERESIS = LATIN CAPITAL LETTER O WITH DIAERESIS
(0x0055, 0x0300, 0x00D9), # U + COMBINING GRAVE ACCENT = LATIN CAPITAL LETTER U WITH GRAVE
(0x0055, 0x0301, 0x00DA), # U + COMBINING ACUTE ACCENT = LATIN CAPITAL LETTER U WITH ACUTE
(0x0055, 0x0302, 0x00DB), # U + COMBINING CIRCUMFLEX ACCENT = LATIN CAPITAL LETTER U WITH CIRCUMFLEX
(0x0055, 0x0308, 0x00DC), # U + COMBINING DIAERESIS = LATIN CAPITAL LETTER U WITH DIAERESIS
(0x0059, 0x0301, 0x00DD), # Y + COMBINING ACUTE ACCENT = LATIN CAPITAL LETTER Y WITH ACUTE
# Latin letters with accents - lowercase
(0x0061, 0x0300, 0x00E0), # a + COMBINING GRAVE ACCENT = LATIN SMALL LETTER A WITH GRAVE
(0x0061, 0x0301, 0x00E1), # a + COMBINING ACUTE ACCENT = LATIN SMALL LETTER A WITH ACUTE
(0x0061, 0x0302, 0x00E2), # a + COMBINING CIRCUMFLEX ACCENT = LATIN SMALL LETTER A WITH CIRCUMFLEX
(0x0061, 0x0303, 0x00E3), # a + COMBINING TILDE = LATIN SMALL LETTER A WITH TILDE
(0x0061, 0x0308, 0x00E4), # a + COMBINING DIAERESIS = LATIN SMALL LETTER A WITH DIAERESIS
(0x0061, 0x030A, 0x00E5), # a + COMBINING RING ABOVE = LATIN SMALL LETTER A WITH RING ABOVE
(0x0063, 0x0327, 0x00E7), # c + COMBINING CEDILLA = LATIN SMALL LETTER C WITH CEDILLA
(0x0065, 0x0300, 0x00E8), # e + COMBINING GRAVE ACCENT = LATIN SMALL LETTER E WITH GRAVE
(0x0065, 0x0301, 0x00E9), # e + COMBINING ACUTE ACCENT = LATIN SMALL LETTER E WITH ACUTE
(0x0065, 0x0302, 0x00EA), # e + COMBINING CIRCUMFLEX ACCENT = LATIN SMALL LETTER E WITH CIRCUMFLEX
(0x0065, 0x0308, 0x00EB), # e + COMBINING DIAERESIS = LATIN SMALL LETTER E WITH DIAERESIS
(0x0069, 0x0300, 0x00EC), # i + COMBINING GRAVE ACCENT = LATIN SMALL LETTER I WITH GRAVE
(0x0069, 0x0301, 0x00ED), # i + COMBINING ACUTE ACCENT = LATIN SMALL LETTER I WITH ACUTE
(0x0069, 0x0302, 0x00EE), # i + COMBINING CIRCUMFLEX ACCENT = LATIN SMALL LETTER I WITH CIRCUMFLEX
(0x0069, 0x0308, 0x00EF), # i + COMBINING DIAERESIS = LATIN SMALL LETTER I WITH DIAERESIS
(0x006E, 0x0303, 0x00F1), # n + COMBINING TILDE = LATIN SMALL LETTER N WITH TILDE
(0x006F, 0x0300, 0x00F2), # o + COMBINING GRAVE ACCENT = LATIN SMALL LETTER O WITH GRAVE
(0x006F, 0x0301, 0x00F3), # o + COMBINING ACUTE ACCENT = LATIN SMALL LETTER O WITH ACUTE
(0x006F, 0x0302, 0x00F4), # o + COMBINING CIRCUMFLEX ACCENT = LATIN SMALL LETTER O WITH CIRCUMFLEX
(0x006F, 0x0303, 0x00F5), # o + COMBINING TILDE = LATIN SMALL LETTER O WITH TILDE
(0x006F, 0x0308, 0x00F6), # o + COMBINING DIAERESIS = LATIN SMALL LETTER O WITH DIAERESIS
(0x0075, 0x0300, 0x00F9), # u + COMBINING GRAVE ACCENT = LATIN SMALL LETTER U WITH GRAVE
(0x0075, 0x0301, 0x00FA), # u + COMBINING ACUTE ACCENT = LATIN SMALL LETTER U WITH ACUTE
(0x0075, 0x0302, 0x00FB), # u + COMBINING CIRCUMFLEX ACCENT = LATIN SMALL LETTER U WITH CIRCUMFLEX
(0x0075, 0x0308, 0x00FC), # u + COMBINING DIAERESIS = LATIN SMALL LETTER U WITH DIAERESIS
(0x0079, 0x0301, 0x00FD), # y + COMBINING ACUTE ACCENT = LATIN SMALL LETTER Y WITH ACUTE
(0x0079, 0x0308, 0x00FF), # y + COMBINING DIAERESIS = LATIN SMALL LETTER Y WITH DIAERESIS
# Common Greek characters
(0x0391, 0x0301, 0x0386), # Α + COMBINING ACUTE ACCENT = GREEK CAPITAL LETTER ALPHA WITH TONOS
(0x0395, 0x0301, 0x0388), # Ε + COMBINING ACUTE ACCENT = GREEK CAPITAL LETTER EPSILON WITH TONOS
(0x0397, 0x0301, 0x0389), # Η + COMBINING ACUTE ACCENT = GREEK CAPITAL LETTER ETA WITH TONOS
(0x0399, 0x0301, 0x038A), # Ι + COMBINING ACUTE ACCENT = GREEK CAPITAL LETTER IOTA WITH TONOS
(0x039F, 0x0301, 0x038C), # Ο + COMBINING ACUTE ACCENT = GREEK CAPITAL LETTER OMICRON WITH TONOS
(0x03A5, 0x0301, 0x038E), # Υ + COMBINING ACUTE ACCENT = GREEK CAPITAL LETTER UPSILON WITH TONOS
(0x03A9, 0x0301, 0x038F), # Ω + COMBINING ACUTE ACCENT = GREEK CAPITAL LETTER OMEGA WITH TONOS
(0x03B1, 0x0301, 0x03AC), # α + COMBINING ACUTE ACCENT = GREEK SMALL LETTER ALPHA WITH TONOS
(0x03B5, 0x0301, 0x03AD), # ε + COMBINING ACUTE ACCENT = GREEK SMALL LETTER EPSILON WITH TONOS
(0x03B7, 0x0301, 0x03AE), # η + COMBINING ACUTE ACCENT = GREEK SMALL LETTER ETA WITH TONOS
(0x03B9, 0x0301, 0x03AF), # ι + COMBINING ACUTE ACCENT = GREEK SMALL LETTER IOTA WITH TONOS
(0x03BF, 0x0301, 0x03CC), # ο + COMBINING ACUTE ACCENT = GREEK SMALL LETTER OMICRON WITH TONOS
(0x03C5, 0x0301, 0x03CD), # υ + COMBINING ACUTE ACCENT = GREEK SMALL LETTER UPSILON WITH TONOS
(0x03C9, 0x0301, 0x03CE), # ω + COMBINING ACUTE ACCENT = GREEK SMALL LETTER OMEGA WITH TONOS
# Common Cyrillic characters
(0x0418, 0x0306, 0x0419), # И + COMBINING BREVE = CYRILLIC CAPITAL LETTER SHORT I
(0x0438, 0x0306, 0x0439), # и + COMBINING BREVE = CYRILLIC SMALL LETTER SHORT I
(0x0423, 0x0306, 0x040E), # У + COMBINING BREVE = CYRILLIC CAPITAL LETTER SHORT U
(0x0443, 0x0306, 0x045E), # у + COMBINING BREVE = CYRILLIC SMALL LETTER SHORT U
]
full_recompose_description = "all possible recomposition pairs from the Unicode BMP"
def collect_all_recomposition_pairs():
"""Collect all possible recomposition pairs from the Unicode data."""
# Map to store recomposition pairs: (base, combining) -> recomposed
recompose_map = {}
# Process all assigned Unicode code points in BMP (Basic Multilingual Plane)
# We limit to BMP (0x0000-0xFFFF) to keep our table smaller with uint16_t
for cp in range(0, 0x10000):
try:
char = chr(cp)
# Skip unassigned or control characters
if not unicodedata.name(char, ''):
continue
# Find decomposition
decomp = unicodedata.decomposition(char)
if not decomp or '<' in decomp: # Skip compatibility decompositions
continue
# Parse the decomposition
parts = decomp.split()
if len(parts) == 2: # Simple base + combining mark
base = int(parts[0], 16)
combining = int(parts[1], 16)
# Only store if both are in BMP
if base < 0x10000 and combining < 0x10000:
recompose_map[(base, combining)] = cp
except (ValueError, TypeError):
continue
# Convert to a list of tuples and sort for binary search
recompose_list = [(base, combining, recomposed)
for (base, combining), recomposed in recompose_map.items()]
recompose_list.sort()
return recompose_list
def validate_common_pairs(full_list):
"""Validate that all common pairs are in the full list.
Raises:
ValueError: If any common pair is missing or has a different recomposition
value than what's in the full table.
"""
full_pairs = {(base, combining): recomposed for base, combining, recomposed in full_list}
for base, combining, recomposed in COMMON_RECOMPOSITION_PAIRS:
full_recomposed = full_pairs.get((base, combining))
if full_recomposed is None:
error_msg = f"Error: Common pair (0x{base:04X}, 0x{combining:04X}) not found in full data"
print(error_msg)
raise ValueError(error_msg)
elif full_recomposed != recomposed:
error_msg = (f"Error: Common pair (0x{base:04X}, 0x{combining:04X}) has different recomposition: "
f"0x{recomposed:04X} vs 0x{full_recomposed:04X}")
print(error_msg)
raise ValueError(error_msg)
def generate_recomposition_table(use_full_list=False, out_file=DEFAULT_OUT_FILE):
"""Generate the recomposition C table."""
# Collect all recomposition pairs for validation
full_recompose_list = collect_all_recomposition_pairs()
# Decide which list to use
if use_full_list:
print("Using full recomposition list...")
recompose_list = full_recompose_list
table_description = full_recompose_description
alt_list = COMMON_RECOMPOSITION_PAIRS
alt_description = common_recompose_description
else:
print("Using common recomposition list...")
# Validate that all common pairs are in the full list
validate_common_pairs(full_recompose_list)
recompose_list = sorted(COMMON_RECOMPOSITION_PAIRS)
table_description = common_recompose_description
alt_list = full_recompose_list
alt_description = full_recompose_description
generation_mode = " --full" if use_full_list else ""
alternative_mode = " --full" if not use_full_list else ""
table_description_detail = f"{table_description} ({len(recompose_list)} entries)"
alt_description_detail = f"{alt_description} ({len(alt_list)} entries)"
# Calculate min/max values for boundary checks
min_base = min(base for base, _, _ in recompose_list)
max_base = max(base for base, _, _ in recompose_list)
min_combining = min(combining for _, combining, _ in recompose_list)
max_combining = max(combining for _, combining, _ in recompose_list)
# Generate implementation file
with open(out_file, 'w') as f:
f.write(f"""\
/* SPDX-License-Identifier: GPL-2.0 */
/*
* {out_file} - Unicode character recomposition
*
* Auto-generated by {this_file}{generation_mode}
*
* Unicode Version: {unicodedata.unidata_version}
*
{textwrap.fill(
f"This file contains a table with {table_description_detail}. " +
f"To generate a table with {alt_description_detail} instead, run:",
width=75, initial_indent=" * ", subsequent_indent=" * ")}
*
* python3 {this_file}{alternative_mode}
*/
/*
* Table of {table_description}
* Sorted by base character and then combining mark for binary search
*/
static const struct ucs_recomposition ucs_recomposition_table[] = {{
""")
for base, combining, recomposed in recompose_list:
try:
base_name = unicodedata.name(chr(base))
combining_name = unicodedata.name(chr(combining))
recomposed_name = unicodedata.name(chr(recomposed))
comment = f"/* {base_name} + {combining_name} = {recomposed_name} */"
except ValueError:
comment = f"/* U+{base:04X} + U+{combining:04X} = U+{recomposed:04X} */"
f.write(f"\t{{ 0x{base:04X}, 0x{combining:04X}, 0x{recomposed:04X} }}, {comment}\n")
f.write(f"""\
}};
/*
* Boundary values for quick rejection
* These are calculated by analyzing the table during generation
*/
#define UCS_RECOMPOSE_MIN_BASE 0x{min_base:04X}
#define UCS_RECOMPOSE_MAX_BASE 0x{max_base:04X}
#define UCS_RECOMPOSE_MIN_MARK 0x{min_combining:04X}
#define UCS_RECOMPOSE_MAX_MARK 0x{max_combining:04X}
""")
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Generate Unicode recomposition table")
parser.add_argument("--full", action="store_true",
help="Generate a full recomposition table (default: common pairs only)")
parser.add_argument("-o", "--output", dest="output_file", default=DEFAULT_OUT_FILE,
help=f"Output file name (default: {DEFAULT_OUT_FILE})")
args = parser.parse_args()
generate_recomposition_table(use_full_list=args.full, out_file=args.output_file)
+354
View File
@@ -0,0 +1,354 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-2.0
#
# Leverage Python's unicodedata module to generate ucs_width_table.h
import unicodedata
import sys
import argparse
# This script's file name
from pathlib import Path
this_file = Path(__file__).name
# Default output file name
DEFAULT_OUT_FILE = "ucs_width_table.h"
# --- Global Constants for Width Assignments ---
# Known zero-width characters
KNOWN_ZERO_WIDTH = (
0x200B, # ZERO WIDTH SPACE
0x200C, # ZERO WIDTH NON-JOINER
0x200D, # ZERO WIDTH JOINER
0x2060, # WORD JOINER
0xFEFF # ZERO WIDTH NO-BREAK SPACE (BOM)
)
# Zero-width emoji modifiers and components
# NOTE: Some of these characters would normally be single-width according to
# East Asian Width properties, but we deliberately override them to be
# zero-width because they function as modifiers in emoji sequences.
EMOJI_ZERO_WIDTH = [
# Skin tone modifiers
(0x1F3FB, 0x1F3FF), # Emoji modifiers (skin tones)
# Variation selectors (note: VS16 is treated specially in vt.c)
(0xFE00, 0xFE0F), # Variation Selectors 1-16
# Gender and hair style modifiers
# These would be single-width by Unicode properties, but are zero-width
# when part of emoji
(0x2640, 0x2640), # Female sign
(0x2642, 0x2642), # Male sign
(0x26A7, 0x26A7), # Transgender symbol
(0x1F9B0, 0x1F9B3), # Hair components (red, curly, white, bald)
# Tag characters
(0xE0020, 0xE007E), # Tags
]
# Regional indicators (flag components)
REGIONAL_INDICATORS = (0x1F1E6, 0x1F1FF) # Regional indicator symbols A-Z
# Double-width emoji ranges
#
# Many emoji characters are classified as single-width according to Unicode
# Standard Annex #11 East Asian Width property (N or Neutral), but we
# deliberately override them to be double-width. References:
# 1. Unicode Technical Standard #51: Unicode Emoji
# (https://www.unicode.org/reports/tr51/)
# 2. Principle of "emoji presentation" in WHATWG CSS Text specification
# (https://drafts.csswg.org/css-text-3/#character-properties)
# 3. Terminal emulator implementations (iTerm2, Windows Terminal, etc.) which
# universally render emoji as double-width characters regardless of their
# Unicode EAW property
# 4. W3C Work Item: Requirements for Japanese Text Layout - Section 3.8.1
# Emoji width (https://www.w3.org/TR/jlreq/)
EMOJI_RANGES = [
(0x1F000, 0x1F02F), # Mahjong Tiles (EAW: N, but displayed as double-width)
(0x1F0A0, 0x1F0FF), # Playing Cards (EAW: N, but displayed as double-width)
(0x1F300, 0x1F5FF), # Miscellaneous Symbols and Pictographs
(0x1F600, 0x1F64F), # Emoticons
(0x1F680, 0x1F6FF), # Transport and Map Symbols
(0x1F700, 0x1F77F), # Alchemical Symbols
(0x1F780, 0x1F7FF), # Geometric Shapes Extended
(0x1F800, 0x1F8FF), # Supplemental Arrows-C
(0x1F900, 0x1F9FF), # Supplemental Symbols and Pictographs
(0x1FA00, 0x1FA6F), # Chess Symbols
(0x1FA70, 0x1FAFF), # Symbols and Pictographs Extended-A
]
def create_width_tables():
"""
Creates Unicode character width tables and returns the data structures.
Returns:
tuple: (zero_width_ranges, double_width_ranges)
"""
# Width data mapping
width_map = {} # Maps code points to width (0, 1, 2)
# Mark emoji modifiers as zero-width
for start, end in EMOJI_ZERO_WIDTH:
for cp in range(start, end + 1):
width_map[cp] = 0
# Mark all regional indicators as single-width as they are usually paired
# providing a combined width of 2 when displayed together.
start, end = REGIONAL_INDICATORS
for cp in range(start, end + 1):
width_map[cp] = 1
# Process all assigned Unicode code points (Basic Multilingual Plane +
# Supplementary Planes) Range 0x0 to 0x10FFFF (the full Unicode range)
for block_start in range(0, 0x110000, 0x1000):
block_end = block_start + 0x1000
for cp in range(block_start, block_end):
try:
char = chr(cp)
# Skip if already processed
if cp in width_map:
continue
# Check for combining marks and a format characters
category = unicodedata.category(char)
# Combining marks
if category.startswith('M'):
width_map[cp] = 0
continue
# Format characters
# Since we have no support for bidirectional text, all format
# characters (category Cf) can be treated with width 0 (zero)
# for simplicity, as they don't need to occupy visual space
# in a non-bidirectional text environment.
if category == 'Cf':
width_map[cp] = 0
continue
# Known zero-width characters
if cp in KNOWN_ZERO_WIDTH:
width_map[cp] = 0
continue
# Use East Asian Width property
eaw = unicodedata.east_asian_width(char)
if eaw in ('F', 'W'): # Fullwidth or Wide
width_map[cp] = 2
elif eaw in ('Na', 'H', 'N', 'A'): # Narrow, Halfwidth, Neutral, Ambiguous
width_map[cp] = 1
else:
# Default to single-width for unknown
width_map[cp] = 1
except (ValueError, OverflowError):
# Skip invalid code points
continue
# Process Emoji - generally double-width
for start, end in EMOJI_RANGES:
for cp in range(start, end + 1):
if cp not in width_map or width_map[cp] != 0: # Don't override zero-width
try:
char = chr(cp)
width_map[cp] = 2
except (ValueError, OverflowError):
continue
# Optimize to create range tables
def ranges_optimize(width_data, target_width):
points = sorted([cp for cp, width in width_data.items() if width == target_width])
if not points:
return []
# Group consecutive code points into ranges
ranges = []
start = points[0]
prev = start
for cp in points[1:]:
if cp > prev + 1:
ranges.append((start, prev))
start = cp
prev = cp
# Add the last range
ranges.append((start, prev))
return ranges
# Extract ranges for each width
zero_width_ranges = ranges_optimize(width_map, 0)
double_width_ranges = ranges_optimize(width_map, 2)
return zero_width_ranges, double_width_ranges
def write_tables(zero_width_ranges, double_width_ranges, out_file=DEFAULT_OUT_FILE):
"""
Write the generated tables to C header file.
The output uses a single sorted-by-`first` table per region (BMP and
non-BMP), with zero-width and double-width ranges merged together. The
non-BMP table also hosts the BMP double-width bitmap in spare bits of
`last`. See the encoding comment at the top of ucs.c for the layout.
Args:
zero_width_ranges: List of (start, end) ranges for zero-width characters
double_width_ranges: List of (start, end) ranges for double-width characters
out_file: Output file name (default: DEFAULT_OUT_FILE)
"""
# Bits per BMP-bitmap chunk hosted in one non-BMP entry's `last` field.
# 8 bits makes `idx / BITS_PER_CHUNK` / `idx % BITS_PER_CHUNK` compile to
# a cheap shift+mask in the lookup. The chunk size is also emitted as
# UCS_NONBMP_BMP_BITS in the generated header so ucs.c stays in sync.
BITS_PER_CHUNK = 8
# Function to split ranges into BMP (16-bit) and non-BMP (above 16-bit)
def split_ranges_by_size(ranges):
bmp_ranges = []
non_bmp_ranges = []
for start, end in ranges:
if end <= 0xFFFF:
bmp_ranges.append((start, end))
elif start > 0xFFFF:
non_bmp_ranges.append((start, end))
else:
# Split the range at 0xFFFF
bmp_ranges.append((start, 0xFFFF))
non_bmp_ranges.append((0x10000, end))
return bmp_ranges, non_bmp_ranges
# Split ranges into BMP and non-BMP
zero_width_bmp, zero_width_non_bmp = split_ranges_by_size(zero_width_ranges)
double_width_bmp, double_width_non_bmp = split_ranges_by_size(double_width_ranges)
# Merge zero- and double-width ranges per region, tagging each with its
# width, then sort by `first` so binary search works on the union.
bmp_entries = sorted(
[(s, e, 0) for s, e in zero_width_bmp] +
[(s, e, 2) for s, e in double_width_bmp],
key=lambda t: t[0])
nonbmp_entries = sorted(
[(s, e, 0) for s, e in zero_width_non_bmp] +
[(s, e, 2) for s, e in double_width_non_bmp],
key=lambda t: t[0])
# Build the BMP double-width bitmap: one bit per BMP entry (in sort
# order), set iff that entry is double-width. Pack into BITS_PER_CHUNK-
# wide chunks, with bit j of the chunk corresponding to entry
# (chunk_index * BITS_PER_CHUNK + j).
bmp_w2_bits = [1 if w == 2 else 0 for _, _, w in bmp_entries]
n_chunks = (len(bmp_w2_bits) + BITS_PER_CHUNK - 1) // BITS_PER_CHUNK
if n_chunks > len(nonbmp_entries):
raise RuntimeError(
f"BMP bitmap needs {n_chunks} host entries, "
f"but only {len(nonbmp_entries)} non-BMP entries are available")
chunks = [] # list of (base_index, end_index, packed_value)
for c in range(n_chunks):
base = c * BITS_PER_CHUNK
end_idx = min(base + BITS_PER_CHUNK - 1, len(bmp_w2_bits) - 1)
value = 0
for j in range(BITS_PER_CHUNK):
k = base + j
if k < len(bmp_w2_bits) and bmp_w2_bits[k]:
value |= 1 << j
chunks.append((base, end_idx, value))
# Function to generate code point description comments
def get_code_point_comment(start, end):
try:
start_char_desc = unicodedata.name(chr(start))
if start == end:
return f"/* {start_char_desc} */"
else:
end_char_desc = unicodedata.name(chr(end))
return f"/* {start_char_desc} - {end_char_desc} */"
except:
if start == end:
return f"/* U+{start:04X} */"
else:
return f"/* U+{start:04X} - U+{end:04X} */"
# Generate C tables
with open(out_file, 'w') as f:
f.write(f"""\
/* SPDX-License-Identifier: GPL-2.0 */
/*
* {out_file} - Unicode character width
*
* Auto-generated by {this_file}
*
* Unicode Version: {unicodedata.unidata_version}
*
* Zero-width and double-width ranges are merged into one sorted-by-`first`
* table per region. The non-BMP table additionally hosts the BMP
* double-width bitmap in the low {BITS_PER_CHUNK} bits of `last` of its
* first {n_chunks} entries (covering {len(bmp_w2_bits)} BMP entries).
* See ucs.c for the encoding details and the lookup code.
*/
/* Bits per BMP-bitmap chunk hosted in one non-BMP entry's `last` field. */
#define UCS_NONBMP_BMP_BITS {BITS_PER_CHUNK}
/* Combined zero- and double-width ranges
* (BMP - Basic Multilingual Plane, U+0000 to U+FFFF). */
static const struct ucs_width16 ucs_bmp_ranges[] = {{
""")
for s, e, w in bmp_entries:
macro = "BMP_0WIDTH" if w == 0 else "BMP_2WIDTH"
comment = get_code_point_comment(s, e)
f.write(f"\t{{ {macro}(0x{s:04X}, 0x{e:04X}) }}, {comment}\n")
f.write(f"""\
}};
/* Combined zero- and double-width ranges (non-BMP, U+10000 and above).
* The first {n_chunks} entries host the BMP double-width bitmap in the low
* {BITS_PER_CHUNK} bits of `last`. */
static const struct ucs_width32 ucs_nonbmp_ranges[] = {{
""")
for i, (s, e, w) in enumerate(nonbmp_entries):
macro = "RANGE_0WIDTH" if w == 0 else "RANGE_2WIDTH"
comment = get_code_point_comment(s, e)
if i < len(chunks):
base, end_idx, value = chunks[i]
f.write(
f"\t{{ {macro}(0x{s:05X}, 0x{e:05X}) {comment}\n"
f"\t | BMP_2W_BITS(0b{value:0{BITS_PER_CHUNK}b}) }},"
f" /* BMP entries [{base:>3}..{end_idx:>3}] */\n")
else:
f.write(f"\t{{ {macro}(0x{s:05X}, 0x{e:05X}) }}, {comment}\n")
f.write("};\n")
if __name__ == "__main__":
# Parse command line arguments
parser = argparse.ArgumentParser(description="Generate Unicode width tables")
parser.add_argument("-o", "--output", dest="output_file", default=DEFAULT_OUT_FILE,
help=f"Output file name (default: {DEFAULT_OUT_FILE})")
args = parser.parse_args()
# Write tables to header file
zero_width_ranges, double_width_ranges = create_width_tables()
write_tables(zero_width_ranges, double_width_ranges, out_file=args.output_file)
# Print summary
zero_width_count = sum(end - start + 1 for start, end in zero_width_ranges)
double_width_count = sum(end - start + 1 for start, end in double_width_ranges)
n_zero = len(zero_width_ranges)
n_double = len(double_width_ranges)
print(f"Generated {args.output_file} with:")
print(f"- {n_zero} zero-width ranges covering ~{zero_width_count} code points")
print(f"- {n_double} double-width ranges covering ~{double_width_count} code points")
print(f"- {n_zero + n_double} merged ranges total")
print(f"- Unicode Version: {unicodedata.unidata_version}")
File diff suppressed because it is too large Load Diff
+459
View File
@@ -0,0 +1,459 @@
// SPDX-License-Identifier: GPL-2.0
/*
* This module exports the functions:
*
* 'int set_selection_user(struct tiocl_selection __user *,
* struct tty_struct *)'
* 'int set_selection_kernel(struct tiocl_selection *, struct tty_struct *)'
* 'void clear_selection(void)'
* 'int paste_selection(struct tty_struct *)'
* 'int sel_loadlut(u32 __user *)'
*
* Now that /dev/vcs exists, most of this can disappear again.
*/
#include <linux/module.h>
#include <linux/tty.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/mutex.h>
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/uaccess.h>
#include <linux/kbd_kern.h>
#include <linux/vt_kern.h>
#include <linux/consolemap.h>
#include <linux/selection.h>
#include <linux/tiocl.h>
#include <linux/console.h>
#include <linux/tty_flip.h>
#include <linux/sched/signal.h>
/* Don't take this from <ctype.h>: 011-015 on the screen aren't spaces */
#define is_space_on_vt(c) ((c) == ' ')
/* FIXME: all this needs locking */
static struct vc_selection {
struct mutex lock;
struct vc_data *cons; /* must not be deallocated */
char *buffer;
unsigned int buf_len;
volatile int start; /* cleared by clear_selection */
int end;
} vc_sel = {
.lock = __MUTEX_INITIALIZER(vc_sel.lock),
.start = -1,
};
/* clear_selection, highlight and highlight_pointer can be called
from interrupt (via scrollback/front) */
/* set reverse video on characters s-e of console with selection. */
static inline void highlight(const int s, const int e)
{
invert_screen(vc_sel.cons, s, e-s+2, true);
}
/* use complementary color to show the pointer */
static inline void highlight_pointer(const int where)
{
complement_pos(vc_sel.cons, where);
}
static u32
sel_pos(int n, bool unicode)
{
if (unicode)
return screen_glyph_unicode(vc_sel.cons, n / 2);
return inverse_translate(vc_sel.cons, screen_glyph(vc_sel.cons, n),
false);
}
/**
* clear_selection - remove current selection
*
* Remove the current selection highlight, if any from the console holding the
* selection.
*
* Locking: The caller must hold the console lock.
*/
void clear_selection(void)
{
highlight_pointer(-1); /* hide the pointer */
if (vc_sel.start != -1) {
highlight(vc_sel.start, vc_sel.end);
vc_sel.start = -1;
}
}
EXPORT_SYMBOL_GPL(clear_selection);
bool vc_is_sel(const struct vc_data *vc)
{
return vc == vc_sel.cons;
}
/*
* User settable table: what characters are to be considered alphabetic?
* 128 bits. Locked by the console lock.
*/
static u32 inwordLut[]={
0x00000000, /* control chars */
0x03FFE000, /* digits and "-./" */
0x87FFFFFE, /* uppercase and '_' */
0x07FFFFFE, /* lowercase */
};
static inline int inword(const u32 c)
{
return c > 0x7f || (( inwordLut[c>>5] >> (c & 0x1F) ) & 1);
}
/**
* sel_loadlut() - load the LUT table
* @lut: user table
*
* Load the LUT table from user space. Make a temporary copy so a partial
* update doesn't make a mess.
*
* Locking: The console lock is acquired.
*/
int sel_loadlut(u32 __user *lut)
{
u32 tmplut[ARRAY_SIZE(inwordLut)];
if (copy_from_user(tmplut, lut, sizeof(inwordLut)))
return -EFAULT;
guard(console_lock)();
memcpy(inwordLut, tmplut, sizeof(inwordLut));
return 0;
}
/* does screen address p correspond to character at LH/RH edge of screen? */
static inline int atedge(const int p, int size_row)
{
return (!(p % size_row) || !((p + 2) % size_row));
}
/* stores the char in UTF8 and returns the number of bytes used (1-4) */
static int store_utf8(u32 c, char *p)
{
if (c < 0x80) {
/* 0******* */
p[0] = c;
return 1;
} else if (c < 0x800) {
/* 110***** 10****** */
p[0] = 0xc0 | (c >> 6);
p[1] = 0x80 | (c & 0x3f);
return 2;
} else if (c < 0x10000) {
/* 1110**** 10****** 10****** */
p[0] = 0xe0 | (c >> 12);
p[1] = 0x80 | ((c >> 6) & 0x3f);
p[2] = 0x80 | (c & 0x3f);
return 3;
} else if (c < 0x110000) {
/* 11110*** 10****** 10****** 10****** */
p[0] = 0xf0 | (c >> 18);
p[1] = 0x80 | ((c >> 12) & 0x3f);
p[2] = 0x80 | ((c >> 6) & 0x3f);
p[3] = 0x80 | (c & 0x3f);
return 4;
} else {
/* outside Unicode, replace with U+FFFD */
p[0] = 0xef;
p[1] = 0xbf;
p[2] = 0xbd;
return 3;
}
}
/**
* set_selection_user - set the current selection.
* @sel: user selection info
* @tty: the console tty
*
* Invoked by the ioctl handle for the vt layer.
*
* Locking: The entire selection process is managed under the console_lock.
* It's a lot under the lock but its hardly a performance path.
*/
int set_selection_user(const struct tiocl_selection __user *sel,
struct tty_struct *tty)
{
struct tiocl_selection v;
if (copy_from_user(&v, sel, sizeof(*sel)))
return -EFAULT;
/*
* TIOCL_SELCLEAR and TIOCL_SELPOINTER are OK to use without
* CAP_SYS_ADMIN as they do not modify the selection.
*/
switch (v.sel_mode) {
case TIOCL_SELCLEAR:
case TIOCL_SELPOINTER:
break;
default:
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
}
return set_selection_kernel(&v, tty);
}
static int vc_selection_store_chars(struct vc_data *vc, bool unicode)
{
char *bp, *obp;
unsigned int i;
/* Allocate a new buffer before freeing the old one ... */
/* chars can take up to 4 bytes with unicode */
bp = kmalloc_array((vc_sel.end - vc_sel.start) / 2 + 1, unicode ? 4 : 1,
GFP_KERNEL | __GFP_NOWARN);
if (!bp) {
printk(KERN_WARNING "selection: kmalloc() failed\n");
clear_selection();
return -ENOMEM;
}
kfree(vc_sel.buffer);
vc_sel.buffer = bp;
obp = bp;
for (i = vc_sel.start; i <= vc_sel.end; i += 2) {
u32 c = sel_pos(i, unicode);
if (unicode)
bp += store_utf8(c, bp);
else
*bp++ = c;
if (!is_space_on_vt(c))
obp = bp;
if (!((i + 2) % vc->vc_size_row)) {
/* strip trailing blanks from line and add newline,
unless non-space at end of line. */
if (obp != bp) {
bp = obp;
*bp++ = '\r';
}
obp = bp;
}
}
vc_sel.buf_len = bp - vc_sel.buffer;
return 0;
}
static int vc_do_selection(struct vc_data *vc, unsigned short mode, int ps,
int pe)
{
int new_sel_start, new_sel_end, spc;
bool unicode = vt_do_kdgkbmode(fg_console) == K_UNICODE;
switch (mode) {
case TIOCL_SELCHAR: /* character-by-character selection */
new_sel_start = ps;
new_sel_end = pe;
break;
case TIOCL_SELWORD: /* word-by-word selection */
spc = is_space_on_vt(sel_pos(ps, unicode));
for (new_sel_start = ps; ; ps -= 2) {
if ((spc && !is_space_on_vt(sel_pos(ps, unicode))) ||
(!spc && !inword(sel_pos(ps, unicode))))
break;
new_sel_start = ps;
if (!(ps % vc->vc_size_row))
break;
}
spc = is_space_on_vt(sel_pos(pe, unicode));
for (new_sel_end = pe; ; pe += 2) {
if ((spc && !is_space_on_vt(sel_pos(pe, unicode))) ||
(!spc && !inword(sel_pos(pe, unicode))))
break;
new_sel_end = pe;
if (!((pe + 2) % vc->vc_size_row))
break;
}
break;
case TIOCL_SELLINE: /* line-by-line selection */
new_sel_start = rounddown(ps, vc->vc_size_row);
new_sel_end = rounddown(pe, vc->vc_size_row) +
vc->vc_size_row - 2;
break;
case TIOCL_SELPOINTER:
highlight_pointer(pe);
return 0;
default:
return -EINVAL;
}
/* remove the pointer */
highlight_pointer(-1);
/* select to end of line if on trailing space */
if (new_sel_end > new_sel_start &&
!atedge(new_sel_end, vc->vc_size_row) &&
is_space_on_vt(sel_pos(new_sel_end, unicode))) {
for (pe = new_sel_end + 2; ; pe += 2)
if (!is_space_on_vt(sel_pos(pe, unicode)) ||
atedge(pe, vc->vc_size_row))
break;
if (is_space_on_vt(sel_pos(pe, unicode)))
new_sel_end = pe;
}
if (vc_sel.start == -1) /* no current selection */
highlight(new_sel_start, new_sel_end);
else if (new_sel_start == vc_sel.start)
{
if (new_sel_end == vc_sel.end) /* no action required */
return 0;
else if (new_sel_end > vc_sel.end) /* extend to right */
highlight(vc_sel.end + 2, new_sel_end);
else /* contract from right */
highlight(new_sel_end + 2, vc_sel.end);
}
else if (new_sel_end == vc_sel.end)
{
if (new_sel_start < vc_sel.start) /* extend to left */
highlight(new_sel_start, vc_sel.start - 2);
else /* contract from left */
highlight(vc_sel.start, new_sel_start - 2);
}
else /* some other case; start selection from scratch */
{
clear_selection();
highlight(new_sel_start, new_sel_end);
}
vc_sel.start = new_sel_start;
vc_sel.end = new_sel_end;
return vc_selection_store_chars(vc, unicode);
}
static int vc_selection(struct vc_data *vc, struct tiocl_selection *v,
struct tty_struct *tty)
{
int ps, pe;
poke_blanked_console();
if (v->sel_mode == TIOCL_SELCLEAR) {
/* useful for screendump without selection highlights */
clear_selection();
return 0;
}
/* Historically 0 => max value */
v->xs = umin(v->xs - 1, vc->vc_cols - 1);
v->ys = umin(v->ys - 1, vc->vc_rows - 1);
v->xe = umin(v->xe - 1, vc->vc_cols - 1);
v->ye = umin(v->ye - 1, vc->vc_rows - 1);
if (mouse_reporting() && (v->sel_mode & TIOCL_SELMOUSEREPORT)) {
mouse_report(tty, v->sel_mode & TIOCL_SELBUTTONMASK, v->xs,
v->ys);
return 0;
}
ps = v->ys * vc->vc_size_row + (v->xs << 1);
pe = v->ye * vc->vc_size_row + (v->xe << 1);
if (ps > pe) /* make vc_sel.start <= vc_sel.end */
swap(ps, pe);
if (vc_sel.cons != vc) {
clear_selection();
vc_sel.cons = vc;
}
return vc_do_selection(vc, v->sel_mode, ps, pe);
}
int set_selection_kernel(struct tiocl_selection *v, struct tty_struct *tty)
{
guard(mutex)(&vc_sel.lock);
guard(console_lock)();
return vc_selection(vc_cons[fg_console].d, v, tty);
}
EXPORT_SYMBOL_GPL(set_selection_kernel);
/* Insert the contents of the selection buffer into the
* queue of the tty associated with the current console.
* Invoked by ioctl().
*
* Locking: called without locks. Calls the ldisc wrongly with
* unsafe methods,
*/
int paste_selection(struct tty_struct *tty)
{
struct vc_data *vc = tty->driver_data;
int pasted = 0;
size_t count;
struct tty_ldisc *ld;
DECLARE_WAITQUEUE(wait, current);
int ret = 0;
bool bp = vc->vc_bracketed_paste;
static const char bracketed_paste_start[] = "\033[200~";
static const char bracketed_paste_end[] = "\033[201~";
const char *bps = bp ? bracketed_paste_start : NULL;
const char *bpe = bp ? bracketed_paste_end : NULL;
scoped_guard(console_lock)
poke_blanked_console();
ld = tty_ldisc_ref_wait(tty);
if (!ld)
return -EIO; /* ldisc was hung up */
tty_buffer_lock_exclusive(&vc->port);
add_wait_queue(&vc->paste_wait, &wait);
mutex_lock(&vc_sel.lock);
while (vc_sel.buffer && (vc_sel.buf_len > pasted || bpe)) {
set_current_state(TASK_INTERRUPTIBLE);
if (signal_pending(current)) {
ret = -EINTR;
break;
}
if (tty_throttled(tty)) {
mutex_unlock(&vc_sel.lock);
schedule();
mutex_lock(&vc_sel.lock);
continue;
}
__set_current_state(TASK_RUNNING);
if (bps) {
bps += tty_ldisc_receive_buf(ld, bps, NULL, strlen(bps));
if (*bps != '\0')
continue;
bps = NULL;
}
count = vc_sel.buf_len - pasted;
if (count) {
pasted += tty_ldisc_receive_buf(ld, vc_sel.buffer + pasted,
NULL, count);
if (vc_sel.buf_len > pasted)
continue;
}
if (bpe) {
bpe += tty_ldisc_receive_buf(ld, bpe, NULL, strlen(bpe));
if (*bpe == '\0')
bpe = NULL;
}
}
mutex_unlock(&vc_sel.lock);
remove_wait_queue(&vc->paste_wait, &wait);
__set_current_state(TASK_RUNNING);
tty_buffer_unlock_exclusive(&vc->port);
tty_ldisc_deref(ld);
return ret;
}
EXPORT_SYMBOL_GPL(paste_selection);
+293
View File
@@ -0,0 +1,293 @@
// SPDX-License-Identifier: GPL-2.0
/*
* ucs.c - Universal Character Set processing
*/
#include <linux/array_size.h>
#include <linux/build_bug.h>
#include <linux/bsearch.h>
#include <linux/consolemap.h>
#include <linux/math.h>
struct ucs_width16 {
u16 first;
u16 last;
};
struct ucs_width32 {
u32 first;
u32 last;
};
/*
* Width table encoding (consumed by ucs_width_table.h):
*
* Zero- and double-width ranges are merged into one sorted-by-`first` table
* per region (BMP / non-BMP). The BMP table stores plain (first, last)
* pairs; per-entry width lives in a packed bitmap *hosted by the non-BMP
* table*.
*
* That hosting is the whole point of the encoding. Non-BMP code points use
* only 20 bits, so each u32 has 12 spare high bits sitting around doing
* nothing — we'd rather use them than spend a separate parallel array for
* width and BMP-bitmap bits. So we move the cp value up by UCS_CP_SHIFT
* and stash metadata in the now-free low bits of `last`:
* - bit UCS_NONBMP_W2_FLAG_BIT: this entry's own width (0=zero, 1=double),
* - bits 0..UCS_NONBMP_BMP_BITS-1: a chunk of the BMP double-width
* bitmap. Bit `j` of the chunk in non-BMP entry `c` is set iff BMP
* entry (c * UCS_NONBMP_BMP_BITS + j) is double-width. The first
* ceil(N_BMP / UCS_NONBMP_BMP_BITS) non-BMP entries carry the bitmap;
* the rest leave these bits zero.
*
* Because the metadata bits sit strictly below the lowest cp-scale bit,
* the bsearch comparator does plain u32 comparison on the shifted key and
* stored values without masking — ordering between distinct code points is
* undisturbed.
*/
#define UCS_CP_SHIFT 12
#define UCS_NONBMP_W2_FLAG_BIT 11
#define UCS_NONBMP_W2_FLAG (1u << UCS_NONBMP_W2_FLAG_BIT)
#define BMP_0WIDTH(first, last) first, last
#define BMP_2WIDTH(first, last) first, last
#define RANGE_0WIDTH(first, last) \
(u32)(first) << UCS_CP_SHIFT, (u32)(last) << UCS_CP_SHIFT
#define RANGE_2WIDTH(first, last) \
(u32)(first) << UCS_CP_SHIFT, ((u32)(last) << UCS_CP_SHIFT) | UCS_NONBMP_W2_FLAG
#define BMP_2W_BITS(b) (b)
#include "ucs_width_table.h"
static_assert(UCS_NONBMP_BMP_BITS <= UCS_NONBMP_W2_FLAG_BIT,
"BMP bitmap chunk would overlap the per-entry width flag");
static_assert(UCS_NONBMP_W2_FLAG_BIT < UCS_CP_SHIFT,
"Metadata bits collide with the shifted cp value");
static_assert(DIV_ROUND_UP(ARRAY_SIZE(ucs_bmp_ranges), UCS_NONBMP_BMP_BITS)
<= ARRAY_SIZE(ucs_nonbmp_ranges),
"Not enough non-BMP entries to host the BMP width bitmap");
#define UCS_IS_BMP(cp) ((cp) <= 0xffff)
static int width16_cmp(const void *key, const void *element)
{
u16 cp = *(u16 *)key;
const struct ucs_width16 *entry = element;
if (cp < entry->first)
return -1;
if (cp > entry->last)
return 1;
return 0;
}
static int width32_cmp(const void *key, const void *element)
{
u32 k = *(u32 *)key;
const struct ucs_width32 *entry = element;
if (k < entry->first)
return -1;
if (k > entry->last)
return 1;
return 0;
}
/**
* ucs_get_width() - Get the display width of a Unicode code point.
* @cp: Unicode code point (UCS-4)
*
* Return: 2 for double-width (East Asian Wide/Fullwidth, emoji, ...),
* 0 for zero-width (combining marks, format characters, ...),
* 1 for everything else (the common case).
*/
unsigned int ucs_get_width(u32 cp)
{
const struct ucs_width16 *e16;
const struct ucs_width32 *e32;
unsigned int idx;
u32 k;
if (UCS_IS_BMP(cp)) {
u16 bmp = cp;
if (bmp < ucs_bmp_ranges[0].first ||
bmp > ucs_bmp_ranges[ARRAY_SIZE(ucs_bmp_ranges) - 1].last)
return 1;
e16 = __inline_bsearch(&bmp, ucs_bmp_ranges,
ARRAY_SIZE(ucs_bmp_ranges),
sizeof(*ucs_bmp_ranges), width16_cmp);
if (!e16)
return 1;
idx = e16 - ucs_bmp_ranges;
return (ucs_nonbmp_ranges[idx / UCS_NONBMP_BMP_BITS].last
>> (idx % UCS_NONBMP_BMP_BITS)) & 1 ? 2 : 0;
}
k = cp << UCS_CP_SHIFT;
if (k < ucs_nonbmp_ranges[0].first ||
k > ucs_nonbmp_ranges[ARRAY_SIZE(ucs_nonbmp_ranges) - 1].last)
return 1;
e32 = __inline_bsearch(&k, ucs_nonbmp_ranges,
ARRAY_SIZE(ucs_nonbmp_ranges),
sizeof(*ucs_nonbmp_ranges), width32_cmp);
if (!e32)
return 1;
return (e32->last & UCS_NONBMP_W2_FLAG) ? 2 : 0;
}
/*
* Structure for base with combining mark pairs and resulting recompositions.
* Using u16 to save space since all values are within BMP range.
*/
struct ucs_recomposition {
u16 base; /* base character */
u16 mark; /* combining mark */
u16 recomposed; /* corresponding recomposed character */
};
#include "ucs_recompose_table.h"
struct compare_key {
u16 base;
u16 mark;
};
static int recomposition_cmp(const void *key, const void *element)
{
const struct compare_key *search_key = key;
const struct ucs_recomposition *entry = element;
/* Compare base character first */
if (search_key->base < entry->base)
return -1;
if (search_key->base > entry->base)
return 1;
/* Base characters match, now compare combining character */
if (search_key->mark < entry->mark)
return -1;
if (search_key->mark > entry->mark)
return 1;
/* Both match */
return 0;
}
/**
* ucs_recompose() - Attempt to recompose two Unicode characters into a single character.
* @base: Base Unicode code point (UCS-4)
* @mark: Combining mark Unicode code point (UCS-4)
*
* Return: Recomposed Unicode code point, or 0 if no recomposition is possible
*/
u32 ucs_recompose(u32 base, u32 mark)
{
/* Check if characters are within the range of our table */
if (base < UCS_RECOMPOSE_MIN_BASE || base > UCS_RECOMPOSE_MAX_BASE ||
mark < UCS_RECOMPOSE_MIN_MARK || mark > UCS_RECOMPOSE_MAX_MARK)
return 0;
struct compare_key key = { base, mark };
struct ucs_recomposition *result =
__inline_bsearch(&key, ucs_recomposition_table,
ARRAY_SIZE(ucs_recomposition_table),
sizeof(*ucs_recomposition_table),
recomposition_cmp);
return result ? result->recomposed : 0;
}
/*
* The fallback table structures implement a 2-level lookup.
*/
struct ucs_page_desc {
u8 page; /* Page index (high byte of code points) */
u8 count; /* Number of entries in this page */
u16 start; /* Start index in entries array */
};
struct ucs_page_entry {
u8 offset; /* Offset within page (0-255) */
u8 fallback; /* Fallback character or range start marker */
};
#include "ucs_fallback_table.h"
static int ucs_page_desc_cmp(const void *key, const void *element)
{
u8 page = *(u8 *)key;
const struct ucs_page_desc *entry = element;
if (page < entry->page)
return -1;
if (page > entry->page)
return 1;
return 0;
}
static int ucs_page_entry_cmp(const void *key, const void *element)
{
u8 offset = *(u8 *)key;
const struct ucs_page_entry *entry = element;
if (offset < entry->offset)
return -1;
if (entry->fallback == UCS_PAGE_ENTRY_RANGE_MARKER) {
if (offset > entry[1].offset)
return 1;
} else {
if (offset > entry->offset)
return 1;
}
return 0;
}
/**
* ucs_get_fallback() - Get a substitution for the provided Unicode character
* @cp: Unicode code point (UCS-4)
*
* Get a simpler fallback character for the provided Unicode character.
* This is used for terminal display when corresponding glyph is unavailable.
* The substitution may not be as good as the actual glyph for the original
* character but still way more helpful than a squared question mark.
*
* Return: Fallback Unicode code point, or 0 if none is available
*/
u32 ucs_get_fallback(u32 cp)
{
const struct ucs_page_desc *page;
const struct ucs_page_entry *entry;
u8 page_idx = cp >> 8, offset = cp;
if (!UCS_IS_BMP(cp))
return 0;
/*
* Full-width to ASCII mapping (covering all printable ASCII 33-126)
* 0xFF01 (!) to 0xFF5E (~) -> ASCII 33 (!) to 126 (~)
* We process them programmatically to reduce the table size.
*/
if (cp >= 0xFF01 && cp <= 0xFF5E)
return cp - 0xFF01 + 33;
page = __inline_bsearch(&page_idx, ucs_fallback_pages,
ARRAY_SIZE(ucs_fallback_pages),
sizeof(*ucs_fallback_pages),
ucs_page_desc_cmp);
if (!page)
return 0;
entry = __inline_bsearch(&offset, ucs_fallback_entries + page->start,
page->count, sizeof(*ucs_fallback_entries),
ucs_page_entry_cmp);
if (!entry)
return 0;
if (entry->fallback == UCS_PAGE_ENTRY_RANGE_MARKER)
entry++;
return entry->fallback;
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,102 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* ucs_recompose_table.h - Unicode character recomposition
*
* Auto-generated by gen_ucs_recompose_table.py
*
* Unicode Version: 16.0.0
*
* This file contains a table with most commonly used Latin, Greek, and
* Cyrillic recomposition pairs only (71 entries). To generate a table with
* all possible recomposition pairs from the Unicode BMP (1000 entries)
* instead, run:
*
* python gen_ucs_recompose_table.py --full
*/
/*
* Table of most commonly used Latin, Greek, and Cyrillic recomposition pairs only
* Sorted by base character and then combining mark for binary search
*/
static const struct ucs_recomposition ucs_recomposition_table[] = {
{ 0x0041, 0x0300, 0x00C0 }, /* LATIN CAPITAL LETTER A + COMBINING GRAVE ACCENT = LATIN CAPITAL LETTER A WITH GRAVE */
{ 0x0041, 0x0301, 0x00C1 }, /* LATIN CAPITAL LETTER A + COMBINING ACUTE ACCENT = LATIN CAPITAL LETTER A WITH ACUTE */
{ 0x0041, 0x0302, 0x00C2 }, /* LATIN CAPITAL LETTER A + COMBINING CIRCUMFLEX ACCENT = LATIN CAPITAL LETTER A WITH CIRCUMFLEX */
{ 0x0041, 0x0303, 0x00C3 }, /* LATIN CAPITAL LETTER A + COMBINING TILDE = LATIN CAPITAL LETTER A WITH TILDE */
{ 0x0041, 0x0308, 0x00C4 }, /* LATIN CAPITAL LETTER A + COMBINING DIAERESIS = LATIN CAPITAL LETTER A WITH DIAERESIS */
{ 0x0041, 0x030A, 0x00C5 }, /* LATIN CAPITAL LETTER A + COMBINING RING ABOVE = LATIN CAPITAL LETTER A WITH RING ABOVE */
{ 0x0043, 0x0327, 0x00C7 }, /* LATIN CAPITAL LETTER C + COMBINING CEDILLA = LATIN CAPITAL LETTER C WITH CEDILLA */
{ 0x0045, 0x0300, 0x00C8 }, /* LATIN CAPITAL LETTER E + COMBINING GRAVE ACCENT = LATIN CAPITAL LETTER E WITH GRAVE */
{ 0x0045, 0x0301, 0x00C9 }, /* LATIN CAPITAL LETTER E + COMBINING ACUTE ACCENT = LATIN CAPITAL LETTER E WITH ACUTE */
{ 0x0045, 0x0302, 0x00CA }, /* LATIN CAPITAL LETTER E + COMBINING CIRCUMFLEX ACCENT = LATIN CAPITAL LETTER E WITH CIRCUMFLEX */
{ 0x0045, 0x0308, 0x00CB }, /* LATIN CAPITAL LETTER E + COMBINING DIAERESIS = LATIN CAPITAL LETTER E WITH DIAERESIS */
{ 0x0049, 0x0300, 0x00CC }, /* LATIN CAPITAL LETTER I + COMBINING GRAVE ACCENT = LATIN CAPITAL LETTER I WITH GRAVE */
{ 0x0049, 0x0301, 0x00CD }, /* LATIN CAPITAL LETTER I + COMBINING ACUTE ACCENT = LATIN CAPITAL LETTER I WITH ACUTE */
{ 0x0049, 0x0302, 0x00CE }, /* LATIN CAPITAL LETTER I + COMBINING CIRCUMFLEX ACCENT = LATIN CAPITAL LETTER I WITH CIRCUMFLEX */
{ 0x0049, 0x0308, 0x00CF }, /* LATIN CAPITAL LETTER I + COMBINING DIAERESIS = LATIN CAPITAL LETTER I WITH DIAERESIS */
{ 0x004E, 0x0303, 0x00D1 }, /* LATIN CAPITAL LETTER N + COMBINING TILDE = LATIN CAPITAL LETTER N WITH TILDE */
{ 0x004F, 0x0300, 0x00D2 }, /* LATIN CAPITAL LETTER O + COMBINING GRAVE ACCENT = LATIN CAPITAL LETTER O WITH GRAVE */
{ 0x004F, 0x0301, 0x00D3 }, /* LATIN CAPITAL LETTER O + COMBINING ACUTE ACCENT = LATIN CAPITAL LETTER O WITH ACUTE */
{ 0x004F, 0x0302, 0x00D4 }, /* LATIN CAPITAL LETTER O + COMBINING CIRCUMFLEX ACCENT = LATIN CAPITAL LETTER O WITH CIRCUMFLEX */
{ 0x004F, 0x0303, 0x00D5 }, /* LATIN CAPITAL LETTER O + COMBINING TILDE = LATIN CAPITAL LETTER O WITH TILDE */
{ 0x004F, 0x0308, 0x00D6 }, /* LATIN CAPITAL LETTER O + COMBINING DIAERESIS = LATIN CAPITAL LETTER O WITH DIAERESIS */
{ 0x0055, 0x0300, 0x00D9 }, /* LATIN CAPITAL LETTER U + COMBINING GRAVE ACCENT = LATIN CAPITAL LETTER U WITH GRAVE */
{ 0x0055, 0x0301, 0x00DA }, /* LATIN CAPITAL LETTER U + COMBINING ACUTE ACCENT = LATIN CAPITAL LETTER U WITH ACUTE */
{ 0x0055, 0x0302, 0x00DB }, /* LATIN CAPITAL LETTER U + COMBINING CIRCUMFLEX ACCENT = LATIN CAPITAL LETTER U WITH CIRCUMFLEX */
{ 0x0055, 0x0308, 0x00DC }, /* LATIN CAPITAL LETTER U + COMBINING DIAERESIS = LATIN CAPITAL LETTER U WITH DIAERESIS */
{ 0x0059, 0x0301, 0x00DD }, /* LATIN CAPITAL LETTER Y + COMBINING ACUTE ACCENT = LATIN CAPITAL LETTER Y WITH ACUTE */
{ 0x0061, 0x0300, 0x00E0 }, /* LATIN SMALL LETTER A + COMBINING GRAVE ACCENT = LATIN SMALL LETTER A WITH GRAVE */
{ 0x0061, 0x0301, 0x00E1 }, /* LATIN SMALL LETTER A + COMBINING ACUTE ACCENT = LATIN SMALL LETTER A WITH ACUTE */
{ 0x0061, 0x0302, 0x00E2 }, /* LATIN SMALL LETTER A + COMBINING CIRCUMFLEX ACCENT = LATIN SMALL LETTER A WITH CIRCUMFLEX */
{ 0x0061, 0x0303, 0x00E3 }, /* LATIN SMALL LETTER A + COMBINING TILDE = LATIN SMALL LETTER A WITH TILDE */
{ 0x0061, 0x0308, 0x00E4 }, /* LATIN SMALL LETTER A + COMBINING DIAERESIS = LATIN SMALL LETTER A WITH DIAERESIS */
{ 0x0061, 0x030A, 0x00E5 }, /* LATIN SMALL LETTER A + COMBINING RING ABOVE = LATIN SMALL LETTER A WITH RING ABOVE */
{ 0x0063, 0x0327, 0x00E7 }, /* LATIN SMALL LETTER C + COMBINING CEDILLA = LATIN SMALL LETTER C WITH CEDILLA */
{ 0x0065, 0x0300, 0x00E8 }, /* LATIN SMALL LETTER E + COMBINING GRAVE ACCENT = LATIN SMALL LETTER E WITH GRAVE */
{ 0x0065, 0x0301, 0x00E9 }, /* LATIN SMALL LETTER E + COMBINING ACUTE ACCENT = LATIN SMALL LETTER E WITH ACUTE */
{ 0x0065, 0x0302, 0x00EA }, /* LATIN SMALL LETTER E + COMBINING CIRCUMFLEX ACCENT = LATIN SMALL LETTER E WITH CIRCUMFLEX */
{ 0x0065, 0x0308, 0x00EB }, /* LATIN SMALL LETTER E + COMBINING DIAERESIS = LATIN SMALL LETTER E WITH DIAERESIS */
{ 0x0069, 0x0300, 0x00EC }, /* LATIN SMALL LETTER I + COMBINING GRAVE ACCENT = LATIN SMALL LETTER I WITH GRAVE */
{ 0x0069, 0x0301, 0x00ED }, /* LATIN SMALL LETTER I + COMBINING ACUTE ACCENT = LATIN SMALL LETTER I WITH ACUTE */
{ 0x0069, 0x0302, 0x00EE }, /* LATIN SMALL LETTER I + COMBINING CIRCUMFLEX ACCENT = LATIN SMALL LETTER I WITH CIRCUMFLEX */
{ 0x0069, 0x0308, 0x00EF }, /* LATIN SMALL LETTER I + COMBINING DIAERESIS = LATIN SMALL LETTER I WITH DIAERESIS */
{ 0x006E, 0x0303, 0x00F1 }, /* LATIN SMALL LETTER N + COMBINING TILDE = LATIN SMALL LETTER N WITH TILDE */
{ 0x006F, 0x0300, 0x00F2 }, /* LATIN SMALL LETTER O + COMBINING GRAVE ACCENT = LATIN SMALL LETTER O WITH GRAVE */
{ 0x006F, 0x0301, 0x00F3 }, /* LATIN SMALL LETTER O + COMBINING ACUTE ACCENT = LATIN SMALL LETTER O WITH ACUTE */
{ 0x006F, 0x0302, 0x00F4 }, /* LATIN SMALL LETTER O + COMBINING CIRCUMFLEX ACCENT = LATIN SMALL LETTER O WITH CIRCUMFLEX */
{ 0x006F, 0x0303, 0x00F5 }, /* LATIN SMALL LETTER O + COMBINING TILDE = LATIN SMALL LETTER O WITH TILDE */
{ 0x006F, 0x0308, 0x00F6 }, /* LATIN SMALL LETTER O + COMBINING DIAERESIS = LATIN SMALL LETTER O WITH DIAERESIS */
{ 0x0075, 0x0300, 0x00F9 }, /* LATIN SMALL LETTER U + COMBINING GRAVE ACCENT = LATIN SMALL LETTER U WITH GRAVE */
{ 0x0075, 0x0301, 0x00FA }, /* LATIN SMALL LETTER U + COMBINING ACUTE ACCENT = LATIN SMALL LETTER U WITH ACUTE */
{ 0x0075, 0x0302, 0x00FB }, /* LATIN SMALL LETTER U + COMBINING CIRCUMFLEX ACCENT = LATIN SMALL LETTER U WITH CIRCUMFLEX */
{ 0x0075, 0x0308, 0x00FC }, /* LATIN SMALL LETTER U + COMBINING DIAERESIS = LATIN SMALL LETTER U WITH DIAERESIS */
{ 0x0079, 0x0301, 0x00FD }, /* LATIN SMALL LETTER Y + COMBINING ACUTE ACCENT = LATIN SMALL LETTER Y WITH ACUTE */
{ 0x0079, 0x0308, 0x00FF }, /* LATIN SMALL LETTER Y + COMBINING DIAERESIS = LATIN SMALL LETTER Y WITH DIAERESIS */
{ 0x0391, 0x0301, 0x0386 }, /* GREEK CAPITAL LETTER ALPHA + COMBINING ACUTE ACCENT = GREEK CAPITAL LETTER ALPHA WITH TONOS */
{ 0x0395, 0x0301, 0x0388 }, /* GREEK CAPITAL LETTER EPSILON + COMBINING ACUTE ACCENT = GREEK CAPITAL LETTER EPSILON WITH TONOS */
{ 0x0397, 0x0301, 0x0389 }, /* GREEK CAPITAL LETTER ETA + COMBINING ACUTE ACCENT = GREEK CAPITAL LETTER ETA WITH TONOS */
{ 0x0399, 0x0301, 0x038A }, /* GREEK CAPITAL LETTER IOTA + COMBINING ACUTE ACCENT = GREEK CAPITAL LETTER IOTA WITH TONOS */
{ 0x039F, 0x0301, 0x038C }, /* GREEK CAPITAL LETTER OMICRON + COMBINING ACUTE ACCENT = GREEK CAPITAL LETTER OMICRON WITH TONOS */
{ 0x03A5, 0x0301, 0x038E }, /* GREEK CAPITAL LETTER UPSILON + COMBINING ACUTE ACCENT = GREEK CAPITAL LETTER UPSILON WITH TONOS */
{ 0x03A9, 0x0301, 0x038F }, /* GREEK CAPITAL LETTER OMEGA + COMBINING ACUTE ACCENT = GREEK CAPITAL LETTER OMEGA WITH TONOS */
{ 0x03B1, 0x0301, 0x03AC }, /* GREEK SMALL LETTER ALPHA + COMBINING ACUTE ACCENT = GREEK SMALL LETTER ALPHA WITH TONOS */
{ 0x03B5, 0x0301, 0x03AD }, /* GREEK SMALL LETTER EPSILON + COMBINING ACUTE ACCENT = GREEK SMALL LETTER EPSILON WITH TONOS */
{ 0x03B7, 0x0301, 0x03AE }, /* GREEK SMALL LETTER ETA + COMBINING ACUTE ACCENT = GREEK SMALL LETTER ETA WITH TONOS */
{ 0x03B9, 0x0301, 0x03AF }, /* GREEK SMALL LETTER IOTA + COMBINING ACUTE ACCENT = GREEK SMALL LETTER IOTA WITH TONOS */
{ 0x03BF, 0x0301, 0x03CC }, /* GREEK SMALL LETTER OMICRON + COMBINING ACUTE ACCENT = GREEK SMALL LETTER OMICRON WITH TONOS */
{ 0x03C5, 0x0301, 0x03CD }, /* GREEK SMALL LETTER UPSILON + COMBINING ACUTE ACCENT = GREEK SMALL LETTER UPSILON WITH TONOS */
{ 0x03C9, 0x0301, 0x03CE }, /* GREEK SMALL LETTER OMEGA + COMBINING ACUTE ACCENT = GREEK SMALL LETTER OMEGA WITH TONOS */
{ 0x0418, 0x0306, 0x0419 }, /* CYRILLIC CAPITAL LETTER I + COMBINING BREVE = CYRILLIC CAPITAL LETTER SHORT I */
{ 0x0423, 0x0306, 0x040E }, /* CYRILLIC CAPITAL LETTER U + COMBINING BREVE = CYRILLIC CAPITAL LETTER SHORT U */
{ 0x0438, 0x0306, 0x0439 }, /* CYRILLIC SMALL LETTER I + COMBINING BREVE = CYRILLIC SMALL LETTER SHORT I */
{ 0x0443, 0x0306, 0x045E }, /* CYRILLIC SMALL LETTER U + COMBINING BREVE = CYRILLIC SMALL LETTER SHORT U */
};
/*
* Boundary values for quick rejection
* These are calculated by analyzing the table during generation
*/
#define UCS_RECOMPOSE_MIN_BASE 0x0041
#define UCS_RECOMPOSE_MAX_BASE 0x0443
#define UCS_RECOMPOSE_MIN_MARK 0x0300
#define UCS_RECOMPOSE_MAX_MARK 0x0327
@@ -0,0 +1,490 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* ucs_width_table.h - Unicode character width
*
* Auto-generated by gen_ucs_width_table.py
*
* Unicode Version: 16.0.0
*
* Zero-width and double-width ranges are merged into one sorted-by-`first`
* table per region. The non-BMP table additionally hosts the BMP
* double-width bitmap in the low 8 bits of `last` of its
* first 33 entries (covering 262 BMP entries).
* See ucs.c for the encoding details and the lookup code.
*/
/* Bits per BMP-bitmap chunk hosted in one non-BMP entry's `last` field. */
#define UCS_NONBMP_BMP_BITS 8
/* Combined zero- and double-width ranges
* (BMP - Basic Multilingual Plane, U+0000 to U+FFFF). */
static const struct ucs_width16 ucs_bmp_ranges[] = {
{ BMP_0WIDTH(0x00AD, 0x00AD) }, /* SOFT HYPHEN */
{ BMP_0WIDTH(0x0300, 0x036F) }, /* COMBINING GRAVE ACCENT - COMBINING LATIN SMALL LETTER X */
{ BMP_0WIDTH(0x0483, 0x0489) }, /* COMBINING CYRILLIC TITLO - COMBINING CYRILLIC MILLIONS SIGN */
{ BMP_0WIDTH(0x0591, 0x05BD) }, /* HEBREW ACCENT ETNAHTA - HEBREW POINT METEG */
{ BMP_0WIDTH(0x05BF, 0x05BF) }, /* HEBREW POINT RAFE */
{ BMP_0WIDTH(0x05C1, 0x05C2) }, /* HEBREW POINT SHIN DOT - HEBREW POINT SIN DOT */
{ BMP_0WIDTH(0x05C4, 0x05C5) }, /* HEBREW MARK UPPER DOT - HEBREW MARK LOWER DOT */
{ BMP_0WIDTH(0x05C7, 0x05C7) }, /* HEBREW POINT QAMATS QATAN */
{ BMP_0WIDTH(0x0600, 0x0605) }, /* ARABIC NUMBER SIGN - ARABIC NUMBER MARK ABOVE */
{ BMP_0WIDTH(0x0610, 0x061A) }, /* ARABIC SIGN SALLALLAHOU ALAYHE WASSALLAM - ARABIC SMALL KASRA */
{ BMP_0WIDTH(0x061C, 0x061C) }, /* ARABIC LETTER MARK */
{ BMP_0WIDTH(0x064B, 0x065F) }, /* ARABIC FATHATAN - ARABIC WAVY HAMZA BELOW */
{ BMP_0WIDTH(0x0670, 0x0670) }, /* ARABIC LETTER SUPERSCRIPT ALEF */
{ BMP_0WIDTH(0x06D6, 0x06DD) }, /* ARABIC SMALL HIGH LIGATURE SAD WITH LAM WITH ALEF MAKSURA - ARABIC END OF AYAH */
{ BMP_0WIDTH(0x06DF, 0x06E4) }, /* ARABIC SMALL HIGH ROUNDED ZERO - ARABIC SMALL HIGH MADDA */
{ BMP_0WIDTH(0x06E7, 0x06E8) }, /* ARABIC SMALL HIGH YEH - ARABIC SMALL HIGH NOON */
{ BMP_0WIDTH(0x06EA, 0x06ED) }, /* ARABIC EMPTY CENTRE LOW STOP - ARABIC SMALL LOW MEEM */
{ BMP_0WIDTH(0x070F, 0x070F) }, /* SYRIAC ABBREVIATION MARK */
{ BMP_0WIDTH(0x0711, 0x0711) }, /* SYRIAC LETTER SUPERSCRIPT ALAPH */
{ BMP_0WIDTH(0x0730, 0x074A) }, /* SYRIAC PTHAHA ABOVE - SYRIAC BARREKH */
{ BMP_0WIDTH(0x07A6, 0x07B0) }, /* THAANA ABAFILI - THAANA SUKUN */
{ BMP_0WIDTH(0x07EB, 0x07F3) }, /* NKO COMBINING SHORT HIGH TONE - NKO COMBINING DOUBLE DOT ABOVE */
{ BMP_0WIDTH(0x07FD, 0x07FD) }, /* NKO DANTAYALAN */
{ BMP_0WIDTH(0x0816, 0x0819) }, /* SAMARITAN MARK IN - SAMARITAN MARK DAGESH */
{ BMP_0WIDTH(0x081B, 0x0823) }, /* SAMARITAN MARK EPENTHETIC YUT - SAMARITAN VOWEL SIGN A */
{ BMP_0WIDTH(0x0825, 0x0827) }, /* SAMARITAN VOWEL SIGN SHORT A - SAMARITAN VOWEL SIGN U */
{ BMP_0WIDTH(0x0829, 0x082D) }, /* SAMARITAN VOWEL SIGN LONG I - SAMARITAN MARK NEQUDAA */
{ BMP_0WIDTH(0x0859, 0x085B) }, /* MANDAIC AFFRICATION MARK - MANDAIC GEMINATION MARK */
{ BMP_0WIDTH(0x0890, 0x0891) }, /* ARABIC POUND MARK ABOVE - ARABIC PIASTRE MARK ABOVE */
{ BMP_0WIDTH(0x0897, 0x089F) }, /* ARABIC PEPET - ARABIC HALF MADDA OVER MADDA */
{ BMP_0WIDTH(0x08CA, 0x0903) }, /* ARABIC SMALL HIGH FARSI YEH - DEVANAGARI SIGN VISARGA */
{ BMP_0WIDTH(0x093A, 0x093C) }, /* DEVANAGARI VOWEL SIGN OE - DEVANAGARI SIGN NUKTA */
{ BMP_0WIDTH(0x093E, 0x094F) }, /* DEVANAGARI VOWEL SIGN AA - DEVANAGARI VOWEL SIGN AW */
{ BMP_0WIDTH(0x0951, 0x0957) }, /* DEVANAGARI STRESS SIGN UDATTA - DEVANAGARI VOWEL SIGN UUE */
{ BMP_0WIDTH(0x0962, 0x0963) }, /* DEVANAGARI VOWEL SIGN VOCALIC L - DEVANAGARI VOWEL SIGN VOCALIC LL */
{ BMP_0WIDTH(0x0981, 0x0983) }, /* BENGALI SIGN CANDRABINDU - BENGALI SIGN VISARGA */
{ BMP_0WIDTH(0x09BC, 0x09BC) }, /* BENGALI SIGN NUKTA */
{ BMP_0WIDTH(0x09BE, 0x09C4) }, /* BENGALI VOWEL SIGN AA - BENGALI VOWEL SIGN VOCALIC RR */
{ BMP_0WIDTH(0x09C7, 0x09C8) }, /* BENGALI VOWEL SIGN E - BENGALI VOWEL SIGN AI */
{ BMP_0WIDTH(0x09CB, 0x09CD) }, /* BENGALI VOWEL SIGN O - BENGALI SIGN VIRAMA */
{ BMP_0WIDTH(0x09D7, 0x09D7) }, /* BENGALI AU LENGTH MARK */
{ BMP_0WIDTH(0x09E2, 0x09E3) }, /* BENGALI VOWEL SIGN VOCALIC L - BENGALI VOWEL SIGN VOCALIC LL */
{ BMP_0WIDTH(0x09FE, 0x09FE) }, /* BENGALI SANDHI MARK */
{ BMP_0WIDTH(0x0A01, 0x0A03) }, /* GURMUKHI SIGN ADAK BINDI - GURMUKHI SIGN VISARGA */
{ BMP_0WIDTH(0x0A3C, 0x0A3C) }, /* GURMUKHI SIGN NUKTA */
{ BMP_0WIDTH(0x0A3E, 0x0A42) }, /* GURMUKHI VOWEL SIGN AA - GURMUKHI VOWEL SIGN UU */
{ BMP_0WIDTH(0x0A47, 0x0A48) }, /* GURMUKHI VOWEL SIGN EE - GURMUKHI VOWEL SIGN AI */
{ BMP_0WIDTH(0x0A4B, 0x0A4D) }, /* GURMUKHI VOWEL SIGN OO - GURMUKHI SIGN VIRAMA */
{ BMP_0WIDTH(0x0A51, 0x0A51) }, /* GURMUKHI SIGN UDAAT */
{ BMP_0WIDTH(0x0A70, 0x0A71) }, /* GURMUKHI TIPPI - GURMUKHI ADDAK */
{ BMP_0WIDTH(0x0A75, 0x0A75) }, /* GURMUKHI SIGN YAKASH */
{ BMP_0WIDTH(0x0A81, 0x0A83) }, /* GUJARATI SIGN CANDRABINDU - GUJARATI SIGN VISARGA */
{ BMP_0WIDTH(0x0ABC, 0x0ABC) }, /* GUJARATI SIGN NUKTA */
{ BMP_0WIDTH(0x0ABE, 0x0AC5) }, /* GUJARATI VOWEL SIGN AA - GUJARATI VOWEL SIGN CANDRA E */
{ BMP_0WIDTH(0x0AC7, 0x0AC9) }, /* GUJARATI VOWEL SIGN E - GUJARATI VOWEL SIGN CANDRA O */
{ BMP_0WIDTH(0x0ACB, 0x0ACD) }, /* GUJARATI VOWEL SIGN O - GUJARATI SIGN VIRAMA */
{ BMP_0WIDTH(0x0AE2, 0x0AE3) }, /* GUJARATI VOWEL SIGN VOCALIC L - GUJARATI VOWEL SIGN VOCALIC LL */
{ BMP_0WIDTH(0x0AFA, 0x0AFF) }, /* GUJARATI SIGN SUKUN - GUJARATI SIGN TWO-CIRCLE NUKTA ABOVE */
{ BMP_0WIDTH(0x0B01, 0x0B03) }, /* ORIYA SIGN CANDRABINDU - ORIYA SIGN VISARGA */
{ BMP_0WIDTH(0x0B3C, 0x0B3C) }, /* ORIYA SIGN NUKTA */
{ BMP_0WIDTH(0x0B3E, 0x0B44) }, /* ORIYA VOWEL SIGN AA - ORIYA VOWEL SIGN VOCALIC RR */
{ BMP_0WIDTH(0x0B47, 0x0B48) }, /* ORIYA VOWEL SIGN E - ORIYA VOWEL SIGN AI */
{ BMP_0WIDTH(0x0B4B, 0x0B4D) }, /* ORIYA VOWEL SIGN O - ORIYA SIGN VIRAMA */
{ BMP_0WIDTH(0x0B55, 0x0B57) }, /* ORIYA SIGN OVERLINE - ORIYA AU LENGTH MARK */
{ BMP_0WIDTH(0x0B62, 0x0B63) }, /* ORIYA VOWEL SIGN VOCALIC L - ORIYA VOWEL SIGN VOCALIC LL */
{ BMP_0WIDTH(0x0B82, 0x0B82) }, /* TAMIL SIGN ANUSVARA */
{ BMP_0WIDTH(0x0BBE, 0x0BC2) }, /* TAMIL VOWEL SIGN AA - TAMIL VOWEL SIGN UU */
{ BMP_0WIDTH(0x0BC6, 0x0BC8) }, /* TAMIL VOWEL SIGN E - TAMIL VOWEL SIGN AI */
{ BMP_0WIDTH(0x0BCA, 0x0BCD) }, /* TAMIL VOWEL SIGN O - TAMIL SIGN VIRAMA */
{ BMP_0WIDTH(0x0BD7, 0x0BD7) }, /* TAMIL AU LENGTH MARK */
{ BMP_0WIDTH(0x0C00, 0x0C04) }, /* TELUGU SIGN COMBINING CANDRABINDU ABOVE - TELUGU SIGN COMBINING ANUSVARA ABOVE */
{ BMP_0WIDTH(0x0C3C, 0x0C3C) }, /* TELUGU SIGN NUKTA */
{ BMP_0WIDTH(0x0C3E, 0x0C44) }, /* TELUGU VOWEL SIGN AA - TELUGU VOWEL SIGN VOCALIC RR */
{ BMP_0WIDTH(0x0C46, 0x0C48) }, /* TELUGU VOWEL SIGN E - TELUGU VOWEL SIGN AI */
{ BMP_0WIDTH(0x0C4A, 0x0C4D) }, /* TELUGU VOWEL SIGN O - TELUGU SIGN VIRAMA */
{ BMP_0WIDTH(0x0C55, 0x0C56) }, /* TELUGU LENGTH MARK - TELUGU AI LENGTH MARK */
{ BMP_0WIDTH(0x0C62, 0x0C63) }, /* TELUGU VOWEL SIGN VOCALIC L - TELUGU VOWEL SIGN VOCALIC LL */
{ BMP_0WIDTH(0x0C81, 0x0C83) }, /* KANNADA SIGN CANDRABINDU - KANNADA SIGN VISARGA */
{ BMP_0WIDTH(0x0CBC, 0x0CBC) }, /* KANNADA SIGN NUKTA */
{ BMP_0WIDTH(0x0CBE, 0x0CC4) }, /* KANNADA VOWEL SIGN AA - KANNADA VOWEL SIGN VOCALIC RR */
{ BMP_0WIDTH(0x0CC6, 0x0CC8) }, /* KANNADA VOWEL SIGN E - KANNADA VOWEL SIGN AI */
{ BMP_0WIDTH(0x0CCA, 0x0CCD) }, /* KANNADA VOWEL SIGN O - KANNADA SIGN VIRAMA */
{ BMP_0WIDTH(0x0CD5, 0x0CD6) }, /* KANNADA LENGTH MARK - KANNADA AI LENGTH MARK */
{ BMP_0WIDTH(0x0CE2, 0x0CE3) }, /* KANNADA VOWEL SIGN VOCALIC L - KANNADA VOWEL SIGN VOCALIC LL */
{ BMP_0WIDTH(0x0CF3, 0x0CF3) }, /* KANNADA SIGN COMBINING ANUSVARA ABOVE RIGHT */
{ BMP_0WIDTH(0x0D00, 0x0D03) }, /* MALAYALAM SIGN COMBINING ANUSVARA ABOVE - MALAYALAM SIGN VISARGA */
{ BMP_0WIDTH(0x0D3B, 0x0D3C) }, /* MALAYALAM SIGN VERTICAL BAR VIRAMA - MALAYALAM SIGN CIRCULAR VIRAMA */
{ BMP_0WIDTH(0x0D3E, 0x0D44) }, /* MALAYALAM VOWEL SIGN AA - MALAYALAM VOWEL SIGN VOCALIC RR */
{ BMP_0WIDTH(0x0D46, 0x0D48) }, /* MALAYALAM VOWEL SIGN E - MALAYALAM VOWEL SIGN AI */
{ BMP_0WIDTH(0x0D4A, 0x0D4D) }, /* MALAYALAM VOWEL SIGN O - MALAYALAM SIGN VIRAMA */
{ BMP_0WIDTH(0x0D57, 0x0D57) }, /* MALAYALAM AU LENGTH MARK */
{ BMP_0WIDTH(0x0D62, 0x0D63) }, /* MALAYALAM VOWEL SIGN VOCALIC L - MALAYALAM VOWEL SIGN VOCALIC LL */
{ BMP_0WIDTH(0x0D81, 0x0D83) }, /* SINHALA SIGN CANDRABINDU - SINHALA SIGN VISARGAYA */
{ BMP_0WIDTH(0x0DCA, 0x0DCA) }, /* SINHALA SIGN AL-LAKUNA */
{ BMP_0WIDTH(0x0DCF, 0x0DD4) }, /* SINHALA VOWEL SIGN AELA-PILLA - SINHALA VOWEL SIGN KETTI PAA-PILLA */
{ BMP_0WIDTH(0x0DD6, 0x0DD6) }, /* SINHALA VOWEL SIGN DIGA PAA-PILLA */
{ BMP_0WIDTH(0x0DD8, 0x0DDF) }, /* SINHALA VOWEL SIGN GAETTA-PILLA - SINHALA VOWEL SIGN GAYANUKITTA */
{ BMP_0WIDTH(0x0DF2, 0x0DF3) }, /* SINHALA VOWEL SIGN DIGA GAETTA-PILLA - SINHALA VOWEL SIGN DIGA GAYANUKITTA */
{ BMP_0WIDTH(0x0E31, 0x0E31) }, /* THAI CHARACTER MAI HAN-AKAT */
{ BMP_0WIDTH(0x0E34, 0x0E3A) }, /* THAI CHARACTER SARA I - THAI CHARACTER PHINTHU */
{ BMP_0WIDTH(0x0E47, 0x0E4E) }, /* THAI CHARACTER MAITAIKHU - THAI CHARACTER YAMAKKAN */
{ BMP_0WIDTH(0x0EB1, 0x0EB1) }, /* LAO VOWEL SIGN MAI KAN */
{ BMP_0WIDTH(0x0EB4, 0x0EBC) }, /* LAO VOWEL SIGN I - LAO SEMIVOWEL SIGN LO */
{ BMP_0WIDTH(0x0EC8, 0x0ECE) }, /* LAO TONE MAI EK - LAO YAMAKKAN */
{ BMP_0WIDTH(0x0F18, 0x0F19) }, /* TIBETAN ASTROLOGICAL SIGN -KHYUD PA - TIBETAN ASTROLOGICAL SIGN SDONG TSHUGS */
{ BMP_0WIDTH(0x0F35, 0x0F35) }, /* TIBETAN MARK NGAS BZUNG NYI ZLA */
{ BMP_0WIDTH(0x0F37, 0x0F37) }, /* TIBETAN MARK NGAS BZUNG SGOR RTAGS */
{ BMP_0WIDTH(0x0F39, 0x0F39) }, /* TIBETAN MARK TSA -PHRU */
{ BMP_0WIDTH(0x0F3E, 0x0F3F) }, /* TIBETAN SIGN YAR TSHES - TIBETAN SIGN MAR TSHES */
{ BMP_0WIDTH(0x0F71, 0x0F84) }, /* TIBETAN VOWEL SIGN AA - TIBETAN MARK HALANTA */
{ BMP_0WIDTH(0x0F86, 0x0F87) }, /* TIBETAN SIGN LCI RTAGS - TIBETAN SIGN YANG RTAGS */
{ BMP_0WIDTH(0x0F8D, 0x0F97) }, /* TIBETAN SUBJOINED SIGN LCE TSA CAN - TIBETAN SUBJOINED LETTER JA */
{ BMP_0WIDTH(0x0F99, 0x0FBC) }, /* TIBETAN SUBJOINED LETTER NYA - TIBETAN SUBJOINED LETTER FIXED-FORM RA */
{ BMP_0WIDTH(0x0FC6, 0x0FC6) }, /* TIBETAN SYMBOL PADMA GDAN */
{ BMP_0WIDTH(0x102B, 0x103E) }, /* MYANMAR VOWEL SIGN TALL AA - MYANMAR CONSONANT SIGN MEDIAL HA */
{ BMP_0WIDTH(0x1056, 0x1059) }, /* MYANMAR VOWEL SIGN VOCALIC R - MYANMAR VOWEL SIGN VOCALIC LL */
{ BMP_0WIDTH(0x105E, 0x1060) }, /* MYANMAR CONSONANT SIGN MON MEDIAL NA - MYANMAR CONSONANT SIGN MON MEDIAL LA */
{ BMP_0WIDTH(0x1062, 0x1064) }, /* MYANMAR VOWEL SIGN SGAW KAREN EU - MYANMAR TONE MARK SGAW KAREN KE PHO */
{ BMP_0WIDTH(0x1067, 0x106D) }, /* MYANMAR VOWEL SIGN WESTERN PWO KAREN EU - MYANMAR SIGN WESTERN PWO KAREN TONE-5 */
{ BMP_0WIDTH(0x1071, 0x1074) }, /* MYANMAR VOWEL SIGN GEBA KAREN I - MYANMAR VOWEL SIGN KAYAH EE */
{ BMP_0WIDTH(0x1082, 0x108D) }, /* MYANMAR CONSONANT SIGN SHAN MEDIAL WA - MYANMAR SIGN SHAN COUNCIL EMPHATIC TONE */
{ BMP_0WIDTH(0x108F, 0x108F) }, /* MYANMAR SIGN RUMAI PALAUNG TONE-5 */
{ BMP_0WIDTH(0x109A, 0x109D) }, /* MYANMAR SIGN KHAMTI TONE-1 - MYANMAR VOWEL SIGN AITON AI */
{ BMP_2WIDTH(0x1100, 0x115F) }, /* HANGUL CHOSEONG KIYEOK - HANGUL CHOSEONG FILLER */
{ BMP_0WIDTH(0x135D, 0x135F) }, /* ETHIOPIC COMBINING GEMINATION AND VOWEL LENGTH MARK - ETHIOPIC COMBINING GEMINATION MARK */
{ BMP_0WIDTH(0x1712, 0x1715) }, /* TAGALOG VOWEL SIGN I - TAGALOG SIGN PAMUDPOD */
{ BMP_0WIDTH(0x1732, 0x1734) }, /* HANUNOO VOWEL SIGN I - HANUNOO SIGN PAMUDPOD */
{ BMP_0WIDTH(0x1752, 0x1753) }, /* BUHID VOWEL SIGN I - BUHID VOWEL SIGN U */
{ BMP_0WIDTH(0x1772, 0x1773) }, /* TAGBANWA VOWEL SIGN I - TAGBANWA VOWEL SIGN U */
{ BMP_0WIDTH(0x17B4, 0x17D3) }, /* KHMER VOWEL INHERENT AQ - KHMER SIGN BATHAMASAT */
{ BMP_0WIDTH(0x17DD, 0x17DD) }, /* KHMER SIGN ATTHACAN */
{ BMP_0WIDTH(0x180B, 0x180F) }, /* MONGOLIAN FREE VARIATION SELECTOR ONE - MONGOLIAN FREE VARIATION SELECTOR FOUR */
{ BMP_0WIDTH(0x1885, 0x1886) }, /* MONGOLIAN LETTER ALI GALI BALUDA - MONGOLIAN LETTER ALI GALI THREE BALUDA */
{ BMP_0WIDTH(0x18A9, 0x18A9) }, /* MONGOLIAN LETTER ALI GALI DAGALGA */
{ BMP_0WIDTH(0x1920, 0x192B) }, /* LIMBU VOWEL SIGN A - LIMBU SUBJOINED LETTER WA */
{ BMP_0WIDTH(0x1930, 0x193B) }, /* LIMBU SMALL LETTER KA - LIMBU SIGN SA-I */
{ BMP_0WIDTH(0x1A17, 0x1A1B) }, /* BUGINESE VOWEL SIGN I - BUGINESE VOWEL SIGN AE */
{ BMP_0WIDTH(0x1A55, 0x1A5E) }, /* TAI THAM CONSONANT SIGN MEDIAL RA - TAI THAM CONSONANT SIGN SA */
{ BMP_0WIDTH(0x1A60, 0x1A7C) }, /* TAI THAM SIGN SAKOT - TAI THAM SIGN KHUEN-LUE KARAN */
{ BMP_0WIDTH(0x1A7F, 0x1A7F) }, /* TAI THAM COMBINING CRYPTOGRAMMIC DOT */
{ BMP_0WIDTH(0x1AB0, 0x1ACE) }, /* COMBINING DOUBLED CIRCUMFLEX ACCENT - COMBINING LATIN SMALL LETTER INSULAR T */
{ BMP_0WIDTH(0x1B00, 0x1B04) }, /* BALINESE SIGN ULU RICEM - BALINESE SIGN BISAH */
{ BMP_0WIDTH(0x1B34, 0x1B44) }, /* BALINESE SIGN REREKAN - BALINESE ADEG ADEG */
{ BMP_0WIDTH(0x1B6B, 0x1B73) }, /* BALINESE MUSICAL SYMBOL COMBINING TEGEH - BALINESE MUSICAL SYMBOL COMBINING GONG */
{ BMP_0WIDTH(0x1B80, 0x1B82) }, /* SUNDANESE SIGN PANYECEK - SUNDANESE SIGN PANGWISAD */
{ BMP_0WIDTH(0x1BA1, 0x1BAD) }, /* SUNDANESE CONSONANT SIGN PAMINGKAL - SUNDANESE CONSONANT SIGN PASANGAN WA */
{ BMP_0WIDTH(0x1BE6, 0x1BF3) }, /* BATAK SIGN TOMPI - BATAK PANONGONAN */
{ BMP_0WIDTH(0x1C24, 0x1C37) }, /* LEPCHA SUBJOINED LETTER YA - LEPCHA SIGN NUKTA */
{ BMP_0WIDTH(0x1CD0, 0x1CD2) }, /* VEDIC TONE KARSHANA - VEDIC TONE PRENKHA */
{ BMP_0WIDTH(0x1CD4, 0x1CE8) }, /* VEDIC SIGN YAJURVEDIC MIDLINE SVARITA - VEDIC SIGN VISARGA ANUDATTA WITH TAIL */
{ BMP_0WIDTH(0x1CED, 0x1CED) }, /* VEDIC SIGN TIRYAK */
{ BMP_0WIDTH(0x1CF4, 0x1CF4) }, /* VEDIC TONE CANDRA ABOVE */
{ BMP_0WIDTH(0x1CF7, 0x1CF9) }, /* VEDIC SIGN ATIKRAMA - VEDIC TONE DOUBLE RING ABOVE */
{ BMP_0WIDTH(0x1DC0, 0x1DFF) }, /* COMBINING DOTTED GRAVE ACCENT - COMBINING RIGHT ARROWHEAD AND DOWN ARROWHEAD BELOW */
{ BMP_0WIDTH(0x200B, 0x200F) }, /* ZERO WIDTH SPACE - RIGHT-TO-LEFT MARK */
{ BMP_0WIDTH(0x202A, 0x202E) }, /* LEFT-TO-RIGHT EMBEDDING - RIGHT-TO-LEFT OVERRIDE */
{ BMP_0WIDTH(0x2060, 0x2064) }, /* WORD JOINER - INVISIBLE PLUS */
{ BMP_0WIDTH(0x2066, 0x206F) }, /* LEFT-TO-RIGHT ISOLATE - NOMINAL DIGIT SHAPES */
{ BMP_0WIDTH(0x20D0, 0x20F0) }, /* COMBINING LEFT HARPOON ABOVE - COMBINING ASTERISK ABOVE */
{ BMP_2WIDTH(0x231A, 0x231B) }, /* WATCH - HOURGLASS */
{ BMP_2WIDTH(0x2329, 0x232A) }, /* LEFT-POINTING ANGLE BRACKET - RIGHT-POINTING ANGLE BRACKET */
{ BMP_2WIDTH(0x23E9, 0x23EC) }, /* BLACK RIGHT-POINTING DOUBLE TRIANGLE - BLACK DOWN-POINTING DOUBLE TRIANGLE */
{ BMP_2WIDTH(0x23F0, 0x23F0) }, /* ALARM CLOCK */
{ BMP_2WIDTH(0x23F3, 0x23F3) }, /* HOURGLASS WITH FLOWING SAND */
{ BMP_2WIDTH(0x25FD, 0x25FE) }, /* WHITE MEDIUM SMALL SQUARE - BLACK MEDIUM SMALL SQUARE */
{ BMP_2WIDTH(0x2614, 0x2615) }, /* UMBRELLA WITH RAIN DROPS - HOT BEVERAGE */
{ BMP_2WIDTH(0x2630, 0x2637) }, /* TRIGRAM FOR HEAVEN - TRIGRAM FOR EARTH */
{ BMP_0WIDTH(0x2640, 0x2640) }, /* FEMALE SIGN */
{ BMP_0WIDTH(0x2642, 0x2642) }, /* MALE SIGN */
{ BMP_2WIDTH(0x2648, 0x2653) }, /* ARIES - PISCES */
{ BMP_2WIDTH(0x267F, 0x267F) }, /* WHEELCHAIR SYMBOL */
{ BMP_2WIDTH(0x268A, 0x268F) }, /* MONOGRAM FOR YANG - DIGRAM FOR GREATER YIN */
{ BMP_2WIDTH(0x2693, 0x2693) }, /* ANCHOR */
{ BMP_2WIDTH(0x26A1, 0x26A1) }, /* HIGH VOLTAGE SIGN */
{ BMP_0WIDTH(0x26A7, 0x26A7) }, /* MALE WITH STROKE AND MALE AND FEMALE SIGN */
{ BMP_2WIDTH(0x26AA, 0x26AB) }, /* MEDIUM WHITE CIRCLE - MEDIUM BLACK CIRCLE */
{ BMP_2WIDTH(0x26BD, 0x26BE) }, /* SOCCER BALL - BASEBALL */
{ BMP_2WIDTH(0x26C4, 0x26C5) }, /* SNOWMAN WITHOUT SNOW - SUN BEHIND CLOUD */
{ BMP_2WIDTH(0x26CE, 0x26CE) }, /* OPHIUCHUS */
{ BMP_2WIDTH(0x26D4, 0x26D4) }, /* NO ENTRY */
{ BMP_2WIDTH(0x26EA, 0x26EA) }, /* CHURCH */
{ BMP_2WIDTH(0x26F2, 0x26F3) }, /* FOUNTAIN - FLAG IN HOLE */
{ BMP_2WIDTH(0x26F5, 0x26F5) }, /* SAILBOAT */
{ BMP_2WIDTH(0x26FA, 0x26FA) }, /* TENT */
{ BMP_2WIDTH(0x26FD, 0x26FD) }, /* FUEL PUMP */
{ BMP_2WIDTH(0x2705, 0x2705) }, /* WHITE HEAVY CHECK MARK */
{ BMP_2WIDTH(0x270A, 0x270B) }, /* RAISED FIST - RAISED HAND */
{ BMP_2WIDTH(0x2728, 0x2728) }, /* SPARKLES */
{ BMP_2WIDTH(0x274C, 0x274C) }, /* CROSS MARK */
{ BMP_2WIDTH(0x274E, 0x274E) }, /* NEGATIVE SQUARED CROSS MARK */
{ BMP_2WIDTH(0x2753, 0x2755) }, /* BLACK QUESTION MARK ORNAMENT - WHITE EXCLAMATION MARK ORNAMENT */
{ BMP_2WIDTH(0x2757, 0x2757) }, /* HEAVY EXCLAMATION MARK SYMBOL */
{ BMP_2WIDTH(0x2795, 0x2797) }, /* HEAVY PLUS SIGN - HEAVY DIVISION SIGN */
{ BMP_2WIDTH(0x27B0, 0x27B0) }, /* CURLY LOOP */
{ BMP_2WIDTH(0x27BF, 0x27BF) }, /* DOUBLE CURLY LOOP */
{ BMP_2WIDTH(0x2B1B, 0x2B1C) }, /* BLACK LARGE SQUARE - WHITE LARGE SQUARE */
{ BMP_2WIDTH(0x2B50, 0x2B50) }, /* WHITE MEDIUM STAR */
{ BMP_2WIDTH(0x2B55, 0x2B55) }, /* HEAVY LARGE CIRCLE */
{ BMP_0WIDTH(0x2CEF, 0x2CF1) }, /* COPTIC COMBINING NI ABOVE - COPTIC COMBINING SPIRITUS LENIS */
{ BMP_0WIDTH(0x2D7F, 0x2D7F) }, /* TIFINAGH CONSONANT JOINER */
{ BMP_0WIDTH(0x2DE0, 0x2DFF) }, /* COMBINING CYRILLIC LETTER BE - COMBINING CYRILLIC LETTER IOTIFIED BIG YUS */
{ BMP_2WIDTH(0x2E80, 0x2E99) }, /* CJK RADICAL REPEAT - CJK RADICAL RAP */
{ BMP_2WIDTH(0x2E9B, 0x2EF3) }, /* CJK RADICAL CHOKE - CJK RADICAL C-SIMPLIFIED TURTLE */
{ BMP_2WIDTH(0x2F00, 0x2FD5) }, /* KANGXI RADICAL ONE - KANGXI RADICAL FLUTE */
{ BMP_2WIDTH(0x2FF0, 0x3029) }, /* IDEOGRAPHIC DESCRIPTION CHARACTER LEFT TO RIGHT - HANGZHOU NUMERAL NINE */
{ BMP_0WIDTH(0x302A, 0x302F) }, /* IDEOGRAPHIC LEVEL TONE MARK - HANGUL DOUBLE DOT TONE MARK */
{ BMP_2WIDTH(0x3030, 0x303E) }, /* WAVY DASH - IDEOGRAPHIC VARIATION INDICATOR */
{ BMP_2WIDTH(0x3041, 0x3096) }, /* HIRAGANA LETTER SMALL A - HIRAGANA LETTER SMALL KE */
{ BMP_0WIDTH(0x3099, 0x309A) }, /* COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK - COMBINING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK */
{ BMP_2WIDTH(0x309B, 0x30FF) }, /* KATAKANA-HIRAGANA VOICED SOUND MARK - KATAKANA DIGRAPH KOTO */
{ BMP_2WIDTH(0x3105, 0x312F) }, /* BOPOMOFO LETTER B - BOPOMOFO LETTER NN */
{ BMP_2WIDTH(0x3131, 0x318E) }, /* HANGUL LETTER KIYEOK - HANGUL LETTER ARAEAE */
{ BMP_2WIDTH(0x3190, 0x31E5) }, /* IDEOGRAPHIC ANNOTATION LINKING MARK - CJK STROKE SZP */
{ BMP_2WIDTH(0x31EF, 0x321E) }, /* IDEOGRAPHIC DESCRIPTION CHARACTER SUBTRACTION - PARENTHESIZED KOREAN CHARACTER O HU */
{ BMP_2WIDTH(0x3220, 0x3247) }, /* PARENTHESIZED IDEOGRAPH ONE - CIRCLED IDEOGRAPH KOTO */
{ BMP_2WIDTH(0x3250, 0xA48C) }, /* PARTNERSHIP SIGN - YI SYLLABLE YYR */
{ BMP_2WIDTH(0xA490, 0xA4C6) }, /* YI RADICAL QOT - YI RADICAL KE */
{ BMP_0WIDTH(0xA66F, 0xA672) }, /* COMBINING CYRILLIC VZMET - COMBINING CYRILLIC THOUSAND MILLIONS SIGN */
{ BMP_0WIDTH(0xA674, 0xA67D) }, /* COMBINING CYRILLIC LETTER UKRAINIAN IE - COMBINING CYRILLIC PAYEROK */
{ BMP_0WIDTH(0xA69E, 0xA69F) }, /* COMBINING CYRILLIC LETTER EF - COMBINING CYRILLIC LETTER IOTIFIED E */
{ BMP_0WIDTH(0xA6F0, 0xA6F1) }, /* BAMUM COMBINING MARK KOQNDON - BAMUM COMBINING MARK TUKWENTIS */
{ BMP_0WIDTH(0xA802, 0xA802) }, /* SYLOTI NAGRI SIGN DVISVARA */
{ BMP_0WIDTH(0xA806, 0xA806) }, /* SYLOTI NAGRI SIGN HASANTA */
{ BMP_0WIDTH(0xA80B, 0xA80B) }, /* SYLOTI NAGRI SIGN ANUSVARA */
{ BMP_0WIDTH(0xA823, 0xA827) }, /* SYLOTI NAGRI VOWEL SIGN A - SYLOTI NAGRI VOWEL SIGN OO */
{ BMP_0WIDTH(0xA82C, 0xA82C) }, /* SYLOTI NAGRI SIGN ALTERNATE HASANTA */
{ BMP_0WIDTH(0xA880, 0xA881) }, /* SAURASHTRA SIGN ANUSVARA - SAURASHTRA SIGN VISARGA */
{ BMP_0WIDTH(0xA8B4, 0xA8C5) }, /* SAURASHTRA CONSONANT SIGN HAARU - SAURASHTRA SIGN CANDRABINDU */
{ BMP_0WIDTH(0xA8E0, 0xA8F1) }, /* COMBINING DEVANAGARI DIGIT ZERO - COMBINING DEVANAGARI SIGN AVAGRAHA */
{ BMP_0WIDTH(0xA8FF, 0xA8FF) }, /* DEVANAGARI VOWEL SIGN AY */
{ BMP_0WIDTH(0xA926, 0xA92D) }, /* KAYAH LI VOWEL UE - KAYAH LI TONE CALYA PLOPHU */
{ BMP_0WIDTH(0xA947, 0xA953) }, /* REJANG VOWEL SIGN I - REJANG VIRAMA */
{ BMP_2WIDTH(0xA960, 0xA97C) }, /* HANGUL CHOSEONG TIKEUT-MIEUM - HANGUL CHOSEONG SSANGYEORINHIEUH */
{ BMP_0WIDTH(0xA980, 0xA983) }, /* JAVANESE SIGN PANYANGGA - JAVANESE SIGN WIGNYAN */
{ BMP_0WIDTH(0xA9B3, 0xA9C0) }, /* JAVANESE SIGN CECAK TELU - JAVANESE PANGKON */
{ BMP_0WIDTH(0xA9E5, 0xA9E5) }, /* MYANMAR SIGN SHAN SAW */
{ BMP_0WIDTH(0xAA29, 0xAA36) }, /* CHAM VOWEL SIGN AA - CHAM CONSONANT SIGN WA */
{ BMP_0WIDTH(0xAA43, 0xAA43) }, /* CHAM CONSONANT SIGN FINAL NG */
{ BMP_0WIDTH(0xAA4C, 0xAA4D) }, /* CHAM CONSONANT SIGN FINAL M - CHAM CONSONANT SIGN FINAL H */
{ BMP_0WIDTH(0xAA7B, 0xAA7D) }, /* MYANMAR SIGN PAO KAREN TONE - MYANMAR SIGN TAI LAING TONE-5 */
{ BMP_0WIDTH(0xAAB0, 0xAAB0) }, /* TAI VIET MAI KANG */
{ BMP_0WIDTH(0xAAB2, 0xAAB4) }, /* TAI VIET VOWEL I - TAI VIET VOWEL U */
{ BMP_0WIDTH(0xAAB7, 0xAAB8) }, /* TAI VIET MAI KHIT - TAI VIET VOWEL IA */
{ BMP_0WIDTH(0xAABE, 0xAABF) }, /* TAI VIET VOWEL AM - TAI VIET TONE MAI EK */
{ BMP_0WIDTH(0xAAC1, 0xAAC1) }, /* TAI VIET TONE MAI THO */
{ BMP_0WIDTH(0xAAEB, 0xAAEF) }, /* MEETEI MAYEK VOWEL SIGN II - MEETEI MAYEK VOWEL SIGN AAU */
{ BMP_0WIDTH(0xAAF5, 0xAAF6) }, /* MEETEI MAYEK VOWEL SIGN VISARGA - MEETEI MAYEK VIRAMA */
{ BMP_0WIDTH(0xABE3, 0xABEA) }, /* MEETEI MAYEK VOWEL SIGN ONAP - MEETEI MAYEK VOWEL SIGN NUNG */
{ BMP_0WIDTH(0xABEC, 0xABED) }, /* MEETEI MAYEK LUM IYEK - MEETEI MAYEK APUN IYEK */
{ BMP_2WIDTH(0xAC00, 0xD7A3) }, /* HANGUL SYLLABLE GA - HANGUL SYLLABLE HIH */
{ BMP_2WIDTH(0xF900, 0xFAFF) }, /* U+F900 - U+FAFF */
{ BMP_0WIDTH(0xFB1E, 0xFB1E) }, /* HEBREW POINT JUDEO-SPANISH VARIKA */
{ BMP_0WIDTH(0xFE00, 0xFE0F) }, /* VARIATION SELECTOR-1 - VARIATION SELECTOR-16 */
{ BMP_2WIDTH(0xFE10, 0xFE19) }, /* PRESENTATION FORM FOR VERTICAL COMMA - PRESENTATION FORM FOR VERTICAL HORIZONTAL ELLIPSIS */
{ BMP_0WIDTH(0xFE20, 0xFE2F) }, /* COMBINING LIGATURE LEFT HALF - COMBINING CYRILLIC TITLO RIGHT HALF */
{ BMP_2WIDTH(0xFE30, 0xFE52) }, /* PRESENTATION FORM FOR VERTICAL TWO DOT LEADER - SMALL FULL STOP */
{ BMP_2WIDTH(0xFE54, 0xFE66) }, /* SMALL SEMICOLON - SMALL EQUALS SIGN */
{ BMP_2WIDTH(0xFE68, 0xFE6B) }, /* SMALL REVERSE SOLIDUS - SMALL COMMERCIAL AT */
{ BMP_0WIDTH(0xFEFF, 0xFEFF) }, /* ZERO WIDTH NO-BREAK SPACE */
{ BMP_2WIDTH(0xFF01, 0xFF60) }, /* FULLWIDTH EXCLAMATION MARK - FULLWIDTH RIGHT WHITE PARENTHESIS */
{ BMP_2WIDTH(0xFFE0, 0xFFE6) }, /* FULLWIDTH CENT SIGN - FULLWIDTH WON SIGN */
{ BMP_0WIDTH(0xFFF9, 0xFFFB) }, /* INTERLINEAR ANNOTATION ANCHOR - INTERLINEAR ANNOTATION TERMINATOR */
};
/* Combined zero- and double-width ranges (non-BMP, U+10000 and above).
* The first 33 entries host the BMP double-width bitmap in the low
* 8 bits of `last`. */
static const struct ucs_width32 ucs_nonbmp_ranges[] = {
{ RANGE_0WIDTH(0x101FD, 0x101FD) /* PHAISTOS DISC SIGN COMBINING OBLIQUE STROKE */
| BMP_2W_BITS(0b00000000) }, /* BMP entries [ 0.. 7] */
{ RANGE_0WIDTH(0x102E0, 0x102E0) /* COPTIC EPACT THOUSANDS MARK */
| BMP_2W_BITS(0b00000000) }, /* BMP entries [ 8.. 15] */
{ RANGE_0WIDTH(0x10376, 0x1037A) /* COMBINING OLD PERMIC LETTER AN - COMBINING OLD PERMIC LETTER SII */
| BMP_2W_BITS(0b00000000) }, /* BMP entries [ 16.. 23] */
{ RANGE_0WIDTH(0x10A01, 0x10A03) /* KHAROSHTHI VOWEL SIGN I - KHAROSHTHI VOWEL SIGN VOCALIC R */
| BMP_2W_BITS(0b00000000) }, /* BMP entries [ 24.. 31] */
{ RANGE_0WIDTH(0x10A05, 0x10A06) /* KHAROSHTHI VOWEL SIGN E - KHAROSHTHI VOWEL SIGN O */
| BMP_2W_BITS(0b00000000) }, /* BMP entries [ 32.. 39] */
{ RANGE_0WIDTH(0x10A0C, 0x10A0F) /* KHAROSHTHI VOWEL LENGTH MARK - KHAROSHTHI SIGN VISARGA */
| BMP_2W_BITS(0b00000000) }, /* BMP entries [ 40.. 47] */
{ RANGE_0WIDTH(0x10A38, 0x10A3A) /* KHAROSHTHI SIGN BAR ABOVE - KHAROSHTHI SIGN DOT BELOW */
| BMP_2W_BITS(0b00000000) }, /* BMP entries [ 48.. 55] */
{ RANGE_0WIDTH(0x10A3F, 0x10A3F) /* KHAROSHTHI VIRAMA */
| BMP_2W_BITS(0b00000000) }, /* BMP entries [ 56.. 63] */
{ RANGE_0WIDTH(0x10AE5, 0x10AE6) /* MANICHAEAN ABBREVIATION MARK ABOVE - MANICHAEAN ABBREVIATION MARK BELOW */
| BMP_2W_BITS(0b00000000) }, /* BMP entries [ 64.. 71] */
{ RANGE_0WIDTH(0x10D24, 0x10D27) /* HANIFI ROHINGYA SIGN HARBAHAY - HANIFI ROHINGYA SIGN TASSI */
| BMP_2W_BITS(0b00000000) }, /* BMP entries [ 72.. 79] */
{ RANGE_0WIDTH(0x10D69, 0x10D6D) /* GARAY VOWEL SIGN E - GARAY CONSONANT NASALIZATION MARK */
| BMP_2W_BITS(0b00000000) }, /* BMP entries [ 80.. 87] */
{ RANGE_0WIDTH(0x10EAB, 0x10EAC) /* YEZIDI COMBINING HAMZA MARK - YEZIDI COMBINING MADDA MARK */
| BMP_2W_BITS(0b00000000) }, /* BMP entries [ 88.. 95] */
{ RANGE_0WIDTH(0x10EFC, 0x10EFF) /* ARABIC COMBINING ALEF OVERLAY - ARABIC SMALL LOW WORD MADDA */
| BMP_2W_BITS(0b00000000) }, /* BMP entries [ 96..103] */
{ RANGE_0WIDTH(0x10F46, 0x10F50) /* SOGDIAN COMBINING DOT BELOW - SOGDIAN COMBINING STROKE BELOW */
| BMP_2W_BITS(0b00000000) }, /* BMP entries [104..111] */
{ RANGE_0WIDTH(0x10F82, 0x10F85) /* OLD UYGHUR COMBINING DOT ABOVE - OLD UYGHUR COMBINING TWO DOTS BELOW */
| BMP_2W_BITS(0b00000000) }, /* BMP entries [112..119] */
{ RANGE_0WIDTH(0x11000, 0x11002) /* BRAHMI SIGN CANDRABINDU - BRAHMI SIGN VISARGA */
| BMP_2W_BITS(0b00001000) }, /* BMP entries [120..127] */
{ RANGE_0WIDTH(0x11038, 0x11046) /* BRAHMI VOWEL SIGN AA - BRAHMI VIRAMA */
| BMP_2W_BITS(0b00000000) }, /* BMP entries [128..135] */
{ RANGE_0WIDTH(0x11070, 0x11070) /* BRAHMI SIGN OLD TAMIL VIRAMA */
| BMP_2W_BITS(0b00000000) }, /* BMP entries [136..143] */
{ RANGE_0WIDTH(0x11073, 0x11074) /* BRAHMI VOWEL SIGN OLD TAMIL SHORT E - BRAHMI VOWEL SIGN OLD TAMIL SHORT O */
| BMP_2W_BITS(0b00000000) }, /* BMP entries [144..151] */
{ RANGE_0WIDTH(0x1107F, 0x11082) /* BRAHMI NUMBER JOINER - KAITHI SIGN VISARGA */
| BMP_2W_BITS(0b10000000) }, /* BMP entries [152..159] */
{ RANGE_0WIDTH(0x110B0, 0x110BA) /* KAITHI VOWEL SIGN AA - KAITHI SIGN NUKTA */
| BMP_2W_BITS(0b01111111) }, /* BMP entries [160..167] */
{ RANGE_0WIDTH(0x110BD, 0x110BD) /* KAITHI NUMBER SIGN */
| BMP_2W_BITS(0b10111110) }, /* BMP entries [168..175] */
{ RANGE_0WIDTH(0x110C2, 0x110C2) /* KAITHI VOWEL SIGN VOCALIC R */
| BMP_2W_BITS(0b11111111) }, /* BMP entries [176..183] */
{ RANGE_0WIDTH(0x110CD, 0x110CD) /* KAITHI NUMBER SIGN ABOVE */
| BMP_2W_BITS(0b11111111) }, /* BMP entries [184..191] */
{ RANGE_0WIDTH(0x11100, 0x11102) /* CHAKMA SIGN CANDRABINDU - CHAKMA SIGN VISARGA */
| BMP_2W_BITS(0b00111111) }, /* BMP entries [192..199] */
{ RANGE_0WIDTH(0x11127, 0x11134) /* CHAKMA VOWEL SIGN A - CHAKMA MAAYYAA */
| BMP_2W_BITS(0b11011110) }, /* BMP entries [200..207] */
{ RANGE_0WIDTH(0x11145, 0x11146) /* CHAKMA VOWEL SIGN AA - CHAKMA VOWEL SIGN EI */
| BMP_2W_BITS(0b11111110) }, /* BMP entries [208..215] */
{ RANGE_0WIDTH(0x11173, 0x11173) /* MAHAJANI SIGN NUKTA */
| BMP_2W_BITS(0b00000001) }, /* BMP entries [216..223] */
{ RANGE_0WIDTH(0x11180, 0x11182) /* SHARADA SIGN CANDRABINDU - SHARADA SIGN VISARGA */
| BMP_2W_BITS(0b00000000) }, /* BMP entries [224..231] */
{ RANGE_0WIDTH(0x111B3, 0x111C0) /* SHARADA VOWEL SIGN AA - SHARADA SIGN VIRAMA */
| BMP_2W_BITS(0b00000001) }, /* BMP entries [232..239] */
{ RANGE_0WIDTH(0x111C9, 0x111CC) /* SHARADA SANDHI MARK - SHARADA EXTRA SHORT VOWEL MARK */
| BMP_2W_BITS(0b00000000) }, /* BMP entries [240..247] */
{ RANGE_0WIDTH(0x111CE, 0x111CF) /* SHARADA VOWEL SIGN PRISHTHAMATRA E - SHARADA SIGN INVERTED CANDRABINDU */
| BMP_2W_BITS(0b10100110) }, /* BMP entries [248..255] */
{ RANGE_0WIDTH(0x1122C, 0x11237) /* KHOJKI VOWEL SIGN AA - KHOJKI SIGN SHADDA */
| BMP_2W_BITS(0b00011011) }, /* BMP entries [256..261] */
{ RANGE_0WIDTH(0x1123E, 0x1123E) }, /* KHOJKI SIGN SUKUN */
{ RANGE_0WIDTH(0x11241, 0x11241) }, /* KHOJKI VOWEL SIGN VOCALIC R */
{ RANGE_0WIDTH(0x112DF, 0x112EA) }, /* KHUDAWADI SIGN ANUSVARA - KHUDAWADI SIGN VIRAMA */
{ RANGE_0WIDTH(0x11300, 0x11303) }, /* GRANTHA SIGN COMBINING ANUSVARA ABOVE - GRANTHA SIGN VISARGA */
{ RANGE_0WIDTH(0x1133B, 0x1133C) }, /* COMBINING BINDU BELOW - GRANTHA SIGN NUKTA */
{ RANGE_0WIDTH(0x1133E, 0x11344) }, /* GRANTHA VOWEL SIGN AA - GRANTHA VOWEL SIGN VOCALIC RR */
{ RANGE_0WIDTH(0x11347, 0x11348) }, /* GRANTHA VOWEL SIGN EE - GRANTHA VOWEL SIGN AI */
{ RANGE_0WIDTH(0x1134B, 0x1134D) }, /* GRANTHA VOWEL SIGN OO - GRANTHA SIGN VIRAMA */
{ RANGE_0WIDTH(0x11357, 0x11357) }, /* GRANTHA AU LENGTH MARK */
{ RANGE_0WIDTH(0x11362, 0x11363) }, /* GRANTHA VOWEL SIGN VOCALIC L - GRANTHA VOWEL SIGN VOCALIC LL */
{ RANGE_0WIDTH(0x11366, 0x1136C) }, /* COMBINING GRANTHA DIGIT ZERO - COMBINING GRANTHA DIGIT SIX */
{ RANGE_0WIDTH(0x11370, 0x11374) }, /* COMBINING GRANTHA LETTER A - COMBINING GRANTHA LETTER PA */
{ RANGE_0WIDTH(0x113B8, 0x113C0) }, /* TULU-TIGALARI VOWEL SIGN AA - TULU-TIGALARI VOWEL SIGN VOCALIC LL */
{ RANGE_0WIDTH(0x113C2, 0x113C2) }, /* TULU-TIGALARI VOWEL SIGN EE */
{ RANGE_0WIDTH(0x113C5, 0x113C5) }, /* TULU-TIGALARI VOWEL SIGN AI */
{ RANGE_0WIDTH(0x113C7, 0x113CA) }, /* TULU-TIGALARI VOWEL SIGN OO - TULU-TIGALARI SIGN CANDRA ANUNASIKA */
{ RANGE_0WIDTH(0x113CC, 0x113D0) }, /* TULU-TIGALARI SIGN ANUSVARA - TULU-TIGALARI CONJOINER */
{ RANGE_0WIDTH(0x113D2, 0x113D2) }, /* TULU-TIGALARI GEMINATION MARK */
{ RANGE_0WIDTH(0x113E1, 0x113E2) }, /* TULU-TIGALARI VEDIC TONE SVARITA - TULU-TIGALARI VEDIC TONE ANUDATTA */
{ RANGE_0WIDTH(0x11435, 0x11446) }, /* NEWA VOWEL SIGN AA - NEWA SIGN NUKTA */
{ RANGE_0WIDTH(0x1145E, 0x1145E) }, /* NEWA SANDHI MARK */
{ RANGE_0WIDTH(0x114B0, 0x114C3) }, /* TIRHUTA VOWEL SIGN AA - TIRHUTA SIGN NUKTA */
{ RANGE_0WIDTH(0x115AF, 0x115B5) }, /* SIDDHAM VOWEL SIGN AA - SIDDHAM VOWEL SIGN VOCALIC RR */
{ RANGE_0WIDTH(0x115B8, 0x115C0) }, /* SIDDHAM VOWEL SIGN E - SIDDHAM SIGN NUKTA */
{ RANGE_0WIDTH(0x115DC, 0x115DD) }, /* SIDDHAM VOWEL SIGN ALTERNATE U - SIDDHAM VOWEL SIGN ALTERNATE UU */
{ RANGE_0WIDTH(0x11630, 0x11640) }, /* MODI VOWEL SIGN AA - MODI SIGN ARDHACANDRA */
{ RANGE_0WIDTH(0x116AB, 0x116B7) }, /* TAKRI SIGN ANUSVARA - TAKRI SIGN NUKTA */
{ RANGE_0WIDTH(0x1171D, 0x1172B) }, /* AHOM CONSONANT SIGN MEDIAL LA - AHOM SIGN KILLER */
{ RANGE_0WIDTH(0x1182C, 0x1183A) }, /* DOGRA VOWEL SIGN AA - DOGRA SIGN NUKTA */
{ RANGE_0WIDTH(0x11930, 0x11935) }, /* DIVES AKURU VOWEL SIGN AA - DIVES AKURU VOWEL SIGN E */
{ RANGE_0WIDTH(0x11937, 0x11938) }, /* DIVES AKURU VOWEL SIGN AI - DIVES AKURU VOWEL SIGN O */
{ RANGE_0WIDTH(0x1193B, 0x1193E) }, /* DIVES AKURU SIGN ANUSVARA - DIVES AKURU VIRAMA */
{ RANGE_0WIDTH(0x11940, 0x11940) }, /* DIVES AKURU MEDIAL YA */
{ RANGE_0WIDTH(0x11942, 0x11943) }, /* DIVES AKURU MEDIAL RA - DIVES AKURU SIGN NUKTA */
{ RANGE_0WIDTH(0x119D1, 0x119D7) }, /* NANDINAGARI VOWEL SIGN AA - NANDINAGARI VOWEL SIGN VOCALIC RR */
{ RANGE_0WIDTH(0x119DA, 0x119E0) }, /* NANDINAGARI VOWEL SIGN E - NANDINAGARI SIGN VIRAMA */
{ RANGE_0WIDTH(0x119E4, 0x119E4) }, /* NANDINAGARI VOWEL SIGN PRISHTHAMATRA E */
{ RANGE_0WIDTH(0x11A01, 0x11A0A) }, /* ZANABAZAR SQUARE VOWEL SIGN I - ZANABAZAR SQUARE VOWEL LENGTH MARK */
{ RANGE_0WIDTH(0x11A33, 0x11A39) }, /* ZANABAZAR SQUARE FINAL CONSONANT MARK - ZANABAZAR SQUARE SIGN VISARGA */
{ RANGE_0WIDTH(0x11A3B, 0x11A3E) }, /* ZANABAZAR SQUARE CLUSTER-FINAL LETTER YA - ZANABAZAR SQUARE CLUSTER-FINAL LETTER VA */
{ RANGE_0WIDTH(0x11A47, 0x11A47) }, /* ZANABAZAR SQUARE SUBJOINER */
{ RANGE_0WIDTH(0x11A51, 0x11A5B) }, /* SOYOMBO VOWEL SIGN I - SOYOMBO VOWEL LENGTH MARK */
{ RANGE_0WIDTH(0x11A8A, 0x11A99) }, /* SOYOMBO FINAL CONSONANT SIGN G - SOYOMBO SUBJOINER */
{ RANGE_0WIDTH(0x11C2F, 0x11C36) }, /* BHAIKSUKI VOWEL SIGN AA - BHAIKSUKI VOWEL SIGN VOCALIC L */
{ RANGE_0WIDTH(0x11C38, 0x11C3F) }, /* BHAIKSUKI VOWEL SIGN E - BHAIKSUKI SIGN VIRAMA */
{ RANGE_0WIDTH(0x11C92, 0x11CA7) }, /* MARCHEN SUBJOINED LETTER KA - MARCHEN SUBJOINED LETTER ZA */
{ RANGE_0WIDTH(0x11CA9, 0x11CB6) }, /* MARCHEN SUBJOINED LETTER YA - MARCHEN SIGN CANDRABINDU */
{ RANGE_0WIDTH(0x11D31, 0x11D36) }, /* MASARAM GONDI VOWEL SIGN AA - MASARAM GONDI VOWEL SIGN VOCALIC R */
{ RANGE_0WIDTH(0x11D3A, 0x11D3A) }, /* MASARAM GONDI VOWEL SIGN E */
{ RANGE_0WIDTH(0x11D3C, 0x11D3D) }, /* MASARAM GONDI VOWEL SIGN AI - MASARAM GONDI VOWEL SIGN O */
{ RANGE_0WIDTH(0x11D3F, 0x11D45) }, /* MASARAM GONDI VOWEL SIGN AU - MASARAM GONDI VIRAMA */
{ RANGE_0WIDTH(0x11D47, 0x11D47) }, /* MASARAM GONDI RA-KARA */
{ RANGE_0WIDTH(0x11D8A, 0x11D8E) }, /* GUNJALA GONDI VOWEL SIGN AA - GUNJALA GONDI VOWEL SIGN UU */
{ RANGE_0WIDTH(0x11D90, 0x11D91) }, /* GUNJALA GONDI VOWEL SIGN EE - GUNJALA GONDI VOWEL SIGN AI */
{ RANGE_0WIDTH(0x11D93, 0x11D97) }, /* GUNJALA GONDI VOWEL SIGN OO - GUNJALA GONDI VIRAMA */
{ RANGE_0WIDTH(0x11EF3, 0x11EF6) }, /* MAKASAR VOWEL SIGN I - MAKASAR VOWEL SIGN O */
{ RANGE_0WIDTH(0x11F00, 0x11F01) }, /* KAWI SIGN CANDRABINDU - KAWI SIGN ANUSVARA */
{ RANGE_0WIDTH(0x11F03, 0x11F03) }, /* KAWI SIGN VISARGA */
{ RANGE_0WIDTH(0x11F34, 0x11F3A) }, /* KAWI VOWEL SIGN AA - KAWI VOWEL SIGN VOCALIC R */
{ RANGE_0WIDTH(0x11F3E, 0x11F42) }, /* KAWI VOWEL SIGN E - KAWI CONJOINER */
{ RANGE_0WIDTH(0x11F5A, 0x11F5A) }, /* KAWI SIGN NUKTA */
{ RANGE_0WIDTH(0x13430, 0x13440) }, /* EGYPTIAN HIEROGLYPH VERTICAL JOINER - EGYPTIAN HIEROGLYPH MIRROR HORIZONTALLY */
{ RANGE_0WIDTH(0x13447, 0x13455) }, /* EGYPTIAN HIEROGLYPH MODIFIER DAMAGED AT TOP START - EGYPTIAN HIEROGLYPH MODIFIER DAMAGED */
{ RANGE_0WIDTH(0x1611E, 0x1612F) }, /* GURUNG KHEMA VOWEL SIGN AA - GURUNG KHEMA SIGN THOLHOMA */
{ RANGE_0WIDTH(0x16AF0, 0x16AF4) }, /* BASSA VAH COMBINING HIGH TONE - BASSA VAH COMBINING HIGH-LOW TONE */
{ RANGE_0WIDTH(0x16B30, 0x16B36) }, /* PAHAWH HMONG MARK CIM TUB - PAHAWH HMONG MARK CIM TAUM */
{ RANGE_0WIDTH(0x16F4F, 0x16F4F) }, /* MIAO SIGN CONSONANT MODIFIER BAR */
{ RANGE_0WIDTH(0x16F51, 0x16F87) }, /* MIAO SIGN ASPIRATION - MIAO VOWEL SIGN UI */
{ RANGE_0WIDTH(0x16F8F, 0x16F92) }, /* MIAO TONE RIGHT - MIAO TONE BELOW */
{ RANGE_2WIDTH(0x16FE0, 0x16FE3) }, /* TANGUT ITERATION MARK - OLD CHINESE ITERATION MARK */
{ RANGE_0WIDTH(0x16FE4, 0x16FE4) }, /* KHITAN SMALL SCRIPT FILLER */
{ RANGE_0WIDTH(0x16FF0, 0x16FF1) }, /* VIETNAMESE ALTERNATE READING MARK CA - VIETNAMESE ALTERNATE READING MARK NHAY */
{ RANGE_2WIDTH(0x17000, 0x187F7) }, /* U+17000 - U+187F7 */
{ RANGE_2WIDTH(0x18800, 0x18CD5) }, /* TANGUT COMPONENT-001 - KHITAN SMALL SCRIPT CHARACTER-18CD5 */
{ RANGE_2WIDTH(0x18CFF, 0x18D08) }, /* U+18CFF - U+18D08 */
{ RANGE_2WIDTH(0x1AFF0, 0x1AFF3) }, /* KATAKANA LETTER MINNAN TONE-2 - KATAKANA LETTER MINNAN TONE-5 */
{ RANGE_2WIDTH(0x1AFF5, 0x1AFFB) }, /* KATAKANA LETTER MINNAN TONE-7 - KATAKANA LETTER MINNAN NASALIZED TONE-5 */
{ RANGE_2WIDTH(0x1AFFD, 0x1AFFE) }, /* KATAKANA LETTER MINNAN NASALIZED TONE-7 - KATAKANA LETTER MINNAN NASALIZED TONE-8 */
{ RANGE_2WIDTH(0x1B000, 0x1B122) }, /* KATAKANA LETTER ARCHAIC E - KATAKANA LETTER ARCHAIC WU */
{ RANGE_2WIDTH(0x1B132, 0x1B132) }, /* HIRAGANA LETTER SMALL KO */
{ RANGE_2WIDTH(0x1B150, 0x1B152) }, /* HIRAGANA LETTER SMALL WI - HIRAGANA LETTER SMALL WO */
{ RANGE_2WIDTH(0x1B155, 0x1B155) }, /* KATAKANA LETTER SMALL KO */
{ RANGE_2WIDTH(0x1B164, 0x1B167) }, /* KATAKANA LETTER SMALL WI - KATAKANA LETTER SMALL N */
{ RANGE_2WIDTH(0x1B170, 0x1B2FB) }, /* NUSHU CHARACTER-1B170 - NUSHU CHARACTER-1B2FB */
{ RANGE_0WIDTH(0x1BC9D, 0x1BC9E) }, /* DUPLOYAN THICK LETTER SELECTOR - DUPLOYAN DOUBLE MARK */
{ RANGE_0WIDTH(0x1BCA0, 0x1BCA3) }, /* SHORTHAND FORMAT LETTER OVERLAP - SHORTHAND FORMAT UP STEP */
{ RANGE_0WIDTH(0x1CF00, 0x1CF2D) }, /* ZNAMENNY COMBINING MARK GORAZDO NIZKO S KRYZHEM ON LEFT - ZNAMENNY COMBINING MARK KRYZH ON LEFT */
{ RANGE_0WIDTH(0x1CF30, 0x1CF46) }, /* ZNAMENNY COMBINING TONAL RANGE MARK MRACHNO - ZNAMENNY PRIZNAK MODIFIER ROG */
{ RANGE_0WIDTH(0x1D165, 0x1D169) }, /* MUSICAL SYMBOL COMBINING STEM - MUSICAL SYMBOL COMBINING TREMOLO-3 */
{ RANGE_0WIDTH(0x1D16D, 0x1D182) }, /* MUSICAL SYMBOL COMBINING AUGMENTATION DOT - MUSICAL SYMBOL COMBINING LOURE */
{ RANGE_0WIDTH(0x1D185, 0x1D18B) }, /* MUSICAL SYMBOL COMBINING DOIT - MUSICAL SYMBOL COMBINING TRIPLE TONGUE */
{ RANGE_0WIDTH(0x1D1AA, 0x1D1AD) }, /* MUSICAL SYMBOL COMBINING DOWN BOW - MUSICAL SYMBOL COMBINING SNAP PIZZICATO */
{ RANGE_0WIDTH(0x1D242, 0x1D244) }, /* COMBINING GREEK MUSICAL TRISEME - COMBINING GREEK MUSICAL PENTASEME */
{ RANGE_2WIDTH(0x1D300, 0x1D356) }, /* MONOGRAM FOR EARTH - TETRAGRAM FOR FOSTERING */
{ RANGE_2WIDTH(0x1D360, 0x1D376) }, /* COUNTING ROD UNIT DIGIT ONE - IDEOGRAPHIC TALLY MARK FIVE */
{ RANGE_0WIDTH(0x1DA00, 0x1DA36) }, /* SIGNWRITING HEAD RIM - SIGNWRITING AIR SUCKING IN */
{ RANGE_0WIDTH(0x1DA3B, 0x1DA6C) }, /* SIGNWRITING MOUTH CLOSED NEUTRAL - SIGNWRITING EXCITEMENT */
{ RANGE_0WIDTH(0x1DA75, 0x1DA75) }, /* SIGNWRITING UPPER BODY TILTING FROM HIP JOINTS */
{ RANGE_0WIDTH(0x1DA84, 0x1DA84) }, /* SIGNWRITING LOCATION HEAD NECK */
{ RANGE_0WIDTH(0x1DA9B, 0x1DA9F) }, /* SIGNWRITING FILL MODIFIER-2 - SIGNWRITING FILL MODIFIER-6 */
{ RANGE_0WIDTH(0x1DAA1, 0x1DAAF) }, /* SIGNWRITING ROTATION MODIFIER-2 - SIGNWRITING ROTATION MODIFIER-16 */
{ RANGE_0WIDTH(0x1E000, 0x1E006) }, /* COMBINING GLAGOLITIC LETTER AZU - COMBINING GLAGOLITIC LETTER ZHIVETE */
{ RANGE_0WIDTH(0x1E008, 0x1E018) }, /* COMBINING GLAGOLITIC LETTER ZEMLJA - COMBINING GLAGOLITIC LETTER HERU */
{ RANGE_0WIDTH(0x1E01B, 0x1E021) }, /* COMBINING GLAGOLITIC LETTER SHTA - COMBINING GLAGOLITIC LETTER YATI */
{ RANGE_0WIDTH(0x1E023, 0x1E024) }, /* COMBINING GLAGOLITIC LETTER YU - COMBINING GLAGOLITIC LETTER SMALL YUS */
{ RANGE_0WIDTH(0x1E026, 0x1E02A) }, /* COMBINING GLAGOLITIC LETTER YO - COMBINING GLAGOLITIC LETTER FITA */
{ RANGE_0WIDTH(0x1E08F, 0x1E08F) }, /* COMBINING CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I */
{ RANGE_0WIDTH(0x1E130, 0x1E136) }, /* NYIAKENG PUACHUE HMONG TONE-B - NYIAKENG PUACHUE HMONG TONE-D */
{ RANGE_0WIDTH(0x1E2AE, 0x1E2AE) }, /* TOTO SIGN RISING TONE */
{ RANGE_0WIDTH(0x1E2EC, 0x1E2EF) }, /* WANCHO TONE TUP - WANCHO TONE KOINI */
{ RANGE_0WIDTH(0x1E4EC, 0x1E4EF) }, /* NAG MUNDARI SIGN MUHOR - NAG MUNDARI SIGN SUTUH */
{ RANGE_0WIDTH(0x1E5EE, 0x1E5EF) }, /* OL ONAL SIGN MU - OL ONAL SIGN IKIR */
{ RANGE_0WIDTH(0x1E8D0, 0x1E8D6) }, /* MENDE KIKAKUI COMBINING NUMBER TEENS - MENDE KIKAKUI COMBINING NUMBER MILLIONS */
{ RANGE_0WIDTH(0x1E944, 0x1E94A) }, /* ADLAM ALIF LENGTHENER - ADLAM NUKTA */
{ RANGE_2WIDTH(0x1F000, 0x1F02F) }, /* U+1F000 - U+1F02F */
{ RANGE_2WIDTH(0x1F0A0, 0x1F0FF) }, /* U+1F0A0 - U+1F0FF */
{ RANGE_2WIDTH(0x1F18E, 0x1F18E) }, /* NEGATIVE SQUARED AB */
{ RANGE_2WIDTH(0x1F191, 0x1F19A) }, /* SQUARED CL - SQUARED VS */
{ RANGE_2WIDTH(0x1F200, 0x1F202) }, /* SQUARE HIRAGANA HOKA - SQUARED KATAKANA SA */
{ RANGE_2WIDTH(0x1F210, 0x1F23B) }, /* SQUARED CJK UNIFIED IDEOGRAPH-624B - SQUARED CJK UNIFIED IDEOGRAPH-914D */
{ RANGE_2WIDTH(0x1F240, 0x1F248) }, /* TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-672C - TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-6557 */
{ RANGE_2WIDTH(0x1F250, 0x1F251) }, /* CIRCLED IDEOGRAPH ADVANTAGE - CIRCLED IDEOGRAPH ACCEPT */
{ RANGE_2WIDTH(0x1F260, 0x1F265) }, /* ROUNDED SYMBOL FOR FU - ROUNDED SYMBOL FOR CAI */
{ RANGE_2WIDTH(0x1F300, 0x1F3FA) }, /* CYCLONE - AMPHORA */
{ RANGE_0WIDTH(0x1F3FB, 0x1F3FF) }, /* EMOJI MODIFIER FITZPATRICK TYPE-1-2 - EMOJI MODIFIER FITZPATRICK TYPE-6 */
{ RANGE_2WIDTH(0x1F400, 0x1F64F) }, /* RAT - PERSON WITH FOLDED HANDS */
{ RANGE_2WIDTH(0x1F680, 0x1F9AF) }, /* ROCKET - PROBING CANE */
{ RANGE_0WIDTH(0x1F9B0, 0x1F9B3) }, /* EMOJI COMPONENT RED HAIR - EMOJI COMPONENT WHITE HAIR */
{ RANGE_2WIDTH(0x1F9B4, 0x1FAFF) }, /* U+1F9B4 - U+1FAFF */
{ RANGE_2WIDTH(0x20000, 0x2FFFD) }, /* U+20000 - U+2FFFD */
{ RANGE_2WIDTH(0x30000, 0x3FFFD) }, /* U+30000 - U+3FFFD */
{ RANGE_0WIDTH(0xE0001, 0xE0001) }, /* LANGUAGE TAG */
{ RANGE_0WIDTH(0xE0020, 0xE007F) }, /* TAG SPACE - CANCEL TAG */
{ RANGE_0WIDTH(0xE0100, 0xE01EF) }, /* VARIATION SELECTOR-17 - VARIATION SELECTOR-256 */
};
+806
View File
@@ -0,0 +1,806 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Provide access to virtual console memory.
* /dev/vcs: the screen as it is being viewed right now (possibly scrolled)
* /dev/vcsN: the screen of /dev/ttyN (1 <= N <= 63)
* [minor: N]
*
* /dev/vcsaN: idem, but including attributes, and prefixed with
* the 4 bytes lines,columns,x,y (as screendump used to give).
* Attribute/character pair is in native endianity.
* [minor: N+128]
*
* /dev/vcsuN: similar to /dev/vcsaN but using 4-byte unicode values
* instead of 1-byte screen glyph values.
* [minor: N+64]
*
* /dev/vcsuaN: same idea as /dev/vcsaN for unicode (not yet implemented).
*
* This replaces screendump and part of selection, so that the system
* administrator can control access using file system permissions.
*
* aeb@cwi.nl - efter Friedas begravelse - 950211
*
* machek@k332.feld.cvut.cz - modified not to send characters to wrong console
* - fixed some fatal off-by-one bugs (0-- no longer == -1 -> looping and looping and looping...)
* - making it shorter - scr_readw are macros which expand in PRETTY long code
*/
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/errno.h>
#include <linux/export.h>
#include <linux/tty.h>
#include <linux/interrupt.h>
#include <linux/mm.h>
#include <linux/init.h>
#include <linux/vt_kern.h>
#include <linux/selection.h>
#include <linux/kbd_kern.h>
#include <linux/console.h>
#include <linux/device.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/poll.h>
#include <linux/signal.h>
#include <linux/slab.h>
#include <linux/notifier.h>
#include <linux/uaccess.h>
#include <asm/byteorder.h>
#include <linux/unaligned.h>
#define HEADER_SIZE 4u
#define CON_BUF_SIZE (IS_ENABLED(CONFIG_BASE_SMALL) ? 256 : PAGE_SIZE)
DEFINE_FREE(free_page_ptr, void *, if (_T) free_page((unsigned long)_T));
/*
* Our minor space:
*
* 0 ... 63 glyph mode without attributes
* 64 ... 127 unicode mode without attributes
* 128 ... 191 glyph mode with attributes
* 192 ... 255 unused (reserved for unicode with attributes)
*
* This relies on MAX_NR_CONSOLES being <= 63, meaning 63 actual consoles
* with minors 0, 64, 128 and 192 being proxies for the foreground console.
*/
#if MAX_NR_CONSOLES > 63
#warning "/dev/vcs* devices may not accommodate more than 63 consoles"
#endif
#define console(inode) (iminor(inode) & 63)
#define use_unicode(inode) (iminor(inode) & 64)
#define use_attributes(inode) (iminor(inode) & 128)
struct vcs_poll_data {
struct notifier_block notifier;
unsigned int cons_num;
int event;
wait_queue_head_t waitq;
struct fasync_struct *fasync;
};
static int
vcs_notifier(struct notifier_block *nb, unsigned long code, void *_param)
{
struct vt_notifier_param *param = _param;
struct vc_data *vc = param->vc;
struct vcs_poll_data *poll =
container_of(nb, struct vcs_poll_data, notifier);
int currcons = poll->cons_num;
int fa_band;
switch (code) {
case VT_UPDATE:
fa_band = POLL_PRI;
break;
case VT_DEALLOCATE:
fa_band = POLL_HUP;
break;
default:
return NOTIFY_DONE;
}
if (currcons == 0)
currcons = fg_console;
else
currcons--;
if (currcons != vc->vc_num)
return NOTIFY_DONE;
poll->event = code;
wake_up_interruptible(&poll->waitq);
kill_fasync(&poll->fasync, SIGIO, fa_band);
return NOTIFY_OK;
}
static void
vcs_poll_data_free(struct vcs_poll_data *poll)
{
unregister_vt_notifier(&poll->notifier);
kfree(poll);
}
static struct vcs_poll_data *
vcs_poll_data_get(struct file *file)
{
struct vcs_poll_data *poll = file->private_data, *kill = NULL;
if (poll)
return poll;
poll = kzalloc_obj(*poll);
if (!poll)
return NULL;
poll->cons_num = console(file_inode(file));
init_waitqueue_head(&poll->waitq);
poll->notifier.notifier_call = vcs_notifier;
/*
* In order not to lose any update event, we must pretend one might
* have occurred before we have a chance to register our notifier.
* This is also how user space has come to detect which kernels
* support POLLPRI on /dev/vcs* devices i.e. using poll() with
* POLLPRI and a zero timeout.
*/
poll->event = VT_UPDATE;
if (register_vt_notifier(&poll->notifier) != 0) {
kfree(poll);
return NULL;
}
/*
* This code may be called either through ->poll() or ->fasync().
* If we have two threads using the same file descriptor, they could
* both enter this function, both notice that the structure hasn't
* been allocated yet and go ahead allocating it in parallel, but
* only one of them must survive and be shared otherwise we'd leak
* memory with a dangling notifier callback.
*/
spin_lock(&file->f_lock);
if (!file->private_data) {
file->private_data = poll;
} else {
/* someone else raced ahead of us */
kill = poll;
poll = file->private_data;
}
spin_unlock(&file->f_lock);
if (kill)
vcs_poll_data_free(kill);
return poll;
}
/**
* vcs_vc - return VC for @inode
* @inode: inode for which to return a VC
* @viewed: returns whether this console is currently foreground (viewed)
*
* Must be called with console_lock.
*/
static struct vc_data *vcs_vc(struct inode *inode, bool *viewed)
{
unsigned int currcons = console(inode);
WARN_CONSOLE_UNLOCKED();
if (currcons == 0) {
currcons = fg_console;
if (viewed)
*viewed = true;
} else {
currcons--;
if (viewed)
*viewed = false;
}
return vc_cons[currcons].d;
}
/**
* vcs_size - return size for a VC in @vc
* @vc: which VC
* @attr: does it use attributes?
* @unicode: is it unicode?
*
* Must be called with console_lock.
*/
static int vcs_size(const struct vc_data *vc, bool attr, bool unicode)
{
int size;
WARN_CONSOLE_UNLOCKED();
size = vc->vc_rows * vc->vc_cols;
if (attr) {
if (unicode)
return -EOPNOTSUPP;
size = 2 * size + HEADER_SIZE;
} else if (unicode)
size *= 4;
return size;
}
static loff_t vcs_lseek(struct file *file, loff_t offset, int orig)
{
struct inode *inode = file_inode(file);
struct vc_data *vc;
int size;
scoped_guard(console_lock) {
vc = vcs_vc(inode, NULL);
if (!vc)
return -ENXIO;
size = vcs_size(vc, use_attributes(inode), use_unicode(inode));
}
if (size < 0)
return size;
return fixed_size_llseek(file, offset, orig, size);
}
static int vcs_read_buf_uni(struct vc_data *vc, char *con_buf,
unsigned int pos, unsigned int count, bool viewed)
{
unsigned int nr, row, col, maxcol = vc->vc_cols;
int ret;
ret = vc_uniscr_check(vc);
if (ret)
return ret;
pos /= 4;
row = pos / maxcol;
col = pos % maxcol;
nr = maxcol - col;
do {
if (nr > count / 4)
nr = count / 4;
vc_uniscr_copy_line(vc, con_buf, viewed, row, col, nr);
con_buf += nr * 4;
count -= nr * 4;
row++;
col = 0;
nr = maxcol;
} while (count);
return 0;
}
static void vcs_read_buf_noattr(const struct vc_data *vc, char *con_buf,
unsigned int pos, unsigned int count, bool viewed)
{
u16 *org;
unsigned int col, maxcol = vc->vc_cols;
org = screen_pos(vc, pos, viewed);
col = pos % maxcol;
pos += maxcol - col;
while (count-- > 0) {
*con_buf++ = (vcs_scr_readw(vc, org++) & 0xff);
if (++col == maxcol) {
org = screen_pos(vc, pos, viewed);
col = 0;
pos += maxcol;
}
}
}
static unsigned int vcs_read_buf(const struct vc_data *vc, char *con_buf,
unsigned int pos, unsigned int count, bool viewed,
unsigned int *skip)
{
u16 *org, *con_buf16;
unsigned int col, maxcol = vc->vc_cols;
unsigned int filled = count;
if (pos < HEADER_SIZE) {
/* clamp header values if they don't fit */
con_buf[0] = min(vc->vc_rows, 0xFFu);
con_buf[1] = min(vc->vc_cols, 0xFFu);
getconsxy(vc, con_buf + 2);
*skip += pos;
count += pos;
if (count > CON_BUF_SIZE) {
count = CON_BUF_SIZE;
filled = count - pos;
}
/* Advance state pointers and move on. */
count -= min(HEADER_SIZE, count);
pos = HEADER_SIZE;
con_buf += HEADER_SIZE;
/* If count >= 0, then pos is even... */
} else if (pos & 1) {
/*
* Skip first byte for output if start address is odd. Update
* region sizes up/down depending on free space in buffer.
*/
(*skip)++;
if (count < CON_BUF_SIZE)
count++;
else
filled--;
}
if (!count)
return filled;
pos -= HEADER_SIZE;
pos /= 2;
col = pos % maxcol;
org = screen_pos(vc, pos, viewed);
pos += maxcol - col;
/*
* Buffer has even length, so we can always copy character + attribute.
* We do not copy last byte to userspace if count is odd.
*/
count = (count + 1) / 2;
con_buf16 = (u16 *)con_buf;
while (count) {
*con_buf16++ = vcs_scr_readw(vc, org++);
count--;
if (++col == maxcol) {
org = screen_pos(vc, pos, viewed);
col = 0;
pos += maxcol;
}
}
return filled;
}
static ssize_t
vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{
struct inode *inode = file_inode(file);
struct vc_data *vc;
struct vcs_poll_data *poll;
unsigned int read;
ssize_t ret;
loff_t pos;
bool viewed, attr, uni_mode;
char *con_buf __free(free_page_ptr) = (char *)__get_free_page(GFP_KERNEL);
if (!con_buf)
return -ENOMEM;
pos = *ppos;
/* Select the proper current console and verify
* sanity of the situation under the console lock.
*/
guard(console_lock)();
uni_mode = use_unicode(inode);
attr = use_attributes(inode);
if (pos < 0)
return -EINVAL;
/* we enforce 32-bit alignment for pos and count in unicode mode */
if (uni_mode && (pos | count) & 3)
return -EINVAL;
poll = file->private_data;
if (count && poll)
poll->event = 0;
read = 0;
ret = 0;
while (count) {
unsigned int this_round, skip = 0;
int size;
vc = vcs_vc(inode, &viewed);
if (!vc) {
ret = -ENXIO;
break;
}
/* Check whether we are above size each round,
* as copy_to_user at the end of this loop
* could sleep.
*/
size = vcs_size(vc, attr, uni_mode);
if (size < 0) {
ret = size;
break;
}
if (pos >= size)
break;
if (count > size - pos)
count = size - pos;
this_round = count;
if (this_round > CON_BUF_SIZE)
this_round = CON_BUF_SIZE;
/* Perform the whole read into the local con_buf.
* Then we can drop the console spinlock and safely
* attempt to move it to userspace.
*/
if (uni_mode) {
ret = vcs_read_buf_uni(vc, con_buf, pos, this_round,
viewed);
if (ret)
break;
} else if (!attr) {
vcs_read_buf_noattr(vc, con_buf, pos, this_round,
viewed);
} else {
this_round = vcs_read_buf(vc, con_buf, pos, this_round,
viewed, &skip);
}
/* Finally, release the console semaphore while we push
* all the data to userspace from our temporary buffer.
*
* AKPM: Even though it's a semaphore, we should drop it because
* the pagefault handling code may want to call printk().
*/
console_unlock();
ret = copy_to_user(buf, con_buf + skip, this_round);
console_lock();
if (ret) {
read += this_round - ret;
ret = -EFAULT;
break;
}
buf += this_round;
pos += this_round;
read += this_round;
count -= this_round;
}
*ppos += read;
if (read)
return read;
return ret;
}
static u16 *vcs_write_buf_noattr(struct vc_data *vc, const char *con_buf,
unsigned int pos, unsigned int count, bool viewed, u16 **org0)
{
u16 *org;
unsigned int col, maxcol = vc->vc_cols;
*org0 = org = screen_pos(vc, pos, viewed);
col = pos % maxcol;
pos += maxcol - col;
while (count > 0) {
unsigned char c = *con_buf++;
count--;
vcs_scr_writew(vc,
(vcs_scr_readw(vc, org) & 0xff00) | c, org);
org++;
if (++col == maxcol) {
org = screen_pos(vc, pos, viewed);
col = 0;
pos += maxcol;
}
}
return org;
}
/*
* Compilers (gcc 10) are unable to optimize the swap in cpu_to_le16. So do it
* the poor man way.
*/
static inline u16 vc_compile_le16(u8 hi, u8 lo)
{
#ifdef __BIG_ENDIAN
return (lo << 8u) | hi;
#else
return (hi << 8u) | lo;
#endif
}
static u16 *vcs_write_buf(struct vc_data *vc, const char *con_buf,
unsigned int pos, unsigned int count, bool viewed, u16 **org0)
{
u16 *org;
unsigned int col, maxcol = vc->vc_cols;
unsigned char c;
/* header */
if (pos < HEADER_SIZE) {
char header[HEADER_SIZE];
getconsxy(vc, header + 2);
while (pos < HEADER_SIZE && count > 0) {
count--;
header[pos++] = *con_buf++;
}
if (!viewed)
putconsxy(vc, header + 2);
}
if (!count)
return NULL;
pos -= HEADER_SIZE;
col = (pos/2) % maxcol;
*org0 = org = screen_pos(vc, pos/2, viewed);
/* odd pos -- the first single character */
if (pos & 1) {
count--;
c = *con_buf++;
vcs_scr_writew(vc, vc_compile_le16(c, vcs_scr_readw(vc, org)),
org);
org++;
pos++;
if (++col == maxcol) {
org = screen_pos(vc, pos/2, viewed);
col = 0;
}
}
pos /= 2;
pos += maxcol - col;
/* even pos -- handle attr+character pairs */
while (count > 1) {
unsigned short w;
w = get_unaligned(((unsigned short *)con_buf));
vcs_scr_writew(vc, w, org++);
con_buf += 2;
count -= 2;
if (++col == maxcol) {
org = screen_pos(vc, pos, viewed);
col = 0;
pos += maxcol;
}
}
if (!count)
return org;
/* odd pos -- the remaining character */
c = *con_buf++;
vcs_scr_writew(vc, vc_compile_le16(vcs_scr_readw(vc, org) >> 8, c),
org);
return org;
}
static ssize_t
vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
{
struct inode *inode = file_inode(file);
struct vc_data *vc;
u16 *org0, *org;
unsigned int written;
int size;
ssize_t ret;
loff_t pos;
bool viewed, attr;
if (use_unicode(inode))
return -EOPNOTSUPP;
char *con_buf __free(free_page_ptr) = (char *)__get_free_page(GFP_KERNEL);
if (!con_buf)
return -ENOMEM;
pos = *ppos;
/* Select the proper current console and verify
* sanity of the situation under the console lock.
*/
guard(console_lock)();
attr = use_attributes(inode);
vc = vcs_vc(inode, &viewed);
if (!vc)
return -ENXIO;
size = vcs_size(vc, attr, false);
if (size < 0)
return size;
if (pos < 0 || pos > size)
return -EINVAL;
if (count > size - pos)
count = size - pos;
written = 0;
while (count) {
unsigned int this_round = count;
if (this_round > CON_BUF_SIZE)
this_round = CON_BUF_SIZE;
/* Temporarily drop the console lock so that we can read
* in the write data from userspace safely.
*/
console_unlock();
ret = copy_from_user(con_buf, buf, this_round);
console_lock();
if (ret) {
this_round -= ret;
if (!this_round) {
/* Abort loop if no data were copied. Otherwise
* fail with -EFAULT.
*/
if (written)
break;
return -EFAULT;
}
}
/* The vc might have been freed or vcs_size might have changed
* while we slept to grab the user buffer, so recheck.
* Return data written up to now on failure.
*/
vc = vcs_vc(inode, &viewed);
if (!vc) {
if (written)
break;
return -ENXIO;
}
size = vcs_size(vc, attr, false);
if (size < 0) {
if (written)
break;
return size;
}
if (pos >= size)
break;
if (this_round > size - pos)
this_round = size - pos;
/* OK, now actually push the write to the console
* under the lock using the local kernel buffer.
*/
if (attr)
org = vcs_write_buf(vc, con_buf, pos, this_round,
viewed, &org0);
else
org = vcs_write_buf_noattr(vc, con_buf, pos, this_round,
viewed, &org0);
count -= this_round;
written += this_round;
buf += this_round;
pos += this_round;
if (org)
update_region(vc, (unsigned long)(org0), org - org0);
}
*ppos += written;
ret = written;
if (written && vc)
vcs_scr_updated(vc);
return ret;
}
static __poll_t
vcs_poll(struct file *file, poll_table *wait)
{
struct vcs_poll_data *poll = vcs_poll_data_get(file);
__poll_t ret = DEFAULT_POLLMASK|EPOLLERR;
if (poll) {
poll_wait(file, &poll->waitq, wait);
switch (poll->event) {
case VT_UPDATE:
ret = DEFAULT_POLLMASK|EPOLLPRI;
break;
case VT_DEALLOCATE:
ret = DEFAULT_POLLMASK|EPOLLHUP|EPOLLERR;
break;
case 0:
ret = DEFAULT_POLLMASK;
break;
}
}
return ret;
}
static int
vcs_fasync(int fd, struct file *file, int on)
{
struct vcs_poll_data *poll = file->private_data;
if (!poll) {
/* don't allocate anything if all we want is disable fasync */
if (!on)
return 0;
poll = vcs_poll_data_get(file);
if (!poll)
return -ENOMEM;
}
return fasync_helper(fd, file, on, &poll->fasync);
}
static int
vcs_open(struct inode *inode, struct file *filp)
{
unsigned int currcons = console(inode);
bool attr = use_attributes(inode);
bool uni_mode = use_unicode(inode);
/* we currently don't support attributes in unicode mode */
if (attr && uni_mode)
return -EOPNOTSUPP;
guard(console_lock)();
if (currcons && !vc_cons_allocated(currcons - 1))
return -ENXIO;
return 0;
}
static int vcs_release(struct inode *inode, struct file *file)
{
struct vcs_poll_data *poll = file->private_data;
if (poll)
vcs_poll_data_free(poll);
return 0;
}
static const struct file_operations vcs_fops = {
.llseek = vcs_lseek,
.read = vcs_read,
.write = vcs_write,
.poll = vcs_poll,
.fasync = vcs_fasync,
.open = vcs_open,
.release = vcs_release,
};
static const struct class vc_class = {
.name = "vc",
};
void vcs_make_sysfs(int index)
{
device_create(&vc_class, NULL, MKDEV(VCS_MAJOR, index + 1), NULL, "vcs%u", index + 1);
device_create(&vc_class, NULL, MKDEV(VCS_MAJOR, index + 65), NULL, "vcsu%u", index + 1);
device_create(&vc_class, NULL, MKDEV(VCS_MAJOR, index + 129), NULL, "vcsa%u", index + 1);
}
void vcs_remove_sysfs(int index)
{
device_destroy(&vc_class, MKDEV(VCS_MAJOR, index + 1));
device_destroy(&vc_class, MKDEV(VCS_MAJOR, index + 65));
device_destroy(&vc_class, MKDEV(VCS_MAJOR, index + 129));
}
int __init vcs_init(void)
{
unsigned int i;
if (register_chrdev(VCS_MAJOR, "vcs", &vcs_fops))
panic("unable to get major %d for vcs device", VCS_MAJOR);
if (class_register(&vc_class))
panic("unable to create vc_class");
device_create(&vc_class, NULL, MKDEV(VCS_MAJOR, 0), NULL, "vcs");
device_create(&vc_class, NULL, MKDEV(VCS_MAJOR, 64), NULL, "vcsu");
device_create(&vc_class, NULL, MKDEV(VCS_MAJOR, 128), NULL, "vcsa");
for (i = 0; i < MIN_NR_CONSOLES; i++)
vcs_make_sysfs(i);
return 0;
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff