view release on metacpan or search on metacpan
examples/izKeys.kbdd view on Meta::CPAN
/SLASH= â÷â / ËË / / / â̸ âÌ· â̶ â̵ / / ââ ââ / â̸ Ì· ââ ââ̶ â̵
#
# These are from "main blocks" of the modifiers and combining; plus Greek standalone diacritics: ͺÎÎ
# One of Ë is obscured by vertical line with middle dot... The Macron-\ 29F7 obscures Ë.
# Circled \ and | with middle dot obscure ËË . Ë duplicated (forward) to make accessible. Also: âÌ
# â̾ Ì Ì Íâ Í Í á·½ combining chars are also duplicated. Also: â¡ â â ⯠⮠⬠â (for symbols).
# ʰʱʲˡˢʷ - from IPA. The rest (and ʳʴʵʶʸ) are v1.1 letter modifiers. (Ë is in front to unobscure the rest.)
#
# Combining for symbols: arrows and round arrows -> ~; rectangular around: to Ë .
#`´¨ËË˰¯ Harpoons are ordered as â, â
# perl -C31 -wlne "next if /^#/; s(^/\w+=\s+)() or die; @t = split m((?<=.)/); print q(<tr><td>), join(q(</td><td>), @t), q(</td></tr>)" a1 > a1.html
[face_shortcuts]
l=Latin
c=CyrillicPhonetic
g=GreekPoly
h=Hebrew
b=US-Base
lib/UI/KeyboardLayout.pm view on Meta::CPAN
# actually: parses configfile string, not file
sub parse_configfile ($$) { # Trailing whitespace is ignored, whitespace about "=" is not
my ($self, $s) = (shift, shift);
$self->parse_add_configstring($s, {});
}
sub parse_add_configstring ($$$) { # Trailing whitespace is ignored, whitespace about "=" is not
my ($self, $s, $vv, @KEYS) = (shift, shift, shift);
$s =~ s/[^\S\n]+$//gm;
$s =~ s/^\x{FEFF}//; # BOM are not stripped by Perl from UTF-8 files with -C31
(my $pre, my %f) = split m(^\[((?:visual\s*->\s*)?[\w/]*)\]\s*$ \n?)mx, $s; # //x is needed to avoid $\
warn "Part before the first section in configfile ignored: `$pre'" if length $pre;
for my $k (sort keys %f) {
# warn "Section `$k'";
my($v, $V, @V) = $f{$k};
if ($k =~ s{^visual\s*->\s*}{[unparsed]/}) { # Make sure that prefixes do not allow visual line to be confused with a config
$v =~ s[(^(?!#|[/\@+]?\w+=).*)]//ms; # find non-comment non-assignment
@V = "unparsed_data=$1";
}
# warn "xxx: @V";
push @KEYS, $k;
my @k = split m(/), $k;
@k = () if "@k" eq ''; # root
for my $l ((grep !/^#/, split(/\n/, $v)), @V) {
die "unrecognized config file line: `$l' in `$s'"
unless my($arr, $at, $slash, $kk, $vvv) = ($l =~ m[^((?:(\@)|(/)|\+)?)(\w+)=(.*)]s);
my $spl = $at ? qr/,/ : ( $slash ? qr[/] : qr[(?!)] );
$vvv = [ length $vvv ? (split $spl, $vvv, -1) : $vvv ] if $arr; # create empty element if $vvv is empty
my $slot = $self->get_deep($vv, @k);
if ($slot and exists $slot->{$kk}) {
if ($arr) {
if (ref($slot->{$kk} || 0) eq 'ARRAY') {
lib/UI/KeyboardLayout.pm view on Meta::CPAN
$name = "VisLr=$name" if $name;
# warn "Multi-char key in <<@k>>" if grep $_ && 1<length, @k;
warn "More that 2 Shift-states in <<@k>>" if @k > 2;
#warn "Sep2 in $name, $skip_first, <$k> ==> <@k>\n" if defined $sep2 and $k =~ /$sep2/;
map {defined() ? [$_, undef, undef, $name] : $_} @k;
# @k
} # -> list of chars
sub process_key ($$$$$$;$) { # $sep may appear only in a beginning of the first key chunk
my ($self, $k, $limit, $sep, $ln, $l_off, $sep2, @tr) = (shift, shift, shift, shift, shift, shift, shift);
my @k = split m((?!^)\Q$sep), $k;
die "Key descriptor `$k' separated by `$sep' has too many parts: expected $limit, got ", scalar @k
if @k > $limit;
defined $k[$_] and $k[$_] =~ s/^--(?=.)/\0/ and $tr[$_]++ for 0..$#k;
$k[0] = '' if $k[0] eq '--'; # Allow a filler (multi)-chunk
map [$self->process_key_chunk( $ln->[$l_off+$_], $tr[$_], (defined($k[$_]) ? $k[$_] : ''), $sep2)], 0..$#k;
} # -> list of arrays of chars
sub decode_kbd_layers ($@) {
my ($self, $lineN, $row, $line_in_row, $cur_layer, @out, $N, $l0) = (shift, 0, -1);
my %needed = qw(unparsed_data x visual_rowcount 2 visual_per_row_counts [2;2] visual_prefixes * prefix_repeat 3 in_key_separator / layer_names ???);
lib/UI/KeyboardLayout.pm view on Meta::CPAN
return $v->[$idx];
}
return;
}
sub fill_kbd_layers ($$) { # We do not do deep processing here...
my($self, $h, %o, %c, %O) = (shift, shift);
my @K = grep m(^\[unparsed]/(KBD|RECT)\b), @{$h->{'[keys]'}};
# my $H = $h->{'[unparsed]'};
for my $k (@K) {
my (@parts, @h) = split m(/), $k;
ref $self and push @h, $self->get_deep($self, @parts[1..$_]) || {} for 0..$#parts;
push @h, $self->get_deep($h, @parts[1..$_]) || {} for 0..$#parts; # Drop [unparsed]/ prefix...
push @h, $self->get_deep($h, @parts[0..$_]) || {} for -1..$#parts;
my ($in, $counts, $offsets) = ($k =~ m(^\[unparsed]/KBD\b) ? $self->decode_kbd_layers( reverse @h )
: $self->decode_rect_layers( reverse @h ) );
exists $o{$_} and die "Visual spec `$k' overwrites exiting layer `$k'" for keys %$in;
my $cnt = (@o{keys %$in} = values %$in);
@c{keys %$in} = ($counts) x $cnt;
@O{keys %$in} = ($offsets) x $cnt if $offsets;
}
lib/UI/KeyboardLayout.pm view on Meta::CPAN
for my $f ($self->order_faces_4_massage) { # Needed for (pre_)link_layers...
next if 'HASH' ne ref $self->{faces}{$f} or $f =~ m(\bVK$); # "parent" taking keys for a child
#warn "Massaging face `$f'...";
for my $key ( qw( Flip_AltGr_Key Diacritic_if_undef DeadChar_DefaultTranslation DeadChar_32bitTranslation extra_report_DeadChar
PrefixChains ctrl_after_modcol create_alpha_ctrl keep_missing_ctrl output_layers
output_layers_WIN output_layers_XKB skip_extra_layers_WIN Prefix_Base_Altern Prefix_Force_Altern
layers_modifiers layers_mods_keys mods_keys_KBD AltGrInv_AltGr_as_Ctrl
ComposeKey_Show AltGr_Invert_Show Apple_Override Apple_Duplicate Apple_HexInput
ComposeKey Explicit_AltGr_Invert Auto_Diacritic_Start CapsLOCKoverride
WindowsEmitDeadkeyDescrREX ExtraChars modkeys_vk) ) {
$self->{faces}{$f}{"[$key]"} = $self->get_deep_via_parents($self, undef, 'faces', (split m(/), $f), $key);
}
$self->{faces}{$f}{'[char2key_prefer_first]'}{$_}++ # Make a hash
for @{ $self->{faces}{$f}{char2key_prefer_first} || [] } ;
$self->{faces}{$f}{'[char2key_prefer_last]'}{$_}++ # Make a hash
for @{ $self->{faces}{$f}{char2key_prefer_last} || [] } ;
$self->{faces}{$f}{'[AltGrInv_AltGr_as_Ctrl]'} = 1 unless defined $self->{faces}{$f}{'[AltGrInv_AltGr_as_Ctrl]'};
my $idx = $self->get_deep($self, 'faces', (split m(/), $f), 'MetaData_Index');
# defined $self->{faces}{$f}{"[$_]"} and not ref $self->{faces}{$f}{"[$_]"}
# or
$self->{faces}{$f}{"[$_]"} = $self->get_deep_via_parents($self, $idx, 'faces', (split m(/), $f), $_)
for qw(LRM_RLM ALTGR SHIFTLOCK NOALTGR);
my %R = qw(ComposeKey_Show â AltGr_Invert_Show ⤨); # On Apple only
defined $self->{faces}{$f}{"[$_]"} or $self->{faces}{$f}{"[$_]"} = $R{$_} for keys %R;
$self->{faces}{$f}{"[ComposeKey_Show]"}[0] = 'â' # Make a safe default
if ref $self->{faces}{$f}{"[ComposeKey_Show]"} and not length $self->{faces}{$f}{"[ComposeKey_Show]"}[0];
my ($compK, %compK) = $self->{faces}{$f}{'[ComposeKey]'};
if ($compK and ref $compK) {
for my $cK (@$compK) {
lib/UI/KeyboardLayout.pm view on Meta::CPAN
push @{ $self->{faces}{$f}{'[AltSubstitutions]'}{lc $s[0]} }, [lc $s[1], 'manual']
if lc $s[0] ne $s[0] and lc $s[1] ne $s[1];
push @{ $self->{faces}{$f}{'[AltSubstitutions]'}{uc $s[0]} }, [uc $s[1], 'manual']
if uc $s[0] ne $s[0] and uc $s[1] ne $s[1];
}
s/^\s+//, s/\s+$//, $_ = $self->stringHEX2string($_) for @{ $self->{faces}{$f}{Import_Prefix_Keys} || []};
my %h = @{ $self->{faces}{$f}{Import_Prefix_Keys} || []};
$self->{faces}{$f}{'[imported2key]'} = \%h if %h;
my ($l0, $c);
unless ($c = $self->{layer_counts}{$l0 = $self->{faces}{$f}{layers}[0]}) {
$l0 = $self->get_deep_via_parents($self, undef, 'faces', (split m(/), $f), 'geometry_via_layer');
$c = $self->{layer_counts}{$l0} if defined $l0;
}
my $o = $self->{layer_offsets}{$l0} if defined $l0;
$self->{faces}{$f}{'[geometry]'} = $c if $c;
$self->{faces}{$f}{'[g_offsets]'} = $o if $o;
}
# $self->__dbg_latin_CtrlD;
for my $f ($self->order_faces_4_massage) { # Needed for face_make_backlinks: must know which keys in faces will be finally present
next if 'HASH' ne ref $self->{faces}{$f} or $f =~ m(\bVK$); # "parent" taking keys for a child
for my $F (@{ $self->{faces}{$f}{AlternCharSubstitutionFaces} || []}) { # Now has a chance to have real layers
lib/UI/KeyboardLayout.pm view on Meta::CPAN
#$self->{faces}{"$f###" . $self->key2hex($k[0])}{'[DEAD]'}{$k[1]}++;
}
}
# $self->__dbg_latin_CtrlD;
$self
}
sub massage_hash_values($) {
my($self) = (shift);
for my $K ( @{$self->{'[keys]'}} ) {
my $h = $self->get_deep($self, split m(/), $K);
$_ = $self->charhex2key($_) for @{ $h->{char2key_prefer_first} || []}, @{ $h->{char2key_prefer_last} || []};
}
}
#use Dumpvalue;
sub print_codepoint ($$;$$) { # $postfix may be a name of base-font. Then the coverage_how is used instead of $postfix
my ($self, $k, $prefix, $postfix) = (shift, shift, shift, shift);
my $K = ($k =~ /$rxCombining/ ? " $k" : $k);
if (defined $postfix) {
lib/UI/KeyboardLayout.pm view on Meta::CPAN
}
$self
}
sub massage_deadkeys_win ($$) {
my($self, $h, @process, @to) = (shift, shift);
my @K = grep m(^\[unparsed]/DEADKEYS\b), @{$h->{'[keys]'}};
# warn "Found deadkey sections `@K'";
# my $H = $h->{'[unparsed]'};
for my $k (@K) {
push @process, $self->get_deep($h, (split m(/), $k), 'unparsed_data');
(my $k1 = $k) =~ s(^\[unparsed]/)();
push @to, $k1
}
@K = grep m(^DEADKEYS\b), @{$h->{'[keys]'}};
for my $k (@K) {
my $slot = $self->get_deep($h, split m(/), $k);
next unless exists $slot->{klc_filename};
open my $fh, '< :encoding(UTF-16)', $slot->{klc_filename}
or die "open of <klc_filename>=`$slot->{klc_filename}' failed: $!";
local $/;
my $in = <$fh>;
push @process, $in;
push @to, $k;
}
for my $k1 (@to) {
#warn "DK sec `$k' -> `$v', <", join('> <', keys %{$h->{'[unparsed]'}{DEADKEYS}{la_ru}}), ">";
#warn "DK sec `$k' -> `$v', <$h->{'[unparsed]'}{DEADKEYS}{la_ru}{unparsed_data}>";
my $v = shift @process;
my($o,$d,$t) = $self->read_deadkeys_win($v); # Translation tables, names, rest of input
my (@parts, @h) = split m(/), $k1;
my %seen = (%$o, %$d);
for my $kk (keys %seen) {
#warn "DK sec `$k1', deadkey `$kk'. Map: ", $self->array2string( [%{$o->{$kk} || {}}] );
my $slot = $self->get_deep($h, @parts, $kk);
warn "Deadkey `$kk' defined for `$k1' conflicts with previous definition"
if $slot and grep exists $slot->{$_}, qw(map name);
$self->put_deep($h, $o->{$kk}, @parts, $kk, 'map') if exists $o->{$kk};
$self->put_deep($h, $d->{$kk}, @parts, $kk, 'name') if exists $d->{$kk};
}
}
lib/UI/KeyboardLayout.pm view on Meta::CPAN
MULTIPLY => [["*", "*"]],
DIVIDE => [["/", "/"]],
RETURN => [["\r", "\r"], ["\n"]],
BACK => [["\b", "\b"], ["\x7f"]],
ESCAPE => [["\e", "\e"], ["\e"]],
CANCEL => [["\cC", "\cC"], ["\cC"]],
);
sub get_VK ($$) {
my ($self, $f) = (shift, shift);
$self->get_deep_via_parents($self, undef, 'faces', (split m(/), $f), 'VK') || {}
# $self->{faces}{$f}{VK} || {}
}
my $min_sec;
sub last_pre_funckeys($$) {
my ($self, $l0) = (shift, shift);
unless (defined $min_sec) {
$min_sec = 1e300;
$min_sec > $_->[0] and $min_sec = $_->[0] for values %start_SEC;
}
lib/UI/KeyboardLayout.pm view on Meta::CPAN
uc => sub ($) {defined (my $c = shift) or return undef; $c = $c->[0] if 'ARRAY' eq ref $c;
my $c1 = uc $c; return undef if $c1 eq $c; $c1} );
sub make_translator ($$$$$) { # translator may take some values from "environment"
# (such as which deadkey is processed), so caching is tricky: if does -> $used_deadkey reflects this
# The translator should return exactly one value (possibly undef) so that map TRANSLATOR, list works intuitively.
# Exception: translator with all_layers: takes a ref to a key (array of arrays of chars); returns array of arrays.
# There is a possibility to redirect the translation to another key; see $cvt (usually combined with 'all_layers').
my ($self, $name, $deadkey, $face, $N, $used_deadkey) = (shift, shift, shift || 0, shift, shift, ''); # $deadkey used eg for diagnostics
die "Undefined recipe in a translator for face `$face', layer $N on deadkey `$deadkey'" unless defined $name;
if ($name =~ /^Imported\[([\/\w]+)(?:,([\da-fA-F]{4,}))?\]$/) {
my($d, @sec) = (($2 ? "$2" : undef), split m(/), "$1");
$d = $deadkey, $used_deadkey ="/$deadkey" unless defined $d;
my $fromKBDD = $self->get_deep($self, 'DEADKEYS', @sec, lc $d, 'map') # DEADKEYS/bepo with 00A4 ---> DEADKEYS/bepo/00a4
or die "DEADKEYS section for `$d' with parts `@sec' not found";
# indexed by lc hex
return sub { my $cc=my $c=shift; return $c unless defined $c; $c = $c->[0] if 'ARRAY' eq ref $c; defined($c = $fromKBDD->{$self->key2hex($c)}) or return $c; $self->document_char(chr hex $c, $name, $cc) }, '';
}
die "unrecognized Imported argument: `$1'" if $name =~ /^Imported(\[.*)/s;
return $translators{$name}, '' if $translators{$name};
if ($name =~ /^PrefixDocs\[(.+)\]$/) {
$self->{faces}{$face}{'[prefixDocs]'}{$deadkey} = $1;
lib/UI/KeyboardLayout.pm view on Meta::CPAN
# warn "geometry: [@$g] [@$o]";
for my $r (@$g) {
my $off = shift @$o;
$c{$tot + $_} = $_ + $off for 0..($r-1);
$tot += $r;
}
return sub ($$$$) { (undef, my ($L, $k, $shift)) = @_; return undef if $L or $shift or $k >= $tot; $self->document_char($chars[$c{$k}], "ByColumn[$c{$k}]") }, '';
}
if ($name =~ /^ByRows\[(.+)\]$/) {
s(^\s+(?!\s|///\s+))(), s((?<!\s)(?<!\s///)\s+$)() for my $recipes = $1;
my (@recipes, @subs) = split m(\s+///\s+), $recipes;
my $LL = $#{ $self->{faces}{$face}{layers} }; # Since all_layers, we are called only for layer 0; subrecipes may need more
for my $rec (@recipes) {
push(@subs, sub {return undef}), next unless length $rec;
#warn "recipe=`$rec'; face=`$face'; N=$N; deadkey=`$deadkey'; last_layer=$LL";
my ($tr) = $self->make_translator_for_layers( $rec, $deadkey, $face, [0..$LL] );
#warn " done";
push @subs, $tr;
}
my $g = $self->{faces}{$face}{'[geometry]'}
or die "Face `$face' has no associated layer with geometry info; did you set geometry_via_layer?";
lib/UI/KeyboardLayout.pm view on Meta::CPAN
}
if ($flat and not $N) {
die "<<<Flat>>> makes sense only in toplevel descriptions of satellite faces: <<<$in>>> in `$face´" unless $deadkey;
my $inv = $invert ? 'Inv' : '';
$self->{faces}{$face}{"[FlatPrefixMap$inv]"}{$deadkey}{$self->key2hex($_)}
= $self->document_char($Map{$_}, 'explicit flat tuneup') for keys %Map;
$used_deadkey = "/$deadkey";
}
return sub ($) { my $c = shift; defined $c or return $c; $c = $c->[0] if 'ARRAY' eq ref $c; $self->document_char($Map{$c}, 'explicit tuneup') }, $used_deadkey;
}
my $map = $self->get_deep($self, 'DEADKEYS', split m(/), $name);
die "Can't resolve character map `$name'" unless defined $map;
unless (exists $map->{map}) {{
my($k1) = keys %$map;
die "Character map `$name' does not contain HEX: `$k1'" if %$map and not $k1 =~ /^[0-9a-f]{4,}$/;
die "Character map is a parent-type map, but no deadkey to use specified" unless defined $deadkey;
my $Map = { map +(chr hex $_, $map->{$_}), keys %$map };
die "Character map `$name' does not contain `$deadkey', contains <", (join '> <', keys %$map), ">"
unless exists $Map->{chr hex $deadkey};
$map = $Map->{chr hex $deadkey}, $used_deadkey = "/$deadkey" if %$Map;
$map = {map => {}}, warn "Character map for `$name' empty" unless %$map;
lib/UI/KeyboardLayout.pm view on Meta::CPAN
} else {
$ARG = [map $self->{faces}{$face}{layers}[$_], @$NN];
$append = "#$face#";
}
[$self->make_translated_layers_tr($ARG, $recipe, $append, $deadkey, $face, $NN)]; # Either we saw (), or $recipe is not a face recipe!
}
sub massage_translated_layers ($$$$;$) {
my ($self, $in, $face, $NN, $deadkey) = (shift, shift, shift, shift, shift, '');
#warn "Massaging `$deadkey' for `$face':$N";
return $in unless my $r = $self->get_deep($self, 'faces', (my @p = split m(/), $face), '[Diacritic_if_undef]');
$r =~ s/^\s+//;
#warn " -> end recipe `$r'";
warn " mk_tr_lyrs 6" if debug_stacking_ord;
my $post = $self->make_translated_layers($r, $face, $NN, $deadkey);
warn " mk_tr_lyrs_st 1" if debug_stacking_ord;
return [$self->make_translated_layers_stack($in, $post)];
}
sub default_char ($$) {
my ($self, $F) = (shift, shift);
lib/UI/KeyboardLayout.pm view on Meta::CPAN
$recipe =~ s/^\s+//;
$recipe
}
sub scan_for_DeadKey_Maps ($) { # Makes a direct-access synonym, scan for DeadKey_Maps* keys
my ($self, %h, $expl) = (shift);
#Dumpvalue->new()->dumpValue($self);
my @F = grep m(^faces(/.*)?$), @{$self->{'[keys]'}};
for my $FF (@F) {
(my $F = $FF) =~ s(^faces/?)();
my(@FF, @HH) = split m(/), $FF;
next if @FF == 1 or $FF[-1] eq 'VK';
my @FF1 = @FF;
push(@HH, $self->get_deep($self, @FF1)), pop @FF1 while @FF1; # All the parents
my $H = $HH[0];
next if $H->{PartialFace};
$self->{faces}{$F} = $H if $F =~ m(/) and exists $H->{layers}; # Make a direct-access copy
#warn "Face section `${FF}'s parents: ", scalar @HH;
#warn "Mismatch of hashes for `$FF'" unless $self->{faces}{$F} == $H;
# warn "compositing: faces `$F'; -> <", (join '> <', %$H), ">";
lib/UI/KeyboardLayout.pm view on Meta::CPAN
}
}
$self
}
sub create_prefix_chains ($) {
my ($self, %h, $expl) = (shift);
my @F = grep m(^faces(/.*)?$), @{$self->{'[keys]'}};
for my $FF (@F) {
(my $F = $FF) =~ s(^faces/?)();
my(@FF, @HH) = split m(/), $FF;
next if @FF == 1 or $FF[-1] eq 'VK';
push(@HH, $self->get_deep($self, @FF)), pop @FF while @FF;
my($H, %KK) = $HH[0];
for my $chain ( @{ $H->{'[PrefixChains]'} || [] } ) {
(my $c = $chain) =~ s/^\s+//;
my @prefix = map { $_ and $self->charhex2key($_) } split /,/, $c, -1; # trailing empty means all are prefixes
length(my $trail_nonprefix = $prefix[-1]) or pop @prefix;
my $start = shift @prefix;
warn "PrefixChain for `$start' in font `$F' is empty" unless @prefix > 1;
for my $Kn (1..$#prefix) {
lib/UI/KeyboardLayout.pm view on Meta::CPAN
}
}
$self
}
sub link_composite_layers ($) { # as above, but finish
my ($self, %h, $expl) = (shift);
my @F = grep m(^faces(/.*)?$), @{$self->{'[keys]'}};
for my $FF (@F) {
(my $F = $FF) =~ s(^faces/?)();
my(@FF, @HH) = split m(/), $FF;
next if @FF == 1 or $FF[-1] eq 'VK';
push(@HH, $self->get_deep($self, @FF)), pop @FF while @FF;
my $H = $HH[0];
for my $new_facename (sort values %{$H->{'[deadkeyFace]'}}) {
#warn "Joining <$F>, <$new_facename>";
$self->link_layers($F, $new_facename, 'skipfix', 'no-slot-warn');
}
}
$self
}
lib/UI/KeyboardLayout.pm view on Meta::CPAN
}
$self
}
sub massage_flat_maps_extra_keys ($) {
my $self = shift;
my @F = grep m(^faces(/.*)?$), @{$self->{'[keys]'}};
my (@Fok, @Fok0, @Fnok);
for my $FF (@F) {
(my $F = $FF) =~ s(^faces/?)();
my(@FF, @HH, @FokF) = split m(/), $FF;
next if @FF == 1 or $FF[-1] eq 'VK';
push @Fok, $F; # Assumed base faces
my($H) = $self->get_deep($self, @FF);
my $Cov = $H->{'[coverageExtraInclPrefix]'};
## warn join ',', sort keys %$Cov;
for my $inv ('', 'Inv') {
for my $dead (sort keys %{$H->{"[FlatPrefixMap$inv]"}}) {
my($sk, @c) = ('');
for my $cHex (sort keys %{$H->{"[FlatPrefixMap$inv]"}{$dead}}) {
my $chr = $self->charhex2key($cHex);