diff options
Diffstat (limited to 'gen-pc-fkeys.pl')
-rwxr-xr-x | gen-pc-fkeys.pl | 364 |
1 files changed, 364 insertions, 0 deletions
diff --git a/gen-pc-fkeys.pl b/gen-pc-fkeys.pl new file mode 100755 index 0000000..1cc5b47 --- /dev/null +++ b/gen-pc-fkeys.pl @@ -0,0 +1,364 @@ +#! /usr/bin/perl -w +# $XTermId: gen-pc-fkeys.pl,v 1.22 2007/11/30 23:03:55 tom Exp $ +# ----------------------------------------------------------------------------- +# this file is part of xterm +# +# Copyright 2004-2005,2007 by Thomas E. Dickey +# +# All Rights Reserved +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +# IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY +# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name(s) of the above copyright +# holders shall not be used in advertising or otherwise to promote the +# sale, use or other dealings in this Software without prior written +# authorization. +# ----------------------------------------------------------------------------- +# +# Construct a list of function-key definitions corresponding to xterm's +# Sun/PC keyboard. This uses ncurses' infocmp to obtain the strings (including +# extensions) to modify (and verify). +use strict; + +my($max_modifier, $terminfo); +my(@old_fkeys, $opt_fkeys, $min_fkeys, $max_fkeys); +my(%old_ckeys, $opt_ckeys, $min_ckeys, $max_ckeys); +my(%old_ekeys, $opt_ekeys, $min_ekeys, $max_ekeys); + +my(@ckey_names); +@ckey_names = ( + 'kcud1', 'kcub1', 'kcuf1', 'kcuu1', # 1 = no modifiers + 'kDN', 'kLFT', 'kRIT', 'kUP', # 2 = shift + # make_ckey_names() repeats this row, appending the modifier code + ); +my %ckey_names; +my(@ckey_known); +@ckey_known = ( + 'kind', 'kLFT', 'kRIT', 'kri', # 2 = shift (standard) + ); + +my(@ekey_names); +@ekey_names = ( + 'khome', 'kend', 'knp', 'kpp', 'kdch1', 'kich1', # 1 = no modifiers + 'kHOM', 'kEND', 'kNXT', 'kPRV', 'kDC', 'kIC', # 2 = shift + # make_ekey_names() repeats this row, appending the modifier code +); +my %ekey_names; + +$min_fkeys=12; # the number of "real" function keys on your keyboard +$max_fkeys=64; # the number of function-keys terminfo can support +$max_modifier=8; # modifier 1 + (1=shift, 2=alt, 4=control 8=meta) + +$min_ckeys=4; # the number of "real" cursor keys on your keyboard +$max_ckeys=($min_ckeys * ($max_modifier - 1)); + +$min_ekeys=6; # the number of "real" editing keys on your keyboard +$max_ekeys=($min_ekeys * ($max_modifier - 1)); + +$opt_ckeys=2; # xterm's modifyCursorKeys resource +$opt_ekeys=2; # xterm's modifyCursorKeys resource +$opt_fkeys=2; # xterm's modifyFunctionKeys resource +$terminfo="xterm-new"; # the terminfo entry to use + +# apply the given modifier to the terminfo string, return the result +sub modify_fkey($$$) { + my $code = $_[0]; + my $text = $_[1]; + my $opts = $_[2]; + if (not defined($text)) { + $text = ""; + } elsif ($code != 1) { + $text =~ s/\\EO/\\E\[/ if ($opts >= 1); + + my $piece = substr $text, 0, length ($text) - 1; + my $final = substr $text, length ($text) - 1; + my $check = substr $piece, length ($piece) - 1; + if ($check =~ /[0-9]/) { + $code = ";" . $code; + } elsif ( $check =~ /\[/ and $opts >= 2) { + $code = "1;" . $code; + } + if ( $opts >= 3 ) { + $code = ">" . $code; + } + $text = $piece . $code . $final; + $text =~ s/([\d;]+)>/>$1/; + } + return $text; +} + +# compute the next modifier value - +# Cycling through the modifiers is not just like counting. Users prefer +# pressing one modifier (even if using Emacs). So first we cycle through +# the individual modifiers, then for completeness two, three, etc. +sub next_modifier { + my $code = $_[0]; + my $mask = $code - 1; + if ($mask == 0) { + $mask = 1; # shift + } elsif ($mask == 1) { + $mask = 4; # control + } elsif ($mask == 2) { + $mask = 3; # shift+alt + } elsif ($mask == 4) { + $mask = 5; # shift+control + } elsif ($mask == 5) { + $mask = 2; # alt + } + # printf ("# next_modifier(%d) = %d\n", $code, $mask + 1); + return $mask + 1; +} + +sub make_ckey_names() { + my ($j, $k); + my $min = $min_ckeys * 2; + my $max = $max_ckeys - 1; + + # printf "# make_ckey_names\n"; + for $j ($min..$max) { + $k = 1 + substr($j / $min_ckeys, 0, 1); + $ckey_names[$j] = $ckey_names[$min_ckeys + ($j % $min_ckeys)] . $k; + # printf "# make %d:%s\n", $j, $ckey_names[$j]; + } + for $j (0..$#ckey_names) { + # printf "# %d:%s\n", $j, $ckey_names[$j]; + $ckey_names{$ckey_names[$j]} = $j; + } +} + +sub make_ekey_names() { + my ($j, $k); + my $min = $min_ekeys * 2; + my $max = $max_ekeys - 1; + + # printf "# make_ekey_names\n"; + for $j ($min..$max) { + $k = 1 + substr($j / $min_ekeys, 0, 1); + $ekey_names[$j] = $ekey_names[$min_ekeys + ($j % $min_ekeys)] . $k; + # printf "# make %d:%s\n", $j, $ekey_names[$j]; + } + for $j (0..$#ekey_names) { + # printf "# %d:%s\n", $j, $ekey_names[$j]; + $ekey_names{$ekey_names[$j]} = $j; + } +} + +# Read the terminfo entry's list of function keys $old_fkeys[]. +# We could handle $old_fkeys[0], but choose to start numbering from 1. +sub readterm($) { + my $term = $_[0]; + my($key, $n, $str); + my(@list) = `infocmp -x -1 $term`; + + for $n (0..$#list) { + chop $list[$n]; + $list[$n] =~ s/^[[:space:]]//; + + $key = $list[$n]; + $key =~ s/=.*//; + + $str = $list[$n]; + $str =~ s/^[^=]+=//; + $str =~ s/,$//; + + if ( $list[$n] =~ /^kf[[:digit:]]+=/ ) { + $key =~ s/^kf//; + # printf "# $n:%s(%d)(%s)\n", $list[$n], $key, $str; + $old_fkeys[$key] = $str; + } elsif ( $key =~ /^kc[[:alpha:]]+1/ + or $key =~ /^k(LFT|RIT|UP|DN)\d?/) { + # printf "# $n:%s(%d)(%s)\n", $list[$n], $key, $str; + $old_ckeys{$key} = $str; + } elsif ( defined $ekey_names{$key} ) { + # printf "# $n:%s(%s)(%s)\n", $list[$n], $key, $str; + $old_ekeys{$key} = $str; + } + } + # printf ("last index:%d\n", $#old_fkeys); +} + +# read the whole terminfo to ensure we get the non-modified stuff, then read +# the part that contains modifiers. +sub read_part($) { + my $part = $_[0]; + + %old_ckeys = (); + @old_fkeys = (); + readterm($terminfo); + readterm($part); +} + +sub nameof_ckeys($) { + my $opts = $_[0]; + my $optname = "xterm+pcc" . ($opts >= 0 ? $opts : "n"); + return $optname; +} + +sub generate_ckeys($) { + my $opts = $_[0]; + my($modifier, $cur_ckey, $index); + + printf "%s|fragment with modifyCursorKeys:%s,\n", + nameof_ckeys($opts), $opts; + + # show the standard cursor definitions + $modifier = 1; + for ($index = 0; $index < $min_ckeys; ++$index) { + $cur_ckey = $index + ($modifier * $min_ckeys); + my $name = $ckey_known[$index]; + my $input = $old_ckeys{$ckey_names[$index]}; + my $result = modify_fkey($modifier + 1, $input, $opts); + printf "\t%s=%s,\n", $name, $result; + if (defined $old_ckeys{$name}) { + if ($old_ckeys{$name} ne $result) { + printf "# found %s=%s\n", $name, $old_ckeys{$name}; + } + } + } + + # show the extended cursor definitions + for ($index = 0; $index < $min_ckeys; ++$index) { + for ($modifier = 1; $modifier < $max_modifier; ++$modifier) { + $cur_ckey = $index + ($modifier * $min_ckeys); + if (defined $ckey_names[$cur_ckey] and + $ckey_names[$cur_ckey] ne "kLFT" and + $ckey_names[$cur_ckey] ne "kRIT" ) { + my $name = $ckey_names[$cur_ckey]; + my $input = $old_ckeys{$ckey_names[$index]}; + my $result = modify_fkey($modifier + 1, $input, $opts); + printf "\t%s=%s,\n", $name, $result; + if (defined $old_ckeys{$name}) { + if ($old_ckeys{$name} ne $result) { + printf "# found %s=%s\n", $name, $old_ckeys{$name}; + } + } + } + } + } +} + +sub nameof_ekeys($) { + my $opts = $_[0]; + my $optname = "xterm+pce" . ($opts >= 0 ? $opts : "n"); + return $optname; +} + +sub generate_ekeys($) { + my $opts = $_[0]; + my($modifier, $cur_ekey, $index); + + printf "%s|fragment with modifyCursorKeys:%s,\n", + nameof_ekeys($opts), $opts; + + for ($index = 0; $index < $min_ekeys; ++$index) { + for ($modifier = 1; $modifier < $max_modifier; ++$modifier) { + $cur_ekey = $index + ($modifier * $min_ekeys); + if (defined $ekey_names[$cur_ekey] ) { + my $name = $ekey_names[$cur_ekey]; + my $input = $old_ekeys{$ekey_names[$index]}; + my $result = modify_fkey($modifier + 1, $input, $opts); + printf "\t%s=%s,\n", $name, $result; + if (defined $old_ekeys{$name}) { + if ($old_ekeys{$name} ne $result) { + printf "# found %s=%s\n", $name, $old_ekeys{$name}; + } + } + } + } + } +} + +sub nameof_fkeys($) { + my $opts = $_[0]; + my $optname = "xterm+pcf" . ($opts >= 0 ? $opts : "n"); + return $optname; +} + +sub generate_fkeys($) { + my $opts = $_[0]; + my($modifier, $cur_fkey); + + printf "%s|fragment with modifyFunctionKeys:%s and ctrlFKeys:10,\n", + nameof_fkeys($opts), $opts; + + for ($cur_fkey = 1, $modifier = 1; $cur_fkey < $max_fkeys; ++$cur_fkey) { + my $index = (($cur_fkey - 1) % $min_fkeys); + if ($index == 0 && $cur_fkey != 1) { + $modifier = next_modifier($modifier); + } + if (defined $old_fkeys[$index + 1]) { + my $input = $old_fkeys[$index + 1]; + my $result = modify_fkey($modifier, $input, $opts); + printf "\tkf%d=%s,\n", $cur_fkey, $result; + if (defined $old_fkeys[$cur_fkey]) { + if ($old_fkeys[$cur_fkey] ne $result) { + printf "# found kf%d=%s\n", $cur_fkey, $old_fkeys[$cur_fkey]; + } + } + } + } +} + +sub show_default() { + readterm($terminfo); + + printf "xterm+pcfkeys|fragment for PC-style keys,\n"; + printf "\tuse=%s,\n", nameof_ckeys($opt_ckeys); + printf "\tuse=%s,\n", nameof_ekeys($opt_ekeys); + printf "\tuse=%s,\n", nameof_fkeys($opt_fkeys); + + generate_ckeys($opt_ckeys); + generate_ekeys($opt_ekeys); + generate_fkeys($opt_fkeys); +} + +sub show_nondefault() +{ + my $opts; + + for ($opts = 0; $opts <= 3; ++$opts) { + if ($opts != $opt_ckeys) { + read_part(nameof_ckeys($opts)); + generate_ckeys($opts); + } + } + + for ($opts = 0; $opts <= 3; ++$opts) { + if ($opts != $opt_ekeys) { + read_part(nameof_ekeys($opts)); + generate_ekeys($opts); + } + } + + for ($opts = 0; $opts <= 3; ++$opts) { + if ($opts != $opt_fkeys) { + read_part(nameof_fkeys($opts)); + generate_fkeys($opts); + } + } +} + +make_ckey_names(); +make_ekey_names(); + +printf "# gen-pc-fkeys.pl\n"; +printf "# %s:timode\n", "vile"; +show_default(); +show_nondefault(); |